scrapy 实现生成指纹的方法
默认使用sha1加密了请求方法,请求体,和请求url地址,得到16进制字符串
fp = hashlib.sha1()
fp.update(to_bytes(request.method))
fp.update(to_bytes(canonicalize_url(request.url)))
fp.update(request.body or b'')
cache[include_headers] = fp.hexdigest() #指纹
要查看数据是否存在于redis的集合中,如果不存在就插入
added = self.server.sadd(self.key, fp)
#added= 0 表示存在
#added!=0 表示不存在,并且已经插入
return added == 0
scrapy_redis和scrapy中request入队的条件
- request对象没见过,新的request
- dont_filter = True 不过滤的情况下会反复抓取
- start_urls 中的url能够被反复抓取
?️
scrapy-redis
存放:过滤完存入请求队列
过滤:set 集合先过滤指纹,指纹就是对每个请求进行转换,判断能否存入 redis 集合,集合会自动去重,能存入,说明没有请求过,就将请求存入到请求队列中。
多个服务器调用同一个 redis 服务器,可以实现分布式爬虫
指纹默认忽略 header,因为 header 里面可能存了 cookie,而 cookie 可能不一样,会导致生成的指纹不一样,所以默认忽略
哈希函数的特性
- 输入域无限,输出域有限
- 相同的输入,必然得到相同的输出(不是随机性)
- 不同的输入,也可能得到相同的输出(哈希碰撞)
- 离散性:对于输出域中的每个结果,在整个输出域是均匀分布的
dict 字典 -> 哈希表
每个字典过来都需要使用哈希表对 key 进行计算
需要阅读的书籍
- 操作系统:精髓与设计原理
- 数据结构
- 算法导论
网易公开课 算法导论 书籍视频
scrapy_redis为什么能够实现去重和请求的持久化以及分布式爬虫
- scrapy_redis把指纹和request对象存储在了redis,下一次程序启动起来之后会从之前的redis中读取数据
- 实现分布式:多个服务器上的爬虫公用一个redis
scray_redis中dmoz给我们展示了一个什么样的爬虫
- 增量式的爬虫:基于request对象的增量
scrapy_redis中如何实现一个增量式的爬虫
- settings中进行配置,指定去重的类,调度器的类,添加上redis_url
scrapy中如何生成的指纹,有什么启发
使用sha1加密请求的url地址,请求的方法和请求体,得到16进制字符串作为指纹
fp = hashlib.sha1()
fp.update(request.url)
fp.update(request.method)
fp.update(request.body or b"")
Redisspider的爬虫和scrapy.spider的区别
- 区别
- redisspider继承的父类是RedisSpider
- redisspider没有start_url,有redis_key
- redis_key表示redis中存放start_url地址的键
- 创建爬虫
- scrapy genspider 爬虫名 允许爬取的范围
- 修改父类
- 添加redis_key
- 启动爬虫
- 让爬虫就绪 scrapy crawl 爬虫
- lpush redis_key url 爬虫会启动
RedisCrawlSpider的爬虫和crwalspdier的区别
- 区别
- RedisCrawlSpider继承的父类是RedisCrawlSpider
- RedisCrawlSpider没有start_url,有redis_key
- redis_key表示redis中存放start_url地址的键
- 创建爬虫
- scrapy genspider -t crwal 爬虫名 允许爬取的范围
- 修改父类
- 添加redis_key
- 启动爬虫
- 让爬虫就绪 scrapy crawl 爬虫
- lpush redis_key url 爬虫会启动