增量式爬虫:在上一次的基础上继续爬取,爬过的不再爬取。
分布式爬虫
:多台服务器可以共享两个队列,所以可以并发来爬取数据。
Scrapy-Redis插件:
安装 pip install scrapy-redis
与原来的爬虫相比,只有设置文件中的4行代码有区别:
增量式和分布式爬虫核心代码
REDIS_URL = "redis://127.0.0.1:6379"
#指定了去重的类
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
#制定了调度器的类
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
#调度器的内容是否持久化, 爬虫执行结束后,是否要清空redis中的数据
SCHEDULER_PERSIST = True
Scrapy-Redis中的去重:
# scrapy_redis.dupefilter.RFPDupeFilter
def request_seen(self, request):
# 请求是否见过,True就是见过,False就是没有见过
# 计算当前请求的特征值
fp = self.request_fingerprint(request)
# 跟以前的请求的特征值进行比对,如果比对上,就返回True,否则返回False
# 向Redis数据库中的Set类型(不能重复)的键中插入数据
# 如果能插入,说明这个特征值以前没有出现过,返回1
# 如果插入不了,说明这个特征值以前出现过,返回0
added = self.server.sadd(self.key, fp)
if added == 1:
return False
elif added == 0:
return True
# return added == 0
计算特征值的方法:
# from scrapy.utils.request import request_fingerprint
def request_fingerprint(request, include_headers=None):
# 计算给定请求的特征值
# 如何判定两个请求是同一个
# 请求中都有啥:请求行 请求头 请求体
# 如果请求行、请求头、请求体中的内容都一样,说明是同一个请求
# 请求行中有 请求方式 url路径
# 请求头中有 User-Agent Cookie Referer 有可能不同,默认不对请求头进行计算特征值
# 请求体 请求体必须计算特征值
# url路径中,参数的位置也可能不同,应该把url地址中的参数取出来,按照相同的方式排序后,再计算特征值
# http://www.example.com/query?id=111&cat=222
# http://www.example.com/query?cat=222&id=111
# 判断是否需要计算请求头,默认是不计算的,但是可以指定进行计算
if include_headers:
include_headers = tuple(to_bytes(h.lower())
for h in sorted(include_headers))
cache = _fingerprint_cache.setdefault(request, {})
# 计算请求的其他部分
if include_headers not in cache:
fp = hashlib.sha1()
# 计算请求方式
fp.update(to_bytes(request.method))
# 计算经过特殊处理的url地址
fp.update(to_bytes(canonicalize_url(request.url)))
# 计算请求体
fp.update(request.body or b'')
# 计算请求头,一般不计算
if include_headers:
for hdr in include_headers:
if hdr in request.headers:
fp.update(hdr)
for v in request.headers.getlist(hdr):
fp.update(v)
# 调用方法获得特征值,进行返回
cache[include_headers] = fp.hexdigest()
return cache[include_headers]
特征值hash算法(散列算法,md5、sha1、sha256、sha384)的特点:
1、相同的明文加密后的结果一定相同
2、不同的明文加密后的结果应该不相同
例外:
不同的明文加密后的结果相同。称之为碰撞。
md5,山东大学的女教授,提高了碰撞的概率
原有爬虫,经过添加4行代码,可以将请求队列和去重队列存储到redis中,从而实现增量式爬虫(不爬取老的或已经爬过的url地址,只爬新的)
RedisSpider
为了实现分布式爬虫(多台服务器同时来运行同样的程序,从而提高效率),也需要设置scrapy-redis的4行设置代码。
跟原有爬虫的区别:
1、继承的父类不同RedisSpider
2、没有start_urls而是提供了一个REDIS_KEY
3、启动过程中需要先开启爬虫,再在redis添加一个起始的路径
4、 配置文件的4行代码(文章开头的4行)
增量式爬虫和分布式爬虫的区别:
1、spider 继承的类不同
增量式爬虫继承的类为CrawlSpider
分布式爬虫继承的类为RedisSpider
2、 指定起始爬虫的url方式不同
增量式在spider中指定start_url=“”地址
分布式在spider中设置redis_key=“” 并在redis数据库中lpush redis_key的值
3、 增量式爬虫和分布式爬虫和普通爬虫的启动方式 相同
分布式爬虫启动爬虫后并不会开始爬取,会在读取redis数据库中的redis_key起始地址url,获取到以后才会开始爬取