</pre> 本文提到的功能已经在上一篇文章中实现 过。这次则是尝试用线程池来加速访问,一则是练习一下线程池使用的方法,而是为下一步实现回复内容的爬取做准备。首先,感谢Adam_Kevint对我的关注,本来只是想写个爬虫练习一下自己的Python编程的,没想到还有人关注。先透露一下,帖子回复的搜索已经大致实现了,不过还没实现线程池功能搜索速度很慢,另外民主湖模拟登陆也实现了,整理整理,有时间就上传上去。</p><p></p><p> 首先,本次实现线程池,有个小问题,就是线程建立时间很久,建立完成之后,很快就搜索完毕,中间有很长一段空白期,用户体验感肯定不好,我继续努力,也希望大神提提宝贵意见。第二,本程序中为了对文件进行有效的读写,采用了互斥锁,感觉挺好用的。第三,就是熟悉了Python任意参数的传递,网上有很多Python的线程池例子,但是参数是固定的,如http://blog.csdn.net/pi9nc/article/details/17056961,不好匹配,我试了几个,觉得现在用这个不错http://developer.51cto.com/art/201002/185290.htm。在此感谢给我大神(我只是代码的搬运工)</p><p> 本文是针对第二篇文章修改的,将一个主题用一个线程来搜索,采用了十个线程,按照队列模型进行搜索。所以只是改动了findAuthorArticleWithoutLogin(authorId,date1)这个函数,还有就是findAuthorArticle(authorId,Fid,FidName,date1)中加了个互斥锁<pre class="python" name="code"> if mutex.acquire(1):
#保存到文件
f.writelines(str(FidName)+u',第'+str(i)+u'页,'+item[1]+','+info+'\n\r')
mutex.release()
实现了文件的独立访问。两个类,一个是工作类,另外一个 是线程管理类。就这样吧,上代码!
# -*- coding: utf-8 -*-
"""
Created on Fri Mar 06 18:13:48 2015
可以爬到所有无需登录的模块
本模块可以从第一页访问,然后根据用户注册时间与网页贴子时间相比较,适时结束访问,加快搜索速度。!
输入参数:
用户ID
用户注册时间:需要登录查看
@author: KyleHuang
@Address: Chongqing University
"""
import re
import urllib2
import datetime
import time
import Queue, threading, sys
from threading import Thread
import time,urllib
# working thread
class Worker(Thread):
worker_count = 0
def __init__( self, workQueue, resultQueue, timeout = 0, **kwds):
Thread.__init__( self, **kwds )
self.id = Worker.worker_count
Worker.worker_count += 1
self.setDaemon( True )
self.workQueue = workQueue
self.resultQueue = resultQueue
self.timeout = timeout
self.start( )
def run( self ):
''' the get-some-work, do-some-work main loop of worker threads '''
while True:
try:
callable, args, kwds = self.workQueue.get(timeout=self.timeout)
res = callable(*args, **kwds)
#print "worker[%2d]: %s" % (self.id, str(res) )
self.resultQueue.put( res )
except Queue.Empty:
break
except :
print 'worker[%2d]' % self.id, sys.exc_info()[:2]
class WorkerManager:
def __init__( self, num_of_workers=10, timeout = 1):
self.workQueue = Queue.Queue()
self.resultQueue = Queue.Queue()
self.workers = []
self.timeout = timeout
self._recruitThreads( num_of_workers )
def _recruitThreads( self, num_of_workers ):
for i in range( num_of_workers ):
worker = Worker( self.workQueue, self.resultQueue, self.timeout )
self.workers.append(worker)
print 'add a task'
def wait_for_complete( self):
# ...then, wait for each of them to terminate:
while len(self.workers):
worker = self.workers.pop()
worker.join( )
if worker.isAlive() and not self.workQueue.empty():
self.workers.append( worker )
#print "All jobs are are completed."
def add_job( self, callable, *args, **kwds ):
self.workQueue.put( (callable, args, kwds) )
print 'Add a task!'
def get_result( self, *args, **kwds ):
return self.resultQueue.get( *args, **kwds )
def findAuthorArticleWithoutLogin(authorId,date1):
FidList={280:u'计算机技术',119:u'学术民主湖',14:u'江风竹雨',27:u'人文社科',63:u'好摄之徒',17:u'书香重大',
109:u'外语角',83:u'黄桷树下',123:u'鱼食天下',107:u'鱼游天下',30:u'激情天下',181:u'数码广场',
18:u'轻松一刻',92:u'老乡会所',195:u'健康大家谈',100:u'心语新缘',234:u'曝光台',103:u'张贴栏',
138:u'生物学院'
#203:u'租房',218:u'兼职',180:u'民主湖超市'
}
#findAuthorArticle(authorId,100,FidList[100],date1)
wm = WorkerManager(10)
for fid in FidList: #将搜索加入到线程池中
wm.add_job( findAuthorArticle, authorId,fid,FidList[fid],date1 )
wm.wait_for_complete() #等待工作完成
#findAuthorArticle(authorId,key,FidList[key],date1)
def findAuthorArticle(authorId,Fid,FidName,date1):
###该函数主要用来访问近几年用户,从第一页访问
pageStart=1#从第一页访问
pageEnd=500#最多访问500页,结束
urlstr='http://www.cqumzh.cn/bbs/forumdisplay.php?fid='+str(Fid);
matchstr='space.php?uid='+str(authorId)
for i in range(pageStart,pageEnd):
print FidName+u'爬虫爬到第'+str(i)+u'页'
#合成URL路径
urlstr2=urlstr+'&page='+str(i)
#模拟请求网址
request = urllib2.Request(urlstr2)
request.add_header('User-Agent', 'fake-client')
response = urllib2.urlopen(request)
myPage =response.read()
#匹配目标内容
myItems=re.findall('<a title=(.*?)>(.*?)</a></span>.*?<td align="center" style="overflow:hidden"nowrap="nowrap">\r\n<cite>\r\n<a href="(.*?)">(.*?)</a>',myPage,re.S)
for item in myItems:
#print item[1]+'authour='+item[2]
#f.writelines(item[1]+'authour='+item[2]+'\n\r')
str1=str(item[2])
#找到目标作者
if str1 == matchstr :
#addr=getWebAdress(item[0])
info=item[0].replace('&','&')
print FidName+u','+item[1]+','+info
if mutex.acquire(1):
#保存到文件
f.writelines(str(FidName)+u',第'+str(i)+u'页,'+item[1]+','+info+'\n\r')
mutex.release()
length=len(myItems)
date2=getItemPage(myItems[length-1][0])
#print date2
dderror=date2-date1
if dderror.days<0:
return
def getWebAdress(objStr):
addr=re.findall('.*?href="(.*?)"',objStr,re.S)
return addr[0]
def getItemPage(objStr):
mItems=re.findall('\d{4}-\d{1,2}-\d{1,2}',objStr,re.S)
mdate=datetime.datetime.strptime(str(mItems[0]), "%Y-%m-%d")
return mdate
if __name__=="__main__":
#此处输入搜索需要的信息
authorId=raw_input(u'请输入作者ID:');
registerDate =raw_input(u'请输入开始日期,(作者注册时间),格式:xxxx-xx-xx');
dd=datetime.datetime.strptime(registerDate, "%Y-%m-%d")
print u"爬虫开始爬民主湖了 ......"
f = open('Bid'+str(authorId)+'.txt','w+')
f.writelines(u"作者"+str(authorId)+u"\n\r")
mutex=threading.Lock()
findAuthorArticleWithoutLogin(authorId,dd)
f.close()