【原创】编写多线程Python爬虫来过滤八戒网上的发布任务

目标:

以特定语言技术为关键字,爬取八戒网中网站设计开发栏目下发布的任务相关信息

 

需求:

用户通过设置自己感兴趣的关键字或正则表达式,来过滤信息。

我自己选择的是通过特定语言技术作为关键字,php、java和python。

注意:如果不选用正则表达式,就会把javascript也爬进来,那前端的信息就比较多了。

 

为什么要使用多线程:

网络烂,读网页时很容易阻塞,这个时候后面的工作都得等;

在保存页面时,有对硬盘I/O的需求,如果阻塞了也得等。

 

实现:

0、3个线程。一个线程A负责读取网页,一个线程B负责分析返回的网页并分析出所需的数据,一个线程C负责把所需的数据写到硬盘上。

1、A线程通过一个list和B线程通信,B线程通过一个list和C线程通信。A是纯生产者,B面对A时是消费者,面对C时是生产者,C是纯生产者。可以把3个线程想象成一个链表,A --> B --> C,其中A线程必定最早结束,其次是B,最后是C。但是注意,前面线程结束了,如果list中还有数据,后面的进程需要消费完该数据后才能结束。

2、既然要访问共享区域,自然是上锁互斥了。

3、具体如何分析网页就不讲了,比较简单。八戒网做的比较实在,都在<li></li>标签内部,很好识别。输出的时候我选择输出为html文件,这样直接就能当网页看。

 

全部代码:

# @author shadowmydx

import urllib2 import re from threading import Thread,Lock listPage = [] # 网页读取线程和网页分析线程通信的缓存区域 listResu = [] # 网页分析线程和输出线程通信的缓存区域 listFilter = [] listFilter.append(re.compile(r'php')) listFilter.append(re.compile(r'[Pp]ython')) listFilter.append(re.compile(r'[jJ]ava[^Ss]')) # 防止匹配到javascript pageLock = Lock() # a 和 b的锁 writLock = Lock() # b 和 c的锁 openEnd = False # a线程结束了吗? analEnd = False # b线程结束了吗? target = r'http://www.witmart.com/cn/web-design/jobs' webhost = r'http://www.witmart.com/cn/web-design/jobs' numPages = 22 class ReadPageThread(Thread): def run(self): global listPage global target global numPages global pageLock global openEnd self.nextPage = 1 while numPages != 0: f = self.openPage(target) pageLock.acquire() listPage.append(f) print target + ' is finished.' pageLock.release() target = self.findNext(f) numPages -= 1 openEnd = True def openPage(self,target): tmp = True while tmp: try: print 'open page..' f = urllib2.urlopen(target).read() print 'open successed!' break except: tmp = True return f def findNext(self,target): global webhost self.nextPage += 1 return webhost + '?p=' + str(self.nextPage) class AnalsPageThread(Thread): def run(self): global listPage global pageLock global openEnd global analEnd f = False while not openEnd or len(listPage) != 0: pageLock.acquire() if len(listPage) != 0: f = listPage.pop(0) else: f = False pageLock.release() if f != False: self.analsPage(f) analEnd = True def analsPage(self,target): global listResu global writLock global listFilter ul = r'<ul class="joblist"' liItem = re.compile(r'<li.*?</li>',re.DOTALL) ulStart = target.find(ul) target = target[ulStart:] liList = liItem.findall(target) for item in liList: # judge if has php for key in listFilter: if key.search(item): writLock.acquire() item = self.replaceHref(item) listResu.append(item) print 'analysis one item success!' writLock.release() break def replaceHref(self,item): return item.replace('/cn','http://www.witmart.com/cn') class WritePageThread(Thread): def __init__(self,pathTo): Thread.__init__(self) self.pathTo = pathTo def run(self): global listResu global writLock global analEnd f = open(self.pathTo + '/' + 'res.html','wb') f.write(r'<html><body><ul>') while analEnd == False or len(listResu) != 0: writLock.acquire() if (len(listResu) != 0): liItem = listResu.pop(0) f.write(liItem) f.write('<br />') print 'write one item success!' writLock.release() f.write('</ul></body></html>') f.close() a = ReadPageThread() b = AnalsPageThread() c = WritePageThread(r'/home/wmydx/info') a.start() b.start() c.start()

 

posted on 2014-12-17 20:45  shadowmydx'sLab  阅读(294)  评论(0编辑  收藏  举报

导航