• scrapy-redis实现分布式爬虫


    OK!终于到了分布式爬虫了,说下,我整了几天才把分布式爬虫给搞定。(心里苦哇)为什么会这么久,请听我徐徐道来。

    在使用分布式爬虫的时候通用的做法是一台电脑作为master端,另外的多台电脑作为slaver端,我采用的是主机与虚拟机来搭建的环境,说说我的主机,一台联想的y410笔记本,只有4G的内存,用到现在已经快5年了,还很坚挺 :-)就是内存小了点,我的虚拟机用的是xubuntu(轻量级的ubuntu),虚拟机作为的master端,master端的redis用来存储数据以及url去重,主机作为slaver端执行代码。这里面有一步很关键,那就是我的主机(slaver端)要能够访问我的虚拟机(master端)里面的redis数据库才行,很无奈我就是卡在了这里,我的主机无论如何都无法ping通虚拟机,也就是访问不了xubuntu的redis数据库,在网上找了各种解决方法,都行不通,最后没办法了直接卸载了vnware重装之后,又修改了下网络配置,才最终解决问题。实属心酸~

    所以呀,如果有小伙伴遇见类似的问题,除了google之外,可以直接考虑重装下自己的vmware。

     

    嗯~好,当主机与虚拟机ping通之后就可以来做分布式了,具体实现细节我就不再赘余了,百度一下出来一大堆结果。我之后会写一篇关于scrapy-redis的源码解读的博客。这里只是记录一下具体代码实现的过程。

    目标网址:人民网
    http://politics.people.com.cn/GB/1024/index1.html

     同样无反爬措施,可以安心使用。

    items.py
     1 import scrapy
     2 
     3 
     4 class PeopleItem(scrapy.Item):
     5     # define the fields for your item here like:
     6     # name = scrapy.Field()
     7     title = scrapy.Field()
     8     pub_time = scrapy.Field()
     9     url = scrapy.Field()
    10     content = scrapy.Field()
     spiders.py
     1 # -*- coding: utf-8 -*-
     2 import scrapy
     3 
     4 from scrapy_redis.spiders import RedisSpider
     5 from ..items import PeopleItem
     6 
     7 
     8 class RedisTestSpider(RedisSpider):
     9     name = 'redis-test'
    10     # allowed_domains = ['people.com.cn']  有坑需注意
    11     # start_urls = ['http://politics.people.com.cn/GB/1024/index1.html']
    12 
    13     redis_key = "redistest:start_urls"
    14 
    15     def __init__(self, *args, **kwargs):
    16         domain = kwargs.pop('domain', '')
    17         self.allowed_domains = filter(None, domain.split(','))
    18         super(RedisTestSpider, self).__init__(*args, **kwargs)
    19 
    20     def parse(self, response):
    21         news_list = response.xpath("//div[@class='ej_list_box clear']/ul/li")
    22         for new in news_list:
    23             item = PeopleItem()
    24             title = new.xpath("./a/text()").extract_first()
    25             url = new.xpath("./a/@href").extract_first()
    26             url = "http://politics.people.com.cn" + url
    27             pub_time = new.xpath("./em/text()").extract_first()
    28 
    29             item["title"] = title
    30             item["url"] = url
    31             item["pub_time"] = pub_time
    32             yield scrapy.Request(url=url, meta={"item": item}, callback=self.parse_detail,
    33                                  dont_filter=True)  # 必须要加上 dont_filter 参数
    34 
    35         # 下一页
    36         next_page_url = response.xpath("//div[@class='page_n clearfix']/a[last()]/@href").extract_first()
    37         next_page_url = "http://politics.people.com.cn/GB/1024/" + next_page_url
    38         is_active = response.xpath("//div[@class='page_n clearfix']/a[last()]/@href").extract_first()
    39 
    40         if next_page_url and is_active != "common_current_page":
    41             yield scrapy.Request(url=next_page_url, callback=self.parse, dont_filter=True)  # 必须要加上 dont_filter 参数
    42 
    43     def parse_detail(self, response):
    44         item = response.meta["item"]
    45         article = ""
    46         content_list = response.xpath("//div[@class='fl text_con_left']//p/text()").extract()
    47         for content in content_list:
    48             content = content.strip()
    49             article += content
    50         print(article)
    51         item["content"] = article
    52         yield item

    spiders.py 这里会有坑的,人民网他的url设计的时候跨度比较大 allowed_domains = ['people.com.cn'] 有时候无法匹配的上,这个时候会控制台会报如下错:

    2019-02-11 00:25:51 [scrapy.spidermiddlewares.offsite] DEBUG: Filtered offsite request to 'politics.people.com.cn': <GET http://politics.people.com.cn/n1/2019/0210/c1024-30616296.html>

    解决的办法就是将allowed_domains = ['people.com.cn'] 注释掉,如果还不能解决就加上 dont_filter ,表示本次请求不要要对url进行过滤。

     settings.py
    USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.22 
                  Safari/537.36 SE 2.X MetaSr 1.0'
    
    ROBOTSTXT_OBEY = False
    
    ITEM_PIPELINES = {
        # 'people.pipelines.PeoplePipeline': 300,
        'scrapy_redis.pipelines.RedisPipeline': 400,
    }
    
    # 使用scrapy-redis的去重规则
    DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
    # 使用scrapy-redis的引擎
    SCHEDULER = "scrapy_redis.scheduler.Scheduler"
    # 暂停功能
    SCHEDULER_PERSIST = True
    # 默认的scrapy-redis请求队列形式(按优先级)
    SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderPriorityQueue"
    # 注释掉默认使用主机的redis
    # REDIS_HOST = '192.168.48.128'
    # REDIS_PORT = 6379
     piplines.py

    将redis里面的数据存储至mongodb / mysql 这里我在网上找到了一些文章我自己还没有取验证,目前主流的做法是单独的写脚本,从redis里面取数据,我是觉得这种做法特别的不好、特别的low,等我验证了网上的一些教程后在来贴出来。

    结束语:

    ok,scrapy真的是一个可拓展性很强的框架,短短的几行设置就能够实现分布式,日后我会更新一些反爬虫措施强一点的网站、模拟登录、以及scrapy的源码解读。老是爬一些无反爬措施的网站真的没什么意思。休息了休息了~

  • 相关阅读:
    如何使用shell脚本快速排序和去重文件数据
    centos7下搭建git和gitlab版本库
    Jenkins安装部署
    那日了狗的上半年的兼容性问题,下半年来解决。
    RecyclerView notifyDataSetChanged不起作用
    android通过BitmapFactory.decodeFile获取图片bitmap报内存溢出的解决办法
    java.lang.UnsatisfiedLinkError: Couldn't load hyphenate_av from loader dalvik.system.PathClassLoader
    android studio Error:java.lang.OutOfMemoryError: GC overhead limit exceeded
    apache https配置
    docker进入容器的方式
  • 原文地址:https://www.cnblogs.com/pontoon/p/10360727.html
Copyright © 2020-2023  润新知