爬虫之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 ...
随机推荐
- c语言变量及输入输出
scanf: 格式字符串的一般形式:%[*][输入数据宽度][长度] 类型 (其中有方括号[] 的项为任选项.) 各项意义: 1) 类型:表示输入数据的类型,其格式符和意义如下表所示. ...
- 利用JS写一个计算平方的网页
<!-- 计算一个数的平方并显示出来 --> <!DOCTYPE html> <html> <head> <meta charset=" ...
- 毕业设计——django中的render()与redirect()问题
1. redirect()时需要传递数据,在网上找到的方法是通过session传递数据,但是个人认为用session传递数据并不合适,session一般用于权限验证数据的传递... 2. render ...
- 迅为IMX6Q PLUS开发板烧写Android6.0系统方法
平台:迅为IMX6Q PLUS开发板工具:MfgTool2 工具 镜像文件在光盘目录“03 镜像_android 6.0.1 文件系统”下.其中商业级核心板为 2G内存镜像,工业级核心板为 1G 内存 ...
- Groovy里面闭包中变量符号的查找与变量定义的限制
class a { def v1 = "v1 in a" static def v2 = "v2 in a" def v4 = "v4 in a&qu ...
- Python爬虫之12306-买票器小白源码
研究不易 import requests import re import urllib.parse import json import datetime from collections impo ...
- 第十四节,OpenCV学习(三)图像的阈值分割
图像的阈值处理 图像的阈值分割:图像的二值化(Binarization) 阈值分割法的特点是:适用于目标与背景灰度有较强对比的情况,重要的是背景或物体的灰度比较单一,而且总可以得到封闭且连通区域的边界 ...
- Beta 冲刺(5/7)
目录 摘要 团队部分 个人部分 摘要 队名:小白吃 组长博客:hjj 作业博客:beta冲刺(5/7) 团队部分 后敬甲(组长) 过去两天完成了哪些任务 ppt制作中 数据集标注 接下来的计划 制作p ...
- 【easy】438.Find All Anagrams in a String 找出字符串中所有的变位词
Input: s: "abab" p: "ab" Output: [0, 1, 2] Explanation: The substring with start ...
- Kubernetes的十大使用技巧
1. bash针对kubectl命令的自动补充这可能是在使用Kubernetes过程中最容易做的事,但它也是其中一个最有用的.要添加自动补充功能,如果使用bash,只需执行以下命令: echo &qu ...