scrapy入门(四)分布式和增量式

一. 分布式

  1. 概念 : 需要搭建一个分布式的机群, 然后在机群的每一台电脑中执行同一组程序, 让其对某一个网站的数据进行联合分布爬取

  2. scrapy + scrapy_redis实现分布式

    scrapy_redis组件的功能 :

    • 提供可被共享的调度器和管道
    • 数据只能存储到redis数据库中
  3. 实现流程

    1. 修改源文件
    #以创建CrawlSpider为例
    #导包
    from scrapy_redis.spiders import RedisCrawlSpider
    #修改爬虫类的父类
    class FbsSpider(RedisCrawlSpider):
        #注释掉allow_domains和start_urls,分布式不推荐使用start_urls
        #添加新属性
        redis_key ='fbsQueue'#表示的是可以被共享的调度器队列的名称,将起始url直接放到调度器中
    
    1. settings文件的配置
    ITEM_PIPELINES = {
        'scrapy_redis.pipelines.RedisPipeline':300
    }
    #确保所有的爬虫通过Redis去重
    DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
    #启用Redis调度存储请求队列
    SCHEDULER = "scrapy_redis.scheduler.Scheduler"
    #不清除Redis队列,起到记忆功能
    #例如隔几天后重新爬取同一个网站,设置为True则之前爬取过的数据不再爬取
    SCHEDULER_PERSIST = True
    
    #指定redis数据库
    #指定连接到redis时使用的端口和地址(可选)
    REDIS_HOST = '指定一个ip地址'
    REDIS_PORT = 6379
    
    1. 对redis数据库的配置文件进行操作(redis.windows.conf)

      • 关闭默认绑定 : 56 Line : #bind 127.0.0.1
      • 关闭保护模式 :75 Line : protect-mode no\
    2. 携带配置文件启动redis服务端, 再启动客户端

      • redis-server.exe redis.windows.conf
      • redis-cli
    3. 在pycharm中启动程序
      scrapy run spider fbs.py #fbs是自定义爬虫名

      之后程序会等待我们进行redis数据库的操作, 才会继续进行

    4. 向调度器的队列中扔入一个起始的url :

      启动redis客户端,输入lpush fbsQueue "起始url"

二. 增量式

核心机制: 对详情页的url去重. redis的set实现去重

原理实现过程:

  • 需要两张表, 一张保存数据源文件, 一份保存数据文件生成的数据指纹
  • 每次先将爬取到的文件生成一份对应的数据指纹,
    • 如果已经存在数据指纹库中, 则不需要向管道提交,
    • 否则保存数据指纹和原文件
#python源文件
from redis import Redis

class ZlsSpider(CrawlSpider):
    #将连接对象作为ZlsSpider类的一个属性
    conn = Redis(host = '127.0.0.1',port = 6379)
    pass

def parse_item(self,response):
    #...
    detail_url = li.xpath('xxxxxxx')
    #将解析得到的url和redis数据库中的表作比较
    #对于不需要深度爬取的页面,可以将要爬取的数据文件拼成一个字符串,然后放入到hashlib中生成一个专属source_id,就相当于url,以后爬取的时候同样判断这个source_id是否在对应的data_id表中
    #source = item['author'] + item['content']
    #source_id =hashlib.sha256(source.encode()).hexdigest()
    #ex = self.conn.sadd('data_id',source_id)
    
    #sadd()功能:如果url存在则不向表中添加数据并返回0,不存在则向表中添加并返回1
    ex = self.conn.sadd('urls_id',detail_url)#urls_id为数据库记录url是否爬取过的表
    if ex == 1 :
        #手动发送请求
        yield scrapy.Request(detail_url,callback=self.parse_detail,meta={'item':item})
def parse_detail(self,response):
    content = response.xpath('xxxxxxxxxx').extract_first()
    
    item = response.meta['item']
    #item对象在前面的for循环中创建,保证每次循环请求不同的url时生成一个item对象
    item['content'] =content
    
    #将item对象传递给管道
    yield item
#pipelines文件中
def process_item(self, item, spider):
    #接受爬虫类的conn
    conn = spider.conn
    conn.lpush('detail_data',item) #detail_data用来保存爬取的数据信息
   	return item

三. 反爬机制总结

  • robots
  • UA伪装
  • 验证码
  • 代理
  • cookie
  • 动态变化的请求参数
  • js加密
  • js混淆
  • 图片懒加载
  • 动态数据的捕获
  • selenium :规避检测
posted @ 2020-03-05 13:41  逸枚俗人  阅读(172)  评论(0编辑  收藏  举报