增量式爬虫和去重

  • Post author:
  • Post category:其他




增量式爬虫:在上一次的基础上继续爬取,爬过的不再爬取。



分布式爬虫

:多台服务器可以共享两个队列,所以可以并发来爬取数据。

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,获取到以后才会开始爬取



版权声明:本文为weixin_44321182原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。