您的位置:首页 > 其它

分布式爬虫样例1

2015-10-14 09:59 543 查看
Python、Redis实现分布式网络爬虫
http://www.bubuko.com/infodetail-820679.html
写爬虫关键是思路,思路明确代码实现起来不是问题。

关于用Python实现一个分布式爬虫,我曾折腾了很长一段时间,翻遍了Google十几页,和
Python分布式爬虫等关键字相关的博客也就那么几篇,后来在学习Redis的时候,终于找到了实现分布式的方法。看来当现有的技术解决不了实际问题的时候,是需要学习新的技术了。

具体实现思路:利用Redis的主从数据同步,所有爬虫获取到的url都放到一个redisqueue中,并且Master和Slave的爬虫都从这个redisqueue中获取url。

需要用到的工具redis-py。

我有两台机器,笔记本Windows,树莓派Linux,笔记本做Master,树莓派做Slave。

爬取网站http://jandan.net/(经常写爬虫的应该不会不知道这个网站。)

以前写爬虫的时候我会把需要下载的URL放在Queue里面,而现在需要把URL放在redisqueue中,借鉴了网上一篇博客的代码

importredis


classRedisQueue(object):

"""SimpleQueuewithRedisBackend"""

def__init__(self,name,namespace=‘queue‘,**redis_kwargs):

"""Thedefaultconnectionparametersare:host=‘localhost‘,port=6379,db=0"""

self.__db=redis.Redis(host=‘192.168.1.105‘,port=6379,db=0)

self.key=‘%s:%s‘%(namespace,name)


defqsize(self):

"""Returntheapproximatesizeofthequeue."""

returnself.__db.llen(self.key)


defempty(self):

"""ReturnTrueifthequeueisempty,Falseotherwise."""

returnself.qsize()==0


defput(self,item):

"""Putitemintothequeue."""

self.__db.rpush(self.key,item)


defget(self,block=True,timeout=None):

"""Removeandreturnanitemfromthequeue.


IfoptionalargsblockistrueandtimeoutisNone(thedefault),block

ifnecessaryuntilanitemisavailable."""

ifblock:

item=self.__db.blpop(self.key,timeout=timeout)

else:

item=self.__db.lpop(self.key)


ifitem:

item=item[1]

returnitem


defget_nowait(self):

"""Equivalenttoget(False)."""

returnself.get(False)


这段代码作为一个模块的形式,文件命名为RedisQueue.py,和爬虫文件放在同一个文件夹里面,具体操作和Queue差不多

>>>fromRedisQueueimportRedisQueue

>>>q=RedisQueue(‘test‘)

>>>q.put(‘helloworld‘)


redis127.0.0.1:6379>keys*

1)"queue:test"

redis127.0.0.1:6379>typequeue:test

list

redis127.0.0.1:6379>llenqueue:test

(integer)1

redis127.0.0.1:6379>lrangequeue:test01

1)"helloworld"


>>>fromRedisQueueimportRedisQueue

>>>q=RedisQueue(‘test‘)

>>>q.get()

‘helloworld‘


先用一段代码将URL放进redisqueue中

#coding=utf-8

frombs4importBeautifulSoup

importurllib2

fromQueueimportQueue

fromRedisQueueimportRedisQueue

queue=Queue()

redis=RedisQueue(‘jandan3‘)


defuser_agent(url):

req_header={‘User-Agent‘:‘Mozilla/5.0(WindowsNT6.1;WOW64;rv:34.0)Gecko/20100101Firefox/34.0‘}

req_timeout=20

req=urllib2.Request(url,None,req_header)

page=urllib2.urlopen(req,None,req_timeout)

html=page

returnhtml


defnext_page():

base_url=‘http://jandan.net/ooxx/page-1006#comments‘

foriinrange(3):

html=user_agent(base_url).read()

soup=BeautifulSoup(html)

next_url=soup.find(‘a‘,{‘class‘:‘next-comment-page‘,‘title‘:‘NewerComments‘}).get(‘href‘)

yieldbase_url

base_url=next_url

forpageinnext_page():

queue.put(page)

print‘Thereare%dpages‘%queue.qsize()


whilenotqueue.empty():

page_url=queue.get()

html=user_agent(page_url).read()

soup=BeautifulSoup(html)

img_urls=soup.find_all([‘img‘])

formyimginimg_urls:

Jpgurl=myimg.get(‘src‘)

redis.put(Jpgurl)

print‘Thereare%dpictures‘%redis.qsize()


然后在Master端可以看到:

redis192.168.1.105:6379>keys*

1)"queue:jandan3"

redis192.168.1.105:6379>


Slave端:

192.168.1.106:6379>keys*

1)"queue:jandan3"

192.168.1.106:6379>


现在Master和Slave都可以读取redisqueue中的数据,下面的工作就是Master和Slave分别运行自己的爬虫对redisqueue中的数据下载就行了。

Windows爬虫代码

importurllib2

fromRedisQueueimportRedisQueue

redis=RedisQueue(‘jandan3‘)


defuser_agent(url):

req_header={‘User-Agent‘:‘Mozilla/5.0(WindowsNT6.1;WOW64;rv:34.0)Gecko/20100101Firefox/34.0‘}

req_timeout=20

req=urllib2.Request(url,None,req_header)

page=urllib2.urlopen(req,None,req_timeout)

html=page

returnhtml


whilenotredis.empty():

down_url=redis.get()

data=user_agent(down_url).read()

withopen(‘D:/Python/picture‘+‘/‘+down_url[-11:],‘wb‘)ascode:

code.write(data)

printdown_url


Linux爬虫代码:

importurllib2

fromRedisQueueimportRedisQueue

redis=RedisQueue(‘jandan3‘)


defuser_agent(url):

req_header={‘User-Agent‘:‘Mozilla/5.0(WindowsNT6.1;WOW64;rv:34.0)Gecko/20100101Firefox/34.0

‘}

req_timeout=20

req=urllib2.Request(url,None,req_header)

page=urllib2.urlopen(req,None,req_timeout)

html=page

returnhtml


whilenotredis.empty():

down_url=redis.get()

data=user_agent(down_url).read()

withopen(‘/mz/picture‘+‘/‘+down_url[-11:],‘wb‘)ascode:

code.write(data)

printdown_url


将这两段代码同时运行,即可对redisqueue中的URL同时下载,直到把redisqueue取空为止。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: