scrapy高階開發(三) 去重策略

2021-09-11 12:51:21 字數 3898 閱讀 5124

# 原始碼位置scrapy.core.engine.executionengine

class executionengine(object):

def schedule(self, request, spider):

self.signals.send_catch_log(signal=signals.request_scheduled,

request=request, spider=spider)

這裡呼叫scheduler的enqueue_request方法做判斷,具體見2

if not self.slot.scheduler.enqueue_request(request):

self.signals.send_catch_log(signal=signals.request_dropped,

request=request, spider=spider)

複製**

# 原始碼位置 scrapy.core.scheduler.scheduler

class scheduler(object):

def __init__(self, dupefilter, jobdir=none, dqclass=none, mqclass=none,

logunser=false, stats=none, pqclass=none):

# dupefilter 為具體過濾器,見3.

self.df = dupefilter

self.dqdir = self._dqdir(jobdir)

self.pqclass = pqclass

self.dqclass = dqclass

self.mqclass = mqclass

self.logunser = logunser

self.stats = stats

......

...def enqueue_request(self, request):

# self.df.request_seen 為過濾器中具體執行過濾的方法邏輯

# 如果request設定了非不過濾(即過濾,雙重否定表肯定)並且該request經過判斷以後的確需要過濾,則列印任職並返回false

if not request.dont_filter and self.df.request_seen(request):

self.df.log(request, self.spider)

return false

if self.stats:

self.stats.inc_value('scheduler/enqueued/redis', spider=self.spider)

self.queue.push(request)

return true

複製**

# 去重啟基類,定義了去重器需要實現的方法

class basedupefilter(object):

@classmethod

def from_settings(cls, settings):

return cls()

def request_seen(self, request):

return false

def open(self): # can return deferred

pass

def close(self, reason): # can return a deferred

pass

def log(self, request, spider): # log that a request has been filtered

pass

# scrapy中預設的去重器

class rfpdupefilter(basedupefilter):

"""request fingerprint duplicates filter"

"" def __init__(self, path=none, debug=false):

self.file = none

# 乙個指紋集合,利用到了set的特性,不重複

self.fingerprints = set()

self.logdupes = true

self.debug = debug

self.logger = logging.getlogger(__name__)

# 這裡會判斷是否設定了jobdir,如果設定了,則會將去重結合寫入到jobdir目錄,具體見《scrapy高階開發(二):暫停與重啟》一文

if path:

self.file = open(os.path.join(path, 'requests.seen'), 'a+')

self.file.seek(0)

self.fingerprints.update(x.rstrip() for x in self.file)

@classmethod

def from_settings(cls, settings):

# settings中將dupefilter_debug設定為true可以開啟過濾debug資訊的列印

debug = settings.getbool('dupefilter_debug')

return cls(job_dir(settings), debug)

def request_seen(self, request):

# 為request生成乙個指紋

fp = self.request_fingerprint(request)

# 判斷當前指紋是否在集合中

if fp in self.fingerprints:

# 如果在返回true代表當前request已經被處理過應該過濾掉

return true

# 否則新增到set中

self.fingerprints.add(fp)

# 如果jobdir檔案存在,則寫入

if self.file:

self.file.write(fp + os.linesep)

# request_fingerprint方法在scrapy.utils.request裡,

# 使用了sha1演算法為每乙個request生成乙個固定長度的hash值

def request_fingerprint(self, request):

return request_fingerprint(request)

# 關閉方法

def close(self, reason):

if self.file:

self.file.close()

# 記錄日誌的方法封裝

def log(self, request, spider):

if self.debug:

msg = "filtered duplicate request: %(request)s"

self.logger.debug(msg, , extra=)

elif self.logdupes:

msg = ("filtered duplicate request: %(request)s"

" - no more duplicates will be shown"

" (see dupefilter_debug to show all duplicates)")

self.logger.debug(msg, , extra=)

self.logdupes = false

spider.crawler.stats.inc_value('dupefilter/filtered', spider=spider)

複製**

request_seen

enqueue_request

python爬蟲去重策略 爬蟲去重策略

1 使用scrapy自帶的set集合去重,當程式結束的時候會被清空,缺點 再次執行會導致資料重複。2 使用mysql做去重,對url位址進行md5,base64加密,加密之後會得到一串字元,判斷字串 是否在mysql表中,如果在表示已經爬取過了,如果不在,表示沒有爬取,執行請求,將加密後的url 3...

python爬蟲去重策略 爬蟲去重策略

下面我會從程式 資料庫等幾個層面詳細敘述一下相應的去重策略。程式層面,像十萬以下url的抓取可以簡單的用set來實現去重。如果是百萬或者千萬量級的話,考慮到效能,我們應該使用基於hash的set實現去重。知道了前面雜湊的知識,你肯定就懂這是為什麼了。雜湊使得我們並不需要對比超長的url以及param...

python爬蟲去重策略 爬蟲的去重策略

1.爬蟲時將爬取過的url存放到資料庫中,利用資料庫進行url的去重 每請求乙個url之前,都現在資料庫中查詢一下。方法最簡單,效率是最低的。2.將已經請求過的url儲存到set中,而set集合是在記憶體中建立的,訪問效率比資料庫的方式要快很多,只需要很簡單的乙個方法,就可以實現url的去重。缺點 ...