14.3 使用scrapy-redis进行分布式爬取
了解了scrapy-redis的原理后,我们学习使用scrapy + scrapyredis进行分布式爬取。
14.3.1 搭建环境
首先搭建scrapy-redis分布式爬虫环境,当前我们有3台Linux 主机。 云服务器(A):116.29.35.201 (Redis Server) 云服务器(B):123.59.45.155 本机(C):1.13.41.127 在3台主机上安装scrapy和scrapy-redis:
$ pip install scrapy $ pip install scrapy-redis
选择其中一台云服务器搭建供所有爬虫使用的Redis数据库,步
247
骤如下:
步骤 01 在云服务器上安装redis-server。
步骤 02 在Redis配置文件中修改服务器的绑定地址(确保数 据库可被所有爬虫访问)。
步骤 03 启动/重启Redis服务器。 登录云服务器(A),在bash中完成上述步骤:
116.29.35.201$ sudo apt-get install redis-server 116.29.35.201$ sudo vi /etc/redis/redis.conf ... # bind 127.0.0.1 bind 0.0.0.0 ... 116.29.35.201$ sudo service redis-server restart
最后,在3台主机上测试能否访问云服务器(A)上的Redis数据 库:
$ redis-cli -h 116.29.35.201 ping PONG
到此,Scrapy分布式爬虫环境搭建完毕。
14.3.2 项目实战
本章的核心知识点是分布式爬取,因此本项目不再对分析页面、 编写Spider等大家熟知的技术进行展示。我们可以任意挑选一个在 之前章节中做过的项目,将其改为分布式爬取的版本,这里以第8章 的toscrape_book项目(爬取books.toscrape.com中的书籍信息) 为例进行讲解。
248
复制toscrape_book项目,得到新项目 toscrape_book_distributed:
$ cp -r toscrape_book toscrape_book_distributed $ cd toscrape_book_distributed
在配置文件settings.py中添加scrapy-redis的相关配置:
# 必选项 # ================================================================= # 指定爬虫所使用的Redis数据库(在云服务器116.29.35.201 上) REDIS_URL = 'redis://116.29.35.201:6379'
# 使用scrapy_redis的调度器替代Scrapy 原版调度器 SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 使用scrapy_redis的RFPDupeFilter作为去重过滤器 DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" # 启用scrapy_redis的RedisPipeline将爬取到的数据汇总到Redis数据库 ITEM_PIPELINES = { 'scrapy_redis.pipelines.RedisPipeline': 300, } # 可选项 # ================================================================= #爬虫停止后,保留/清理Redis中的请求队列以及去重集合 # True:保留,False:清理,默认为False SCHEDULER_PERSIST = True
将单机版本的Spider改为分布式版本的Spider,只需做如下简 单改动:
from scrapy_redis.spiders import RedisSpider
# 1.更改基类 # class BooksSpider(spider.Spider): class BooksSpider(RedisSpider): ...
249
# 2.注释start_urls #start_urls = ['http://books.toscrape.com/'] ...
上述改动针对“如何为多个爬虫设置起始爬取点”这个问题,解 释如下:
● 在分布式爬取时,所有主机上的代码是相同的,如果使用之 前单机版本的Spider代码,那么每一台主机上的Spider都通 过start_urls属性定义了起始爬取点,在构造起始爬取点的 Request对象时,dont_filter参数设置为了True,即忽略去 重过滤器的过滤。因此多个(数量等于爬虫数量)重复请求 将强行进入Redis中的请求队列,这可能导致爬取到重复数 据。
● 为了解决上述问题,scrapy-redis提供了一个新的Spider基 类RedisSpider,RedisSpider重写了start_requests方法, 它尝试从Redis数据库的某个特定列表中获取起始爬取点, 并构造Request对象(dont_filter=False),该列表的键可 通过配置文件设置(REDIS_START_URLS_KEY),默认为 <spider_name>:start_urls。在分布式爬取时,用户运行所 有爬虫后,需手动使用Redis命令向该列表添加起始爬取 点,之后只有其中一个爬虫能获取到起始爬取点,因此对应 的请求也就只有一个,从而避免了重复。 到此,分布式版本的项目代码已经完成了,分发到各个主机:
$ scp -r toscrape_book_distributed liushuo@116.29.35.201:~/scrapy_b $ scp -r toscrape_book_distributed liushuo@123.59.45.155:~/scrapy_b
分别在3台主机使用相同命令运行爬虫:
$ scrapy crawl books
250
2017-05-14 17:56:42 [scrapy.utils.log] INFO: Scrapy 1.3.3 start 2017-05-14 17:56:42 [scrapy.utils.log] INFO: Overridden setting 'scrapy_redis.dupefilter.RFPDupeFilter', 'FEED_EXPORT_FIELDS': ['up 'review_rating', 'review_num'], 'SCHEDULER': 'scrapy_redis.schedule 'toscrape_book', 'ROBOTSTXT_OBEY': True, 'NEWSPIDER_MODULE': 'toscr 'SPIDER_MODULES': ['toscrape_book.spiders']} 2017-05-14 17:56:42 [scrapy.middleware] INFO: Enabled extension ['scrapy.extensions.logstats.LogStats', 'scrapy.extensions.telnet.TelnetConsole', 'scrapy.extensions.corestats.CoreStats'] 2017-05-14 17:56:42 [books] INFO: Reading start URLs from redis 16, encoding: utf-8 2017-05-14 17:56:42 [scrapy.middleware] INFO: Enabled downloade ['scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware', 'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware', 'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutM 'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMid 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware', 'scrapy.downloadermiddlewares.retry.RetryMiddleware', 'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware', 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionM 'scrapy.downloadermiddlewares.redirect.RedirectMiddleware', 'scrapy.downloadermiddlewares.cookies.CookiesMiddleware', 'scrapy.downloadermiddlewares.stats.DownloaderStats'] 2017-05-14 17:56:42 [scrapy.middleware] INFO: Enabled spider mi ['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware', 'scrapy.spidermiddlewares.offsite.OffsiteMiddleware', 'scrapy.spidermiddlewares.referer.RefererMiddleware', 'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware', 'scrapy.spidermiddlewares.depth.DepthMiddleware'] 2017-05-14 17:56:42 [scrapy.middleware] INFO: Enabled item pipe ['scrapy_redis.pipelines.RedisPipeline'] 2017-05-14 17:56:42 [scrapy.core.engine] INFO: Spider opened 2017-05-14 17:56:42 [scrapy.extensions.logstats] INFO: Crawled items (at 0 items/min) 2017-05-14 17:56:42 [scrapy.extensions.telnet] DEBUG: Telnet c ...阻塞在此处...
运行后,由于Redis中的起始爬取点列表和请求队列都是空的, 3个爬虫都进入了暂停等待的状态,因此在任意主机上使用Redis客 户端设置起始爬取点:
$ redis-cli -h 116.29.35.201 116.29.35.201:6379> lpush books:start_urls 'http://books.toscrape.c (integer) 1
251
随后,其中一个爬虫(本实验中是云服务器A)从起始爬取点列 表中获取到了url,在其log中观察到如下信息:
2017-05-14 17:57:18 [books] DEBUG: Read 1 requests from 'books:star
该爬虫用起始爬取点url构造的Request对象最终被添加到Redis 中的请求队列之后。各个爬虫相继开始工作了,可在各爬虫的log中 观察到类似于如下的信息:
2017-05-14 18:00:42 [scrapy.core.scraper] DEBUG: Scraped from http://books.toscrape.com/catalogue/arena_587/index.html> {'name': 'Arena', 'price': '£21.36', 'review_num': '0', 'review_rating': 'Four', 'stock': '11', 'upc': '2c34f9432069b52b'} 2017-05-14 18:00:42 [scrapy.core.engine] DEBUG: Crawled (200) http://books.toscrape.com/catalogue/page-21.html) 2017-05-14 18:00:42 [scrapy.core.scraper] DEBUG: Scraped from http://books.toscrape.com/catalogue/adultery_586/index.html> {'name': 'Adultery', 'price': '£20.88', 'review_num': '0', 'review_rating': 'Five', 'stock': '11', 'upc': 'bb967277222e689c'} 2017-05-14 18:00:42 [scrapy.core.engine] DEBUG: Crawled (200) http://books.toscrape.com/catalogue/page-21.html) 2017-05-14 18:00:42 [scrapy.core.scraper] DEBUG: Scraped from http://books.toscrape.com/catalogue/a-mothers-reckoning-living-in-t l> {'name': "A Mother's Reckoning: Living in the Aftermath of Tra 'price': '£19.53', 'review_num': '0', 'review_rating': 'Three', 'stock': '11', 'upc': '2b69dec0193511d9'} 2017-05-14 18:00:43 [scrapy.core.scraper] DEBUG: Scraped from http://books.toscrape.com/catalogue/112263_583/index.html> {'name': '11/22/63', 'price': '£48.48', 'review_num': '0',
252
'review_rating': 'Three', 'stock': '11', 'upc': 'a9d7b75461084a26'} 2017-05-14 18:00:43 [scrapy.core.engine] DEBUG: Crawled (200) http://books.toscrape.com/catalogue/page-21.html) 2017-05-14 18:00:43 [scrapy.core.scraper] DEBUG: Scraped from http://books.toscrape.com/catalogue/10-happier-how-i-tamed-the-voic losing-my-edge-and-found-self-help-that-actually-works_582/index.ht {'name': '10% Happier: How I Tamed the Voice in My Head, Reduc 'Without Losing My Edge, and Found Self-Help That Actu 'price': '£24.57', 'review_num': '0', 'review_rating': 'Two', 'stock': '10', 'upc': '34669b2e9d407d3a'}
等待全部爬取完成后,在Redis中查看爬取到的数据:
116.29.35.201:6379> keys * 1) "books:items" 2) "books:dupefilter" 116.29.35.201:6379> llen books:items (integer) 1000 116.29.35.201:6379> LRANGE books:items 0 4 1) "{\"stock\": \"22\", \"review_num\": \"0\", \"upc\": \"a897 the Attic\", \"review_rating\": \"Three\", \"price\": \"\\u00a351.7 2) "{\"stock\": \"20\", \"review_num\": \"0\", \"upc\": \"e00e Objects\", \"review_rating\": \"Four\", \"price\": \"\\u00a347.82\" 3) "{\"stock\": \"20\", \"review_num\": \"0\", \"upc\": \"90fa Velvet\", \"review_rating\": \"One\", \"price\": \"\\u00a353.74\"}" 4) "{\"stock\": \"20\", \"review_num\": \"0\", \"upc\": \"6957 \"Soumission\", \"review_rating\": \"One\", \"price\": \"\\u00a350. 5) "{\"stock\": \"19\", \"review_num\": \"0\", \"upc\": \"2597 Little Secrets of Getting Your Dream Job\", \"review_rating\": \"Fo 116.29.35.201:6379> LRANGE books:items -5 -1 1) "{\"name\": \"Shameless\", \"price\": \"\\u00a358.35\", \"r \"c068c013d6921fea\", \"review_num\": \"0\", \"stock\": \"1\"}" 2) "{\"stock\": \"1\", \"review_num\": \"0\", \"upc\": \"19fec Devotion (The Regency Spies of London #1)\", \"review_rating\": \"F 3) "{\"stock\": \"1\", \"review_num\": \"0\", \"upc\": \"f684a (Women's Murder Club #1)\", \"review_rating\": \"One\", \"price\": 4) "{\"stock\": \"1\", \"review_num\": \"0\", \"upc\": \"228ba to See Before You Die\", \"review_rating\": \"Five\", \"price\": \" 5) "{\"name\": \"Girl in the Blue Coat\", \"price\": \"\\u00a3 \"upc\": \"41fc5dce044f16f5\", \"review_num\": \"0\", \"stock\": \"
253
如上所示,我们成功地爬取到了1000项数据(由各爬虫最后的 log信息得知,爬虫A:514项,爬虫B:123项,爬虫C:363项)。每一 项数据以json形式存储在Redis的列表中,需要使用这些数据时,可 以编写Python程序将它们从Redis中读出,代码框架如下:
import redis import json
ITEM_KEY = 'books:items'
def process_item(item): # 添加处理数据的代码 ...
def main(): r = redis.StrictRedis(host='116.29.35.201', port=6379) for _ in range(r.llen(ITEM_KEY)): data = r.lpop(ITEM_KEY) item = json.loads(data.decode('utf8')) process_item(item)
if __name__ == '__main__': main()
到此,我们完成了分布式爬取的项目。

scrapy--分布式爬虫的更多相关文章

  1. 第三百五十六节,Python分布式爬虫打造搜索引擎Scrapy精讲—scrapy分布式爬虫要点

    第三百五十六节,Python分布式爬虫打造搜索引擎Scrapy精讲—scrapy分布式爬虫要点 1.分布式爬虫原理 2.分布式爬虫优点 3.分布式爬虫需要解决的问题

  2. scrapy分布式爬虫scrapy_redis二篇

    =============================================================== Scrapy-Redis分布式爬虫框架 ================ ...

  3. scrapy分布式爬虫scrapy_redis一篇

    分布式爬虫原理 首先我们来看一下scrapy的单机架构:     可以看到,scrapy单机模式,通过一个scrapy引擎通过一个调度器,将Requests队列中的request请求发给下载器,进行页 ...

  4. scrapy 分布式爬虫- RedisSpider

    爬去当当书籍信息 多台机器同时爬取,共用一个redis记录 scrapy_redis 带爬取的request对象储存在redis中,每台机器读取request对象并删除记录,经行爬取.实现分布式爬虫 ...

  5. Scrapy分布式爬虫,分布式队列和布隆过滤器,一分钟搞定?

    使用Scrapy开发一个分布式爬虫?你知道最快的方法是什么吗?一分钟真的能 开发好或者修改出 一个分布式爬虫吗? 话不多说,先让我们看看怎么实践,再详细聊聊细节~ 快速上手 Step 0: 首先安装 ...

  6. 三十五 Python分布式爬虫打造搜索引擎Scrapy精讲—scrapy分布式爬虫要点

    1.分布式爬虫原理 2.分布式爬虫优点 3.分布式爬虫需要解决的问题

  7. Scrapy分布式爬虫打造搜索引擎- (二)伯乐在线爬取所有文章

    二.伯乐在线爬取所有文章 1. 初始化文件目录 基础环境 python 3.6.5 JetBrains PyCharm 2018.1 mysql+navicat 为了便于日后的部署:我们开发使用了虚拟 ...

  8. Centos7__Scrapy + Scrapy_redis 用Docker 实现分布式爬虫

    原理:其实就是用到redis的优点及特性,好处自己查--- 1,scrapy 分布式爬虫配置: settings.py BOT_NAME = 'first' SPIDER_MODULES = ['fi ...

  9. 基于Python,scrapy,redis的分布式爬虫实现框架

    原文  http://www.xgezhang.com/python_scrapy_redis_crawler.html 爬虫技术,无论是在学术领域,还是在工程领域,都扮演者非常重要的角色.相比于其他 ...

  10. Python爬虫从入门到放弃(二十)之 Scrapy分布式原理

    关于Scrapy工作流程回顾 Scrapy单机架构 上图的架构其实就是一种单机架构,只在本机维护一个爬取队列,Scheduler进行调度,而要实现多态服务器共同爬取数据关键就是共享爬取队列. 分布式架 ...

随机推荐

  1. js中const、let、var的区别

    今天第一次遇到const定义的变量,查阅了相关资料整理了这篇文章.主要内容是:js中三种定义变量的方式const, var, let的区别. 1.const定义的变量不可以修改,而且必须初始化. 1 ...

  2. ACM-ICPC World Finals 2019 G.First of Her Name

    题意:给一颗字典树,m次查询,每次给出一个字符串,问你该字符串是字典树上多少串的后缀 题解:字典树求广义sam,每次把查询串在sam上跑一遍,最后到达的点的sz就是答案,中途没法走了,就是没有出现过 ...

  3. shiro中记住我功能

    Shiro提供了记住我(RememberMe)的功能,比如访问如淘宝等一些网站时,关闭了浏览器下次再打开时还是能记住你是谁,下次访问时无需再登录即可访问,基本流程如下: 1.首先在登录页面选中Reme ...

  4. React文档(四)渲染元素

    元素是React应用的最小单位. 一个React元素描述了你在屏幕上所看到的东西: const element = <h1>Hello, world</h1>; 和浏览器页面中 ...

  5. Spring注解之@Retention

    作用是定义被它所注解的注解保留多久,一共有三种策略,定义在RetentionPolicy枚举中: package java.lang.annotation; /** * Annotation rete ...

  6. [CodeForces - 614A] A - Link/Cut Tree

    A - Link/Cut Tree Programmer Rostislav got seriously interested in the Link/Cut Tree data structure, ...

  7. 主流Linux发行版简介

    发行版 包格式 所属厂商 发布年份 最新版本 说明 RHEL RPM RedHat 2004 7.3 RedHat Linux9.0后的企业方向,系统可以免费下载安装但无法使用官方yum源 Fedor ...

  8. Oracle 如何循环查询结果集,进行新增或修改

    Oracle的PL/SQL中怎样循环查询的结果集,然后根据查询结果进行判断,是新增或修改操作 loop循环例子 for item in (select a,b,c from table_a where ...

  9. sql 中,如何获取两个日期之前月数、周数、天数

    1.获取两个日期之间的月数.周数.天数语法 --1.获取两个日期之间的月数.周数.天数 --1.1)声明参数 ) ) --1.2)获取两个日期直接的月数 select DATEDIFF(MM,@sta ...

  10. 快递小哥逆袭自传:用了6年时间做到了IT部门主管

    在我30岁生日那天,终于收到升职的通知,自己如愿的也从一名小小程序员升职成为IT主管,负责公司硬件设备驱动程序开发项目,工资也从原来月薪10K变到现在月薪20K.或许对于很多人而言,在三十岁的时候,可 ...