免责声明:本文仅做分享...
目录
scrapy分布式爬虫
分布式: 需要搭建一个分布式的机群,让机群中的每一台电脑去执行同一组程序,对同一组资源进行联合且分布的数据爬取.
多台电脑同时工作,更快的完成任务,即是其中一台电脑出问题了,其它电脑还能继续工作, 任务不会因此而终止.
如果多个项目(多台电脑有相同的项目)同时访问一个url,数据是不会共享的,就意味着三个项目爬取到的是所有 的数据,重复三份。有时候想要进行提高效率.
原来的scrapy框架无法实现分布式:
调度器是独有的(一个项目一个调度器),没有办法实现共享.
可以让多个相同项目启动时,爬取到的数据不重复,最终只需要一份总数据就可以了.
--更快, 更强 .
选择使用reids作为共享调度器,实现分布式的任务共享!!!
伪分布式
一台电脑, 多个终端, 跑相同的项目.
redis
select 索引(有16个库,0-15代表索引,不执行这条语句就是0)
5大数据类型.
自己安装
快速学习使用
字 符 串 类 型
列 表 类 型
hash 类型
购物车的数据,
hash类型:
键 值
字段和值
user username coco age 18
添加数据
hset 键 字段 值
hset user username coco
hset user age 18
查询
hget 键 字段
根据键查询所有字段
hkeys 键
根据键查询所有字段得的值
hvals 键
删除某个键的某个字段
hdel 键 字段【可选多个】
nil 空:None null
添加多个
hmset 键 字段名 值 字段名 值 【可以作为追加,也可以一次添加一个,也可以一次添加多个】
获取多个
hmget 键 字段名 【可选多个】
hlen 键
set 类型
set类型 集合(无序且唯一)
添加数据
sadd 键 值1 值2 值3
查询数据
smembers 键
删除数据(随机删除)
spop 键 【个数】
指定删除数据
srem 键 指定数据【可以同时删除多个数据】
求交集 :获取两个键中相同的值
sinter 键1 键2
求并集:获取两个键中的所有值(重复的只保留一个)
sunion 键1 键2
求差集:
sdiff 键1 键2
zset 类型
Sorted Set (有序~)
set和hash的结合体 都不允许重复的成员出现在一个Set中。它们之间的主要差别是Sorted-Set中的每一个成员都会有一个分数(score)与 之关联,Redis正是通过分数来为集合中的成员进行从小到大的排序。Sorted-Set中的成员必须是唯一的,但是分数
(score)却是可以重复的.
有顺序的集合类型
zset(set+hash的结合体)
添加数据
zadd 键 分数 数据 分数 数据
zadd zs1 11 11
获取所有数据,显示数据的顺序是按照分数值从小到大进行排序
zrange 键 开始索引 结束索引
分数值从大到小排序
zrevrange 键 开始索引 结束索引
通过分数值查询范围
zrangebyscore 键 最小 最大
查询指定分值范围的数据个数
zcount 键 最小 最大
查看某个数据的分值
zscore 键 分数对应的数据
删除数据
zrem 键 分数对应的数据
小结:
5大数据类型结构:
字符串:1: 1
列表:1: 1 2 3 4
哈希:1: 字段:2 2:3
集合:1: 1 2 3 4
有序集合: 1: 分数:2 2:3
scrapy-redis
scrapy-redis:可以给原本的scrapy框架提供共享的调度器.
安装第三方库:
pip install scrapy-redis
settings.py配置:
ip 为 redis 服务的.
# 指定连接的redis数据库的ip地址和端口号.
REDIS_URL = "redis://127.0.0.1:6379"
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 开启redis的持久化.
SCHEDULER_PERSIST = True
REDIS_URL = 'redis://127.0.0.1:6379' # 连接redis
#或者
# REDIS_HOST = '127.0.0.1'
# REDIS_PORT = 6379
# 指定去重方式 给请求对象去重
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" # 指定那个去重方法给request对象去
重
# 设置公共调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
SCHEDULER_PERSIST = True
spider文件修改:
如果要使用scrapyredis
原本spider继承的是CrawlSpider,需要更改为RedisCrawlSpider
原本spider继承的是Spider,需要更改为RedisSpider
注释allowed_domains , start_urls
定义:redis_key='保存到redis的键'
redis数据库添加 键 值
开启redis服务, 执行命令:
127.0.0.1:6379> lpush xj https://www.xjie.edu.cn/tzgg1.htm
(integer) 1
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379> lrange xj 0 -1
1) "https://www.xjie.edu.cn/tzgg1.htm"
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379> keys *
1) "111"
2) "xj:dupefilter"
3) "key"
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379> del xj:dupefilter
(integer) 1
127.0.0.1:6379>
127.0.0.1:6379> keys *
1) "111"
2) "key"
127.0.0.1:6379>
爬完后会生成目标url的指纹 , 以后就不再爬取.
--如果下一次要重新爬,就要删除此指纹. del xj:dupefilter
启动
开终端 -- > scrapy crawl xj
数据解析时 yield item 对象, 由管道自定义保存.
--保存方式 该怎么写怎么写 ~
scrapy总结
'''
如何创建scrapy
scrapy startproject 项目名
cd 项目名
scrapy genspider 爬虫名 爬虫名.com
执行爬虫
scrapy crawl 爬虫名
流程:
1= 改动settings.py
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,
like Gecko) Chrome/125.0.0.0 Safari/537.36'
ROBOTSTXT_OBEY = False # 不遵循
LOG_LEVEL = 'ERROR'
2= 改动spider下的爬虫名.py
class BaiduSpider(scrapy.Spider):
name = "baidu" # 爬虫的名字
# allowed_domains = ["baidu.com"] # 允许的域名
start_urls = ["请求url"]
scrapy启动之后,引擎会从spider获取start_url 自动发起请求。
最后请求成功,得到响应对象叫给了spider类的parse方法
def parse(self, response): # response为响应对象
二进制数据
response.content
json数据
response.json()
html源代码数据
response.text
如果是二进制数据,直接保存
如果是json数据,先通过字典的操作获取到想要的数据值
如果是 html源代码,先通过xpath的操作获取到想要的数据值
response.xpath(’xpath表达式‘).get() 获取对象的data属性值 url
response.xpath(’xpath表达式‘).getall() 返回的是一个列表,[url]
3= 基于管道保存
1- 解析出来数据(实际要保存的数据)
2 -在items.py创建一个类 类中的属性为
数据名 = scrapy.Field()
3- 解析数据的位置创建 items类型对象,再通过字典的操作把数据存入
items = items对象
items[数据名] = 数据值
4- yield items 把items对象提交给管道
5- 在pipelines.py中创建管道类。编写对应的保存代码吧数据进行保存
1- 保存到文本文件中
2- 保存到excel中
3- 保存到mysql中
open_spider: 爬虫开启的时候执行 只执行一次
打开文件
创建数据库连接
创建工作簿
process_item: 只要yield一条数据,就执行一次
执行代码保存的
写入
insert
append
close_spider:爬虫结束的时候执行 只执行一次
关闭文件
关闭连接
保存文件
4= 需要在settings中开启管道
管道类可以同时设置多个,一份数据可以保存到文本文件 可以保存到数据库 保存到excel
只需要设置一个优先级数字,数字越小优先级越大。
如果设置了多个管道,在管道类中process_item方法中加入return 把数据再返回给下一个管道
分页,详情页
结合手动发起请求
1- 把当前得到的分页url或者详情页url 交给yield scrapy.Request(url=请求的url,callback=回调方
法,meta={'item':item})
在回调方法中写的就是针对分页url或者详情页的url 进行数据解析
2- 把得到的url存入start_urls中,这样就不需要手动发起请求,自动发起。解析方法是parse
配合spider类的子类Crawlspider
spider类继承crawlspider
指定连接提取器
rules = (Rule(LinkExtractor(allow=r'正则匹配'), callback="回调方法", follow=False),
Rule(LinkExtractor(allow=r'正则匹配'), callback="回调方法", follow=True)
)
follow
为True 设置继续追踪
为False 设置不追踪
中间件:
篡改请求或者响应
scrapy-redis:
分工协作,共同抓取同一份数据
1- settings.py
# 指定调度器 存储到redis
SCHEDULER = 'scrapy_redis.scheduler.Scheduler'
# 确保所有spider通过redis共享相同的重复过滤器
DUPEFILTER_CLASS = 'scrapy_redis.dupefilter.RFPDupeFilter'
# 指定redis连接
REDIS_URL = 'redis://127.0.0.1:6379'
2- 改动spider
继承改动
把start_urls去掉
加入redis_key = 键
3- 去redis中加入列表数据
lpush 键 请求的url
测试scrapy-redis
注意顺序,先去redis添加 再执行scrapy