设为首页 收藏本站
查看: 2077|回复: 0

[经验分享] Python、Redis实现分布式网络爬虫

[复制链接]
累计签到:6 天
连续签到:1 天
发表于 2015-12-1 09:21:21 | 显示全部楼层 |阅读模式
写爬虫关键是思路,思路明确代码实现起来不是问题。
关于用Python实现一个分布式爬虫,我曾折腾了很长一段时间,翻遍了Google十几页,和 Python 分布式 爬虫 等关键字相关的博客也就那么几篇,后来在学习Redis的时候,终于找到了实现分布式的方法。看来当现有的技术解决不了实际问题的时候,是需要学习新的技术了。
具体实现思路:利用Redis的主从数据同步,所有爬虫获取到的url都放到一个redis queue中,并且Master和Slave的爬虫都从这个redis queue中获取url。
需要用到的工具redis-py。
我有两台机器,笔记本Windows,树莓派Linux,笔记本做Master,树莓派做Slave。
爬取网站http://jandan.net/(经常写爬虫的应该不会不知道这个网站。)
以前写爬虫的时候我会把需要下载的URL放在Queue里面,而现在需要把URL放在 redis queue 中,借鉴了网上一篇博客的代码


import redis    class RedisQueue(object):      """Simple Queue with Redis Backend"""      def __init__(self, name, namespace='queue', **redis_kwargs):          """The default connection parameters are: 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)        def qsize(self):          """Return the approximate size of the queue."""          return self.__db.llen(self.key)        def empty(self):          """Return True if the queue is empty, False otherwise."""          return self.qsize() == 0        def put(self, item):          """Put item into the queue."""          self.__db.rpush(self.key, item)        def get(self, block=True, timeout=None):          """Remove and return an item from the queue.           If optional args block is true and timeout is None (the default), block         if necessary until an item is available."""          if block:              item = self.__db.blpop(self.key, timeout=timeout)          else:              item = self.__db.lpop(self.key)            if item:              item = item[1]          return item        def get_nowait(self):          """Equivalent to get(False)."""          return self.get(False)  
这段代码作为一个模块的形式,文件命名为RedisQueue.py,和爬虫文件放在同一个文件夹里面,具体操作和Queue差不多




>>> from RedisQueue import RedisQueue  >>> q = RedisQueue('test')  >>> q.put('hello world')   redis 127.0.0.1:6379> keys *  1) "queue:test"  redis 127.0.0.1:6379> type queue:test  list  redis 127.0.0.1:6379> llen queue:test  (integer) 1  redis 127.0.0.1:6379> lrange queue:test 0 1  1) "hello world"   >>> from RedisQueue import RedisQueue  >>> q = RedisQueue('test')  >>> q.get()  'hello world'
先用一段代码将URL放进redis queue中




#coding=utf-8from bs4 import BeautifulSoupimport urllib2from Queue import Queuefrom RedisQueue import RedisQueuequeue = Queue()redis = RedisQueue('jandan3') def user_agent(url):    req_header = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0'}    req_timeout = 20    req = urllib2.Request(url,None,req_header)    page = urllib2.urlopen(req,None,req_timeout)    html = page    return html def next_page():    base_url = 'http://jandan.net/ooxx/page-1006#comments'    for i in range(3):        html = user_agent(base_url).read()        soup = BeautifulSoup(html)                 next_url = soup.find('a',{'class':'next-comment-page','title':'Newer Comments'}).get('href')        yield base_url        base_url = next_url        for page in next_page():    queue.put(page)print 'There are %d pages'%queue.qsize()        while not queue.empty():    page_url = queue.get()    html = user_agent(page_url).read()    soup = BeautifulSoup(html)    img_urls = soup.find_all(['img'])    for myimg in img_urls:        Jpgurl = myimg.get('src')        redis.put(Jpgurl)print 'There are %d pictures'%redis.qsize()
然后在Master端可以看到:




redis 192.168.1.105:6379> keys *1) "queue:jandan3"redis 192.168.1.105:6379>  

Slave端:




192.168.1.106:6379> keys *1) "queue:jandan3"192.168.1.106:6379>
现在Master和Slave都可以读取redis queue中的数据,下面的工作就是Master和Slave分别运行自己的爬虫对redis queue中的数据下载就行了。
Windows爬虫代码




import urllib2from RedisQueue import RedisQueueredis = RedisQueue('jandan3') def user_agent(url):    req_header = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0'}    req_timeout = 20    req = urllib2.Request(url,None,req_header)    page = urllib2.urlopen(req,None,req_timeout)    html = page    return html while not redis.empty():    down_url = redis.get()    data = user_agent(down_url).read()    with open('D:/Python/picture'+'/'+down_url[-11:],'wb')as code:        code.write(data)    print down_url
Linux爬虫代码:




import urllib2from RedisQueue import RedisQueueredis = RedisQueue('jandan3') def user_agent(url):    req_header = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0'}    req_timeout = 20    req = urllib2.Request(url,None,req_header)    page = urllib2.urlopen(req,None,req_timeout)    html = page    return html while not redis.empty():    down_url = redis.get()    data = user_agent(down_url).read()    with open('/mz/picture'+'/'+down_url[-11:],'wb')as code:        code.write(data)    print down_url  

将这两段代码同时运行,即可对redis queue 中的URL同时下载,直到把redis queue取空为止。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-145705-1-1.html 上篇帖子: 唠叨一些关于Python的事情 下篇帖子: 工欲善其事必先利其器-Notepad++使用小记(Python)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表