去重

去重原理:
相当于是写了集合self.vister_urls=set(),把所有的url放进去当执行yield Requets的时候就会执行,进行判断,看是否这个访问的url在这个集合里面,如果在的话,就不添加进去了

from scrapy.utils.request import request_fingerprint##进行加密,url的唯一标识

每一次yield Request的时候,就会执行settings里面的去重
从from_settings开始执行,返回的时候,就执行下面的requets_seen方法

settings:
#执行自定义的去重规则
DUPEFILTER_CLASS='scrapyproject1.dupliter.Self_Dupliter'

spider:

#yield   Request(url=page_url, callback=self.parse,dont_filter=True)##每一次requets的时候,就会执行去重的方法,不准询去重规则,如果要遵循的话,那么应该为false
要遵循去重规则,就要改成dont_filter=False,或者不添加,默认为False

原理分析:

from   scrapy.dupefilter import  BaseDupeFilter
from scrapy.utils.request import request_fingerprint##进行加密,url的唯一标识,会进行加密处理
'''
在scrapy里面有一个唯一标识
http://xxx.com/?k1=v1&k2=v2
http://xxx.com/?k2=v2&k1=v1
如果是md5进行加密的话,这两个url是不一样的,但是这两个url是相同的
但是scrapy里面有一个方法,可以辨别出两个相同的url出来
request_fingerprint(放在里面进行加密,如果是相同的打印出来也是相同的)
'''

##去重

class Self_Dupliter(BaseDupeFilter):
def __init__(self):
self.vister_urls=set()
##设置url元祖


@classmethod
def from_settings(cls, settings):
print('最开始')
return cls()

# def request_seen(self, request):###传入的requets里面有url,可以直接取出来
# print('执行去重规则')
# if request.url in self.vister_urls:
# return True
# self.vister_urls.add(request.url)
# return False

def request_seen(self, request): ###传入的requets里面有url,可以直接取出来
print('执行去重规则')
print(request.url)
fd=request_fingerprint(request)##进行了加密处理,长度一样
if fd in self.vister_urls:##如果访问的url在这里的话,就返回true,不执行
print('存在')
print(request.url)
return True
self.vister_urls.add(fd)


##爬虫开始的时候
def open(self): # can return deferred
print('开始')

##redis,爬虫结束
def close(self, reason): # can return a deferred
print('结束')


##记录日志的时候
def log(self, request, spider): # log that a request has been filtered
print('记录日志')


'''
可以让他每次来不执行init方法
直接是下面的方法,所以init里面定义的set可以一直加值,在进行判断,相当于是一个存放url(不重复)集合

执行顺序:
最开始执行settings(有执行去重类,导入模块的时候)
在执行parse方法,如果settings里面配置了去重的类的话,那么每yield Requets的时候,就会执行这个自定义的去重类:
去重类执行顺序:先执行from_seen,在执行open,在执行request_seen(多次执行,每yield Request一次的话,就执行一次这个方法),最后执行close
'''



连接redis去重处理(放进redis集合里面)

爬虫里面:
from   scrapy.http.request  import  Request
def parse(self, response):
print('执行操作')
# obj=response.xpath('//*[@id="dig_lcpage"]/ul/li/a[re:test(@class,"ct_pagepa")]/@href').extract()
obj=response.xpath('//*[@id="dig_lcpage"]/ul/li/a[re:test(@href,"/all/hot/recent/(d+)")]/@href').extract()
for i in obj:
# print(i)
page='https://dig.chouti.com'+i
yield Request(url=page,callback=self.parse)#dont_filter=True是不执行去重的,当为false是执行去重的

 settings里面

DUPEFILTER_CLASS='scrapy_pro.dupfliter.DupFliter'

去重类里面:
from scrapy.dupefilter import BaseDupeFilter
from scrapy.utils.request import request_fingerprint
import redis
class DupFliter(BaseDupeFilter):
def __init__(self):
self.dupdic=redis.Redis(host='127.0.0.1',port=6379)
# def request_seen(self,request):
# url=request_fingerprint(request)
# if url in self.dupdic:
# return True
# self.dupdic.add(url)
# print('添加成功',request.url)
def request_seen(self,request):
url=request_fingerprint(request)
print('执行去重')
if url==1:
self.dupdic.sadd('scrapy_urls', request.url) ##做判断,看是否是相等的
print('添加成功', request.url)
return False
print('已经存在',request.url)
return True
# 如果是添加成功的haul,那么久返回fasle,不做处理,如果返回true就会执行下一个yield
原文地址:https://www.cnblogs.com/yunxintryyoubest/p/9940215.html