scrapy框架二

scrapy学习

整体流程图

流程图

中间件介绍

  • middlewares.py

  • # 爬虫中间件: 处于spider和引擎之间(不常用)
    
    # 下载中间件: 处于引擎和下载器之间(常用)
    class MiddleproDownloaderMiddleware:
    
        def process_request(self, request, spider):
            """
            拦截所有的请求
            :param request: 拦截到的请求对象
            :param spider: 爬虫文件中爬虫类实例化的对象
            """
            # 对请求头进行相关操作
            # request.headers['Cookie'] = 'xxx'
            pass
    
        def process_response(self, request, response, spider):
            """
            拦截所有的响应
            :param response: 响应对象
            :param spider: 爬虫文件中爬虫类实例化的对象
            :return: 返回响应
            """
            return response
    
        def process_exception(self, request, exception, spider):
            """
            拦截发生异常的请求
            :param spider: 爬虫文件中爬虫类实例化的对象
            :return: 返回修正后的请求
            """
            # 将代理的设置写在此处
            # request.meta['proxy'] = 'https://ip:port'
            
            # 将修正后的请求对象重新进行请求发送
            return request  
        
    
  • 配置文件中打开

    • DOWNLOADER_MIDDLEWARES = {
         'middlePro.middlewares.MiddleproDownloaderMiddleware': 543,
      }
      

CrawlSpider

  • 作用: 实现全站数据爬取

  • 创建: scrapy genspider -t crawl test www.xxx.com

  • import scrapy
    from scrapy.linkextractors import LinkExtractor
    from scrapy.spiders import CrawlSpider, Rule
    
    
    class TestSpider(CrawlSpider):
        name = 'test'
        allowed_domains = ['www.xxx.com']
        start_urls = ['http://www.xxx.com/']
    	
        link = LinkExtractor(allow=r'Items/')  # 核心一: 链接提取器,使用正则匹配出页面中所有符合的链接数据
        rules = (
            Rule(, callback='parse_item', follow=True),
        )  # 核心二: 规则提取器,follow=True可以深度提取
    
        def parse_item(self, response):
            item = {}
            return item
    
    

分布式

  • 概念: 可以组建一个分布式机群,然后让其对同一组网络资源进行联合且分布的数据爬取。

  • 实现原理: 使用scrapy-redis组件结合着scrapy实现分布式

    • scrapy-redis作用: 提供可以被共享的管道和调度器
  • 实现步骤

    1. 创建工程并进入: scrapy startproject dcsProcd dcsPro

    2. 创建爬虫文件: scrapy genspider -t crawl dcs www.xx.com

    3. 修改爬虫文件

      • import scrapy
        from scrapy.linkextractors import LinkExtractor
        from scrapy.spiders import CrawlSpider, Rule
        from scrapy_redis.spiders import RedisCrawlSpider
        from dcsPro.items import DcsproItem
        
        """
        导包:from scrapy_redis.spiders import RedisCrawlSpider
        修改爬虫的父类为:RedisCrawlSpider
        将start_urls替换成redis_key = ‘xxx’:调度器队列的名称
        编写正常的数据爬取操作
        """
        
        
        class DcsSpider(RedisCrawlSpider):
            name = 'dcs'
            # allowed_domains = ['www.xx.com']
            # start_urls = ['http://www.xx.com/']
            redis_key = 'dcsQueue'  # 调度器队列名称
        
            rules = (
                Rule(LinkExtractor(allow=r'index_\d+\.html'), callback='parse_item', follow=True),
            )
        
            def parse_item(self, response):
                div_list = response.xpath('/html/body/div[3]/div[2]/div')
                for div in div_list:
                    title = div.xpath('./div/a/text()').extract_first()
                    img_url = "https" + div.xpath('./img/@ata-original').extract_first()
        
                    item = DcsproItem()
                    item['title'] = title
                    item['url'] = img_url
        
                    yield item
        
        
    4. 根据爬虫文件中用到的item类修改items.py文件

      • import scrapy
        
        
        class DcsproItem(scrapy.Item):
            title = scrapy.Field()
            url = scrapy.Field()
        
    5. 修改settings.py配置文件

      • ROBOTSTXT_OBEY = False  # 是否遵循robots协议
        USER_AGENT = '...'  # UA
        LOG_LEVEL = 'ERROR'  # 设置日志等级
        COOKIES_ENABLED = True  # 打开cookie机制
        ITEM_PIPELINES = {
            ...
           'scrapy_redis.pipelines.RedisPipeline': 400,  # 指定管道
        }
        # 使用scrapy-redis组件的去重队列
        DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
        # 使用scrapy-redis组件自己的调度器
        SCHEDULER = "scrapy_redis.scheduler.Scheduler"
        # 是否允许暂停
        SCHEDULER_PERSIST = True
        
        # 指定redis
        REDIS_HOST = '127.0.0.1'  # 填写redis地址
        REDIS_PORT = 6379  # 填写redis端口
        
    6. 修改redis的配置文件redis.window.conf

      • 关闭默认绑定:56行:# bind 127.0.0.1
        关闭保护模型:75行:protected-mode no
        
    7. 启动redis服务端和客户端

      • redis-server --service-start  # 启动redis服务端
        
    8. 执行当前工程

      • scrapy crawl dcs
        
    9. 向调度器的队列中扔入一个起始的url

      • redis-cli  # 进入redis客户端
        lpush dcsQueue 网址  # 队列名称在第3步爬虫文件中有定义
        
        # 在dcs:items中可以看到存储的数据
        

增量式

  • 作用: 监测网站数据更新的情况

  • 核心: 去重

  • 实现步骤

    1. 创建工程并进入: scrapy startproject incrementalProcd incrementalPro

    2. 创建爬虫文件: scrapy genspider -t crawl incremental www.xxx.com

    3. 修改爬虫文件

      • # incremental.py
        # 以下是以当时测试的网站为例
        import scrapy
        from redis import Redis
        from scrapy.linkextractors import LinkExtractor
        from scrapy.spiders import CrawlSpider, Rule
        
        from incrementalPro.items import IncrementalproItem
        
        
        class IncrementalSpider(CrawlSpider):
            name = 'incremental'
            # allowed_domains = ['www.xxx.com']
            start_urls = ['https://sc.chinaz.com/tupian/']
        
            conn = Redis(host='127.0.0.1', port=6379)
        
            rules = (
                Rule(LinkExtractor(allow=r'index_\d+\.html'), callback='parse_item', follow=True),
            )
        
            def parse_item(self, response):
                div_list = response.xpath('/html/body/div[3]/div[2]/div')
                for div in div_list:
                    detail_url = 'https://sc.chinaz.com' + div.xpath('./div/a/@href').extract_first()
        
                    ex = self.conn.sadd('urls', detail_url)
                    if ex == 1:
                        """ 有数据更新的情况 """
                        yield scrapy.Request(detail_url, callback=self.parse_detail)
                    else:
                        """ 无数据更新 """
                        pass
        
            def parse_detail(self, response):
                title = response.xpath('/html/body/div[3]/div[1]/div[1]/div[2]/div[1]/h1/text()').extract_first()
                blurb = response.xpath('/html/body/div[3]/div[1]/div[1]/div[2]/div[3]/div[1]/p[2]/text()').extract_first()
                
                if title and blurb:
                    """ 标题和简介存在的情况下 """
                    item = IncrementalproItem()
                    item['title'] = title
                    item['blurb'] = blurb
        
                    yield item
        
        
    4. 根据爬虫文件中用到的item类修改items.py文件

      • # items.py
        import scrapy
        
        
        class IncrementalproItem(scrapy.Item):
            title = scrapy.Field()
            blurb = scrapy.Field()
        
    5. 修改管道文件pipelines.py

      • # pipelines.py
        # 注意事项: 因为这边往redis中扔入的是一个字典,可能有些版本是不适用的,我这边使用的是redis-2.10.6版本
        # pip install -U redis==2.10.6
        class IncrementalproPipeline:
            def process_item(self, item, spider):
                spider.conn.lpush('imgData', item)
                return item
        
    6. 修改settings.py配置文件

      • USER_AGENT = '...'
        ROBOTSTXT_OBEY = False
        LOG_LEVEL = 'ERROR'
        COOKIES_ENABLED = True
        
        ITEM_PIPELINES = {
           'incrementalPro.pipelines.IncrementalproPipeline': 300,
        }
        
    7. 启动redis服务端: redis-server --service-start

    8. 启动工程: scrapy crawl incremental

      • 在imgData中可以看到存储的数据
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值