C#开源爬虫NCrawler源代码解读以及将其移植到python3.2(3)
在将程序移植到python之前,先来复习一下python的多线程编程的相关知识。
请看下面的一段代码:
import time import threading import urllib.request import queue class ThreadUrl(threading.Thread): def __init__(self,q,name): threading.Thread.__init__(self) self.q = q self.name=name def run(self): host = self.q.get() url = urllib.request.urlopen(host) url.read() print('thread '+self.name+' is done') self.q.task_done() def mutlithread(): q = queue.Queue() ts=[] for i in range(5): ts.append(ThreadUrl(q,i)) for i in range(5): ts[i].setDaemon(True) for i in range(5): ts[i].start() global hosts for host in hosts: q.put(host) q.join() def singlethread(): global hosts for host in hosts: url = urllib.request.urlopen(host) url.read() if __name__=='__main__': hosts=['http://www.2cto.com/kf/201207/142453.html', 'http://www.cnblogs.com/slider/archive/2012/06/21/2557499.html', 'http://www.baidu.com/', 'http://www.csdn.net/', 'http://www.cnblogs.com/'] t=time.time() mutlithread() print('m:'+str(time.time()-t)) t=time.time() singlethread() print('s:'+str(time.time()-t))
代码中分别用两个函数读取里 hosts 数组里的5个网页的内容,在运行后你会发现,采用多线程的方式过程持续0.5秒,而单线程会花费0.6秒,当然由于执行的任务非常简单,所以差别不是很大,但是多线程的优势是无疑的。
顺便讲解一下代码:
在python中有一个线程安全的序列 数据结构,叫queue。在构造时可以声明它的容量。在上述示例中我们主要用到了它的3个成员函数。
put 表示放入对象。
get 表示获取对象,当queue没有item时,get会默认阻塞。每次get都会开启一个task,所以在获取完成后,要执行 task_done 函数。当所有task都被done后,并且queue中没有item时,q.join()所造成的阻塞就会结束,主程序就能继续运行。
另外python的thread也有join的概念,表示主线程等待 join 的子线程的阻塞。
至于另一个函数setDaemon(True)表示这个线程是后台线程,随主线程结束而结束。