您当前的位置:首页 > 计算机 > 编程开发 > Python

爬虫--Scrapy-redis分布式爬虫(基础)

时间:08-16来源:作者:点击数:
CDSY,CDSY.XYZ

安装scrapy-redis

pip install scrapy-redis -i https://pypi.douban.com/simple

Scrapy-Redis分布式策略

假设有四台电脑:Windows 10、Mac OS X、Ubuntu 16.04、CentOS 7.2,任意一台电脑都可以作
为 Master端 或 Slaver端,比如:

- `Master端`(核心服务器) :使用 Windows 10,搭建一个Redis数据库,不负责爬取,只负责url指
- 纹判重、Request的分配,以及数据的存储
- `Slaver端`(爬虫程序执行端) :使用 Mac OS X 、Ubuntu 16.04、CentOS 7.2,负责执行爬虫程
- 序,运行过程中提交新的Request给Master

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jw33HV2u-16024
25589171)(img/masterAndslaver.png)]

1. 首先Slaver端从Master端拿任务(Request、url)进行数据抓取,Slaver抓取数据的同时,产
2. 生新任务的Request便提交给 Master 处理;
3. Master端只有一个Redis数据库,负责将未处理的Request去重和任务分配,将处理后的Requ
4. est加入待爬队列,并且存储爬取的数据。

Scrapy-Redis默认使用的就是这种策略,我们实现起来很简单,因为任务调度等工作Scrapy-
Redis都已经帮我们做好了,我们只需要继承RedisSpider、指定redis_key就行了。

缺点是,Scrapy-Redis调度的任务是Request对象,里面信息量比较大(不仅包含url,还有ca
llback函数、headers等信息),可能导致的结果就是会降低爬虫速度、而且会占用Redis大量
的存储空间,所以如果要保证效率,那么就需要一定硬件水平。

安装Redis

准备两台电脑  都装redis


master端
可以保证master上面的redis可以被连接
	注意:redis默认配置是不让远程连接,需要注释掉redis.conf配置文件中
		的 #bind 127.0.0.1   #protected-mode no
	
启动master端的redis数据库
	  redis--cli          --启动本地数据库
	  ping				  --检测数据库连接状态,返回PONG,则表示成功

	  set key1 'hello'     -- 存入{'key1':'hello'}
	   





slave端
redis-cli -h 192.168.199.108,-h 参数表示连接到指定主机的redis数据库地址  -p 可以指定端口

	--keys				查询刚才存入的键数据
	-- get key1 	    查询刚才存入的key1的值
	
如果查询到刚才在master端存入的数据则表示配置成功



注意:Slave端无需启动redis-server,Master端启动即可。只要 Slave 端读取到了 Master 端的
 Redis 数据库,则表示能够连接成功,可以实施分布式。

分布式爬虫源码

链接:https://pan.baidu.com/s/16aXPHtePiarEIFATwcILbw 提取码:hhhh 

源码详解

一、dmoz (class DmozSpider(CrawlSpider))

这个爬虫继承的是CrawlSpider,它是用来说明Redis的持续性,当我们第一次运行dmoz爬

虫,然后Ctrl + C停掉之后,再运行dmoz爬虫,之前的爬取记录是保留在Redis里的。

分析起来,其实这就是一个 scrapy-redis 版 CrawlSpider 类,需要设置Rule规则,以及callback

不能写parse()方法。

执行方式:scrapy crawl dmoz

from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
 
 
class DmozSpider(CrawlSpider):
    """Follow categories and extract links."""
    name = 'dmoz'
    allowed_domains = ['dmoztools.net/']
    start_urls = ['http://dmoztools.net/']
 
    rules = [
        Rule(LinkExtractor(
            restrict_css=('.top-cat', '.sub-cat', '.cat-item')
        ), callback='parse_directory', follow=True),
    ]
 
    def parse_directory(self, response):
        for div in response.css('.title-and-desc'):
            yield {
                'name': div.css('.site-title::text').extract_first(),
                'description': div.css('.site-descr::text').extract_first().strip(),
                'link': div.css('a::attr(href)').extract_first(),
        }

二、mycrawler_redis (class MyCrawler(RedisCrawlSpider))

这个RedisCrawlSpider类爬虫继承了RedisCrawlSpider,能够支持分布式的抓取。因为采

用的是crawlSpider,所以需要遵守Rule规则,以及callback不能写parse()方法。

同样也不再有start_urls了,取而代之的是redis_key,scrapy-redis将key从Redis里pop出

来,成为请求的url地址。

from scrapy.spiders import Rule
from scrapy.linkextractors import LinkExtractor

from scrapy_redis.spiders import RedisCrawlSpider


class MyCrawler(RedisCrawlSpider):
    """Spider that reads urls from redis queue (myspider:start_urls)."""

    # 爬虫名
    name = 'mycrawler_redis'
    # redis_key: 类似start_url,但是只是redis的一个key
    # 监听redis中的key
    redis_key = 'mycrawler:start_urls'
    # 允许的域名
    allowed_domains = ['dmoz.org']

    # 规则
   rules = (
    	Rule(LinkExtractor(), callback='parse_page', follow=True),
	)

    # __init__方法必须按规定写,使用时只需要修改super()里的类名参数即可
    def __init__(self, *args, **kwargs):
        # Dynamically define the allowed domains list.
        domain = kwargs.pop('domain', '')
        self.allowed_domains = filter(None, domain.split(','))
 
        # 修改这里的类名为当前类名
        super(MyCrawler, self).__init__(*args, **kwargs)
 
    def parse_page(self, response):
        return {
            'name': response.css('title::text').extract_first(),
            'url': response.url,
   			}



注意:

	同样的,RedisCrawlSpider类不需要写allowd_domains和start_urls:
	
	scrapy-redis将从在构造方法__init__()里动态定义爬虫爬取域范围,也可以选择直接写allowd_domains。
	
	必须指定redis_key,即启动爬虫的命令,参考格式:redis_key = 'myspider:start_urls'
	
	根据指定的格式,start_urls将在 Master端的 redis-cli 里 lpush 到 Redis数据库里,RedisSpider 将在数据
	库里获取start_urls。



执行方式:

	通过runspider方法执行爬虫的py文件(也可以分次执行多条),爬虫(们)将处于等待准备状态:
	
	scrapy runspider mycrawler_redis.py
	
	在Master端的redis-cli输入push指令,参考格式:
	
	$redis > lpush mycrawler:start_urls http://www.dmoz.org/
	
	爬虫获取url,开始执行。

三、myspider_redis (class MySpider(RedisSpider))

这个爬虫继承了RedisSpider, 它能够支持分布式的抓取,采用的是basic spider,需要

写parse函数。

其次就是不再有start_urls了,取而代之的是redis_key,scrapy-redis将key从Redis里po

p出来,成为请求的url地址。

from scrapy_redis.spiders import RedisSpider


class MySpider(RedisSpider):
    """Spider that reads urls from redis queue (myspider:start_urls)."""
    # 爬虫名
    name = 'myspider_redis'
    # redis_key: 类似start_url,但是只是redis的一个key
    # 监听当前爬虫所连接的redis数据库中的指定key为‘myspider:start_urls’是否改变
    redis_key = 'myspider:start_urls'
    # 允许的域名
    allowed_domains = ['dmoz.org']

    def parse(self, response):
        pass


注意:

	RedisSpider类 不需要写allowd_domains和start_urls:
	
	scrapy-redis将从在构造方法__init__()里动态定义爬虫爬取域范围,也可以选择直接
	写allowd_domains。
	
	必须指定redis_key,即启动爬虫的命令,参考格式:redis_key = 'myspider:start_urls'
	
	根据指定的格式,start_urls将在 Master端的 redis-cli 里 lpush 到 Redis数据库里,RedisS
	pider 将在数据库里获取start_urls。


执行方式:
	
	通过runspider方法执行爬虫的py文件(也可以分次执行多条),爬虫(们)将处于等待准备状态:

	scrapy runspider myspider_redis.py
	
	在Master端的redis-cli输入push指令,参考格式:
	
	$redis > lpush myspider:start_urls http://dmoztools.net/
	
	Slaver端爬虫获取到请求,开始爬取。

总结:

如果只是用到Redis的去重和保存功能,就选第一种;

如果要写分布式,则根据情况,选择第二种、第三种;

通常情况下,会选择用第二种方式编写深度聚焦爬虫

CDSY,CDSY.XYZ
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐