import requests import queue import time import logging import threading loghandel=logging.getLogger( totest ) fhand = logging.FileHandler( ./log/main.log , a ) formator = logging.Formatter( %(asctime)s - %(name)s - %(levelname)s - %(module)s - %(lineno)d - %(message)s , %a, %d %b %Y %H:%M:%S ) fhand.setFormatter(formator) fhand.setLevel(logging.DEBUG) loghandel.addHandler(fhand) loghandel.setLevel(logging.DEBUG) def test5(threadcount): reqqueue = queue.Queue() respqueue=queue.Queue() for i in range(1,624): reqqueue.put( http://club.autohome.com.cn/bbs/forum-c-3170-{0}.html?orderby=dateline qaType=-1 .format(i)) def downloadpage(url): starttime = time.time() startclock = time.clock() rsp = requests.get(url) endtime = time.time() endclock = time.clock() loghandel.info(rsp.url + + str(rsp.elapsed.microseconds) + + str(rsp.status_code) + + str( endtime - starttime)+ + str(endclock - startclock)) respqueue.put(rsp) while reqqueue.qsize()!=0: threadpool=[] for i in range(1, threadcount): try: page = reqqueue.get(block=False) t = threading.Thread(target=downloadpage(page)) threadpool.append(t) except queue.Empty as e: loghandel.error( the pagequeue is empty ) break for t in threadpool: t.start() for t in threadpool: t.join() threadpool.clear() return respqueue if __name__ == __main__ : for i in [2, 6, 11, 31, 51]: starttime = time.time() startclock = time.clock() test5(i) endtime = time.time() endclock = time.clock() print(str(i - 1), endtime - starttime, endclock - startclock)
t = threading.Thread(target=downloadpage(page)) 这句话有误,
你这实际上是主线程调用downloadpage(page),然后把返回值赋值给target,
你可以在downloadpage方法种加入print threading.current_thread().getName()语句看看执行的线程就知道了,
应该写成: t = threading.Thread(target=downloadpage,args=(page,))
因此你代码执行的效果就是main线程串行执行,没有其他线程并发。
其次,你这个线程池是不对的,你这样写每次都会创建一个新的线程对象去执行downloadpage方法,达不到线程复用的目的……
分析的很透彻
感谢指点。
我又改进了一下,downloadpage这个方法不传参数了,在这个方法里面加了一个循环,如果队列中仍有url,就取出来并访问。
这样就不用每次创建对象了。抓取速度简直飞一般的感觉。
不过这个也就是取个巧,还不是线程池。我百度过,python3好像是没有现成的线程池方面的包的,不知道是不是这样。