爬虫之scrapy-redis
redis分布式部署
scrapy框架是否可以自己实现分布式?
不可以原因有两点
- 其一:因为多台机器上部署的scrapy会各自拥有各自的调度器,这样就使得多台机器无法分配start_urls列表中的url。(多台机器无法共享同一个调度器)
- 其二:多台机器爬取到的数据无法通过同一个管道对数据进行统一的数据持久出存储。(多台机器无法共享同一个管道)
基于scrapy-redis组件的分布式爬虫
scrapy-redis组件中为我们封装好了可以被多台机器共享的调度器和管道,我们可以直接使用并实现分布式数据爬取
实现方式:
- .基于该组件的RedisSpider类 ==》基于该组件的RedisCrawlSpider类
分布式实现流程:
- 一.修改爬虫文件
- .导入scrapy-redis模块:from scrapy_redis.spiders import RedisSpider
- .将当前爬虫类的父类修改成RedisSpider
- .将allowed_domains和start_urls进行删除
- .添加一个新的属性redis_key = 'xxx',该属性值表示的就是可以被共享的调度器队列的名称
- 二.进行配置文件的配置
- .保证爬虫文件发起的请求都会被提交到可以被共享的调度器的队列中
- SCHEDULER = "scrapy_redis.scheduler.Scheduler"
2.确保所有爬虫共享相同的去重指纹
DUPEFILTER = "scrapy_redis.dupefilter.RFPDuperFilter"- .保证爬虫文件提交的item会被存储到可以被共享的管道中
- ITEM_PIPELINES = {
- 'scrapy_redis.pipelines.RedisPipeline':
- }
4. 在redis中保持scrapy-redis用到的队列,不会清理redis中的队列,从而实现暂停和恢复功能
SCHEDULER_PERSTST = True- .配置最终数据存储的redis数据库
- REDIS_HOST = 'redis服务的ip地址'
- REDIS_PORT =
- REDIS_ENCODING = ‘utf-’
- REDIS_PARAMS = {‘password’:’’}
- .redis数据库的配置文件进行配置:关闭保护模式和 改bind 0.0.0.0
- 7.开启redis服务和客户端
- 8.执行爬虫文件:scrapy runspider xxx.py
- 9.向调度器队列中仍入一个起始的url:
代码如下
1.创建项目和应用
- scrapy start project redisDemo
- cd redisDemo
- scrapy genspider testDemo
- # -*- coding: utf- -*-
- import scrapy
- from scrapy_redis.spiders import RedisSpider
- from redisDemo.items import RedisdemoItem
- '''
- 一.修改爬虫文件
- .导入scrapy-redis模块:from scrapy_redis.spiders import RedisSpider
- .将当前爬虫类的父类修改成RedisSpider
- .将allowed_domains和start_urls进行删除
- .添加一个新的属性redis_key = 'xxx',该属性值表示的就是可以被共享的调度器队列的名称
- 二.进行配置文件的配置
- .保证爬虫文件发起的请求都会被提交到可以被共享的调度器的队列中
- SCHEDULER = "scrapy_redis.scheduler.Scheduler"
- .保证爬虫文件提交的item会被存储到可以被共享的管道中
- ITEM_PIPELINES = {
- 'scrapy_redis.pipelines.RedisPipeline':
- }
- .配置最终数据存储的redis数据库
- REDIS_HOST = 'redis服务的ip地址'
- REDIS_PORT =
- REDIS_ENCODING = ‘utf-’
- REDIS_PARAMS = {‘password’:’’}
- .redis数据库的配置文件进行配置:关闭保护模式和 改bind 0.0.0.0
- .开启redis服务和客户端
- .执行爬虫文件:scrapy runspider xxx.py
- .向调度器队列中仍入一个起始的url:
- '''
- class TestdemoSpider(RedisSpider):
- name = 'testDemo'
- # allowed_domains = ['www.x.com'] # 不注释可能会出问题
- # start_urls = ['http://www.x.com/'] # 起始url需手动输入
- redis_key = 'cmdb' # 表示的就是可以被共享的调度器队列的名称
- url = 'http://db.pharmcube.com/database/cfda/detail/cfda_cn_instrument/%d' # 所有的url
- page = # 生成所有url的公共变量
- def parse(self, response):
- item = RedisdemoItem() # 实例化item
- item['num'] = response.xpath('/html/body/div/table/tbody/tr[1]/td[2]/text()').extract_first()
- item['company_name'] = response.xpath('//html/body/div/table/tbody/tr[2]/td[2]/text()').extract_first()
- item['company_address'] = response.xpath('/html/body/div/table/tbody/tr[3]/td[2]/text()').extract_first()
- yield item
- urls = []
- if self.page < :
- self.page +=
- new_url = format(self.url % self.page)
- yield scrapy.Request(url=new_url, callback=self.parse)
testDemo.py
- import scrapy
- class RedisdemoItem(scrapy.Item):
- # define the fields for your item here like:
- num = scrapy.Field()
- company_name = scrapy.Field()
- company_address = scrapy.Field()
items.py
- BOT_NAME = 'redisDemo'
- SPIDER_MODULES = ['redisDemo.spiders']
- NEWSPIDER_MODULE = 'redisDemo.spiders'
- # Crawl responsibly by identifying yourself (and your website) on the user-agent
- # USER_AGENT = 'redisDemo (+http://www.yourdomain.com)'
- # Obey robots.txt rules
- ROBOTSTXT_OBEY = False
- USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
- # 使用的是可以被共享的调度器
- # 增加了一个去重容器类的配置, 作用使用Redis的set集合来存储请求的指纹数据, 从而实现请求去重的持久化
- DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
- # 使用scrapy-redis组件自己的调度器
- SCHEDULER = "scrapy_redis.scheduler.Scheduler"
- # 配置调度器是否要持久化, 也就是当爬虫结束了, 要不要清空Redis中请求队列和去重指纹的set。如果是True, 就表示要持久化存储, 就不清空数据, 否则清空数据
- SCHEDULER_PERSIST = True
- # 使用scrapy-redis中封装好的可以被共享的管道
- ITEM_PIPELINES = {
- 'scrapy_redis.pipelines.RedisPipeline':
- }
- # 配置redis
- REDIS_HOST = '192.168.12.57' # ip
- REDIS_PORT = # 端口
- REDIS_ENCODING = 'utf-8' # 编码
- # REDIS_PARAMS = {‘password’:’’} # 密码 没有就不写了
settings.py
redis配置
- 开启redis服务和客户端
net start redis
- 在爬虫应用目录下执行爬虫文件:(多台机器启动)
scrapy runspider xxx.py
- 需要向调度器队列中仍入一个起始的url:(不要在开启新机器了)
在redis-cli中输入- lpush cmdb http://db.pharmcube.com/database/cfda/detail/cfda_cn_instrument/1
- 查看内容: lrange testDemo:items 0 -1
- ok,结束
增量爬取
无非判断发送请求的url或者在数据存入时候的关键字判断
- # -*- coding: utf- -*-
- import scrapy
- from scrapy.linkextractors import LinkExtractor
- from scrapy.spiders import CrawlSpider, Rule
- from incrementDemo.items import IncrementdemoItem
- from redis import Redis
- import hashlib
- class QiubaiSpider(CrawlSpider):
- name = 'qiubai'
- # allowed_domains = ['www.x.com']
- start_urls = ['https://www.qiushibaike.com/text/']
- rules = (
- Rule(LinkExtractor(allow=r'/text/page/\d+/'), callback='parse_item', follow=True), # 所有页面
- Rule(LinkExtractor(allow=r'/text/$'), callback='parse_item', follow=True), # 第一页面
- )
- # 创建redis链接对象
- conn = Redis(host='127.0.0.1', port=)
- def parse_item(self, response):
- div_list = response.xpath('//div[@id="content-left"]/div') # 获取内容标签列表
- for div in div_list:
- item = IncrementdemoItem()
- item['author'] = div.xpath('./div[1]/a[2]/h2/text() | ./div[1]/span[2]/h2/text()').extract_first() # 作者
- item['content'] = div.xpath('.//div[@class="content"]/span/text()').extract_first() # 内容
- # 将解析到的数据值生成一个唯一的标识进行redis存储
- source = item['author'] + item['content']
- source_id = hashlib.sha256(source.encode()).hexdigest()
- # 将解析内容的唯一表示存储到redis的data_id中
- ex = self.conn.sadd('data_id', source_id)
- if ex == :
- print('该条数据没有爬取过,可以爬取......')
- yield item
- else:
- print('该条数据已经爬取过了,不需要再次爬取了!!!')
爬虫文件
items和管道
- import scrapy
- class IncrementdemoItem(scrapy.Item):
- # define the fields for your item here like:
- author = scrapy.Field()
- content = scrapy.Field()
items.py
- from redis import Redis
- import json
- class IncrementdemoPipeline(object):
- conn = None
- def open_spider(self, spider):
- self.conn = Redis(host='127.0.0.1', port=)
- def process_item(self, item, spider):
- dic = {
- 'author': item['author'],
- 'content': item['content']
- }
- # print(dic)
- self.conn.lpush('qiubaiData', json.dumps(dic))
- return item
管道
- ROBOTSTXT_OBEY = False
- USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'
- ITEM_PIPELINES = {
- 'incrementDemo.pipelines.IncrementdemoPipeline': ,
- }
settings.py
爬虫之scrapy-redis的更多相关文章
- 基于Python,scrapy,redis的分布式爬虫实现框架
原文 http://www.xgezhang.com/python_scrapy_redis_crawler.html 爬虫技术,无论是在学术领域,还是在工程领域,都扮演者非常重要的角色.相比于其他 ...
- 爬虫系列----scrapy爬取网页初始
一 基本流程 创建工程,工程名称为(cmd):firstblood: scrapy startproject firstblood 进入工程目录中(cmd):cd :./firstblood 创建爬虫 ...
- Python爬虫框架Scrapy教程(1)—入门
最近实验室的项目中有一个需求是这样的,需要爬取若干个(数目不小)网站发布的文章元数据(标题.时间.正文等).问题是这些网站都很老旧和小众,当然也不可能遵守 Microdata 这类标准.这时候所有网页 ...
- python爬虫之Scrapy学习
在爬虫的路上,学习scrapy是一个必不可少的环节.也许有好多朋友此时此刻也正在接触并学习scrapy,那么很好,我们一起学习.开始接触scrapy的朋友可能会有些疑惑,毕竟是一个框架,上来不知从何学 ...
- 爬虫07 /scrapy图片爬取、中间件、selenium在scrapy中的应用、CrawlSpider、分布式、增量式
爬虫07 /scrapy图片爬取.中间件.selenium在scrapy中的应用.CrawlSpider.分布式.增量式 目录 爬虫07 /scrapy图片爬取.中间件.selenium在scrapy ...
- 爬虫06 /scrapy框架
爬虫06 /scrapy框架 目录 爬虫06 /scrapy框架 1. scrapy概述/安装 2. 基本使用 1. 创建工程 2. 数据分析 3. 持久化存储 3. 全栈数据的爬取 4. 五大核心组 ...
- python爬虫使用scrapy框架
scrapy框架提升篇 关注公众号"轻松学编程"了解更多 1.创建启动爬虫脚本 在项目目录下创建start.py文件: 添加代码: #以后只要运行start.py就可以启动爬虫 i ...
- 爬虫框架-scrapy的使用
Scrapy Scrapy是纯python实现的一个为了爬取网站数据.提取结构性数据而编写的应用框架. Scrapy使用了Twisted异步网络框架来处理网络通讯,可以加快我们的下载速度,并且包含了各 ...
- Python逆向爬虫之scrapy框架,非常详细
爬虫系列目录 目录 Python逆向爬虫之scrapy框架,非常详细 一.爬虫入门 1.1 定义需求 1.2 需求分析 1.2.1 下载某个页面上所有的图片 1.2.2 分页 1.2.3 进行下载图片 ...
- 教你分分钟学会用python爬虫框架Scrapy爬取心目中的女神
本博文将带领你从入门到精通爬虫框架Scrapy,最终具备爬取任何网页的数据的能力.本文以校花网为例进行爬取,校花网:http://www.xiaohuar.com/,让你体验爬取校花的成就感. Scr ...
随机推荐
- 使用Docker安装ELK系列(超简单)
root权限 docker版本:1.13.1 ELK版本:6.4.3 项目中均关闭X-Pack 一.安装Elasticsearch 新建elasticsearch目录,并再其下新建文件config/e ...
- 12C数据库ORA-40365: The SYS user cannot be locked while the password file is in its current format
[环境介绍] 系统环境:Solaris + Oracle 12CR2 [背景描述] 基于集团数据库安全检查项,需要把sys用户锁定或者修改复杂口令整改. 在整改前已经对参数remote_login ...
- HTTP常见的状态码——面试题常考
一些常见的状态码为: 200 - 服务器成功返回网页 400(错误请求)服务器不理解请求的语法. 404 - 请求的网页不存在 500(服务器内部错误)服务器遇到错误,无法完成请求. 503 - 服 ...
- AB PLC首次IP地址如何分配
AB PLC首次IP地址如何分配,这里介绍的方法是针对CompactLogix和ControlLogix控制器 一.准备工作 AB PLC控制器一台,本文以5069-L330ER为例,将其通电: 笔记 ...
- Spring Cloud 2-Config 分布式配置中心(七)
Spring Cloud Config 1.github配置 2.服务端配置 pom.xml application.xml Application.java 3.配置和命名 1. 配置加载顺序 ...
- java学习笔记04-基本数据类型
编写一款可用的软件,离不开对数据的操作(经常有人说:程序=数据+算法).数据可能有很多类型,比如对于年龄来说,数据就是整数. 对于金额来,数据是带小数的.在java中,可以分为内置数据类型和引用数据类 ...
- 安装 python pip Django
python 安装 1. 官网下载:以 window 为例,按提示下载,版本号根据实际需求选择: 2. 选择路径,安装完成后,命令行输入 python 检测是否安装成功,下图为安装成功显示:quit( ...
- ffmpeg推流方式采用TCP协议
ffmpeg默认推流方式采用UDP方式,若需要使用TCP协议,则需要修改. 1.使用命令时: ffmpeg 跟参数 -rtsp_transport tcp 2.编码时 AVFormatContext ...
- 【easy】671. Second Minimum Node In a Binary Tree
Given a non-empty special binary tree consisting of nodes with the non-negative value, where each no ...
- 【easy】653. Two Sum IV - Input is a BST
BST树求得两个节点的和是target //因为是BST所以中序遍历得到的是递增数组 //这个题的方法就是在一个递增数组中找到两个数的和相加是目标结果 /** * Definition for a b ...