Scrapy框架之分布式操做

1、分布式爬虫介绍

  分布式爬虫概念:多台机器上执行同一个爬虫程序,实现网站数据的分布爬取。html

一、原生的Scrapy没法实现分布式爬虫的缘由?

  • 调度器没法在多台机器间共享:由于多台机器上部署的scrapy会各自拥有各自的调度器,这样就使得多台机器没法分配start_urls列表中的url。
  • 管道没法给多台机器共享:多台机器爬取到的数据没法经过同一个管道对数据进行统一的数据持久出存储。

二、scrapy-redis组件

  scrapy-redis是专门为scrapy框架开发的一套组件。该组件能够解决上述两个问题,让Scrapy实现分布式。
  组件安装:python

$ pip3 intall scrapy-redis

2、基于RedisCrawlSpider的分布式爬取

一、redis配置和启动

(1)对redis配置文件redis.conf进行配置

  • 注释该行:bind 127.0.0.1,表示可让其余ip访问redis
  • 将yes该为no:protected-mode no,表示可让其余ip操做redis
# 不注释时,只容许本机的客户端链接
# bind 127.0.0.1

# yes改成no,关闭redis的保护模式,客户端能够对服务器进行读写操做
protected-mode  no

(2)基于配置文件开启redis服务器

# MAC/Linux
$ pwd
/Users/hqs/redis-5.0.2
$ src/redis-server redis.conf 

# windows
$ redis-server.exe redis-windows.conf

二、项目和爬虫建立

$ scrapy startproject redisPro
$ cd redisPro/
$ scrapy genspider -t crawl qiubai www.qiushibaike.com/pic/

  这里运用CrawlSpider建立爬虫文件爬取全站图片数据。web

三、爬虫文件编写

import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from scrapy_redis.spiders import RedisCrawlSpider
from redisPro.items import RedisproItem    # 引入items类


class QiubaiSpider(RedisCrawlSpider):
    name = 'qiubai'
    # allowed_domains = ['www.qiushibaike.com/pic/']
    # start_urls = ['http://www.qiushibaike.com/pic/']
    # redis_key表示调度器中的队列(将要爬取的页面数据对应的url都须要放置到调度器队列中)
    redis_key = 'qiubaispider'   # 自定义调度器队列的名称,该行代码表示的含义和start_urls同样

    # 连接提取器
    # 从页面提取连接页码的url:/pic/page/2?s=5147462
    # s后对应的参数值会在浏览器刷新时动态变化, 正则忽略s参数的变化进行提取
    link = LinkExtractor(allow=r'/pic/page/\d+')
    # 规则解析器
    rules = (
        Rule(link, callback='parse_item', follow=True),
    )

    def parse_item(self, response):
        """解析操做:提取图片连接"""
        div_list = response.xpath('//div[@id="content-left"]/div')    # 获取divz列表
        for div in div_list:    # 遍历div列表
            # 解析提取div中图片url,保存在img标签的src属性下
            img_url = "https:" + div.xpath('.//div[@class="thumb"]/a/img/@src').extract_first()
            # 实例化items对象
            item = RedisproItem()
            item['img_url'] = img_url    # 封装items

            yield item

(1)引入scrapy-redis中的模块

  在爬虫文件中要导入RedisCrawlSpider类,而后将爬虫文件修改为基于该类的源文件。redis

from scrapy_redis.spiders import RedisCrawlSpider

# class QiubaiSpider(CrawlSpider):
class QiubaiSpider(RedisCrawlSpider):

(2)声明redis_key属性

  redis_key表示调度器中的队列(将要爬取的页面数据对应的url都须要放置到调度器队列中)。
  redis_key自定义调度器队列的名称,表示的含义和start_urls同样,所以须要将原来的start_url注释掉。数据库

class QiubaiSpider(RedisCrawlSpider):
    name = 'qiubai'
    # allowed_domains = ['www.qiushibaike.com/pic/']
    # start_urls = ['http://www.qiushibaike.com/pic//']
    # redis_key表示调度器中的队列(将要爬取的页面数据对应的url都须要放置到调度器队列中)
    redis_key = 'qiubaispider'   # 自定义调度器队列的名称,该行代码表示的含义和start_urls同样

(3)连接提取器和规则解析器定义

class QiubaiSpider(RedisCrawlSpider)
    """代码省略"""    
    # 连接提取器
    # 从页面提取连接页码的url:/pic/page/2?s=5147462
    # s后对应的参数值会在浏览器刷新时动态变化, 正则忽略s参数的变化进行提取
    link = LinkExtractor(allow=r'/pic/page/\d+')
    # 规则解析器
    rules = (
        Rule(link, callback='parse_item', follow=True),
    )

(4)items.py编写和爬虫引入调用

import scrapy

class RedisproItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    img_url =scrapy.Field()

四、settings.py配置修改

(1)使用scrapy-redis组件中封装好的管道

  使用scrapy-redis组件中封装好的能够被共享的管道。
  能够将每台机器爬取到的数据存储经过该管道存储到redis数据库中,从而实现了多台机器的管道共享。windows

# Configure item pipelines
# See https://doc.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
    # 'redisPro.pipelines.RedisproPipeline': 300,
    'scrapy_redis.pipelines.RedisPipeline': 400,
}

(2)使用scrapy-redis组件中封装好的调度器

  使用scrapy-redis组件中封装好的调度器,将全部的url存储到该指定的调度器中,从而实现了多台机器的调度器共享。
  如下代码可在settings.py中任意位置粘贴:浏览器

# 使用scrapy-redis组件的去重队列
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 使用scrapy-redis组件本身的调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"   # 核心配置
# 是否容许暂停
SCHEDULER_PERSIST = True   # 值为True表示:宕机恢复服务时,从宕机的那个地方开始爬取,不用从头开始

(3)爬虫程序不在redis本机时,指定redis地址

  管道默认会链接且将数据存储到本机的redis服务中,若是想要链接存储到其余redis服务中须要在settings.py中进行以下配置bash

# 若是redis服务器不在本身本机,则须要作以下配置
REDIS_HOST = '192.168.31.31' # redis服务的ip地址
REDIS_PORT = 6379
# 可选配置
# REDIS_ENCODING = 'utf-8'
# REDIS_PARAMS = {'password':'123456'}

(4)修改ua和关闭robots协议

# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36' # 假装请求载体身份

# Obey robots.txt rules
ROBOTSTXT_OBEY = False   # 不听从门户网站robots协议,避免某些信息爬取不到

五、执行爬虫程序

  执行爬虫程序的方式与以前不一样。
  格式:lpush 队列名称(redis-key) 起始url服务器

$ pwd
/Users/hqs/ScrapyProjects/redisPro/redisPro/spiders
$ scrapy runspider qiubai.py
.......
2018-12-08 12:04:34 [scrapy.extensions.telnet] DEBUG: Telnet console listening on 127.0.0.1:6023

  而后须要在redis客户端中,将起始url扔到调度器队列中:框架

$ src/redis-cli 
127.0.0.1:6379> lpush qiubaispider https://www.qiushibaike.com/pic/    # 将url扔入队列
(integer) 1

  查看reids中保存的爬取数据:

127.0.0.1:6379> keys *
1) "qiubai:items"
2) "data"
3) "name"
4) "qiubai:dupefilter"
127.0.0.1:6379> lrange qiubai:items 0 -1
   1) "{\"img_url\": \"https://pic.qiushibaike.com/system/pictures/12132/121326116/medium/FO4Z7Q83NXSOPYTL.jpg\"}"
   ......
相关文章
相关标签/搜索