Подтвердить что ты не робот

Как фильтровать повторяющиеся запросы на основе url в scrapy

Я пишу сканер для веб-сайта, используя scrapy с CrawlSpider.

Scrapy предоставляет встроенный фильтр дубликатов запросов, который фильтрует повторяющиеся запросы на основе URL-адресов. Кроме того, я могу отфильтровать запросы, используя член правил CrawlSpider.

Что я хочу сделать, это отфильтровать запросы, например:

http:://www.abc.com/p/xyz.html?id=1234&refer=5678

Если я уже посетил

http:://www.abc.com/p/xyz.html?id=1234&refer=4567

ПРИМЕЧАНИЕ: ссылка - это параметр, который не влияет на полученный ответ, поэтому мне все равно, изменяется ли значение этого параметра.

Теперь, если у меня есть набор, который накапливает все идентификаторы, я мог бы игнорировать его в моей функции callback parse_item (что моя функция обратного вызова) для достижения этой функциональности.

Но это означало бы, что я по крайней мере получаю эту страницу, когда мне это не нужно.

Итак, каков способ, которым я могу рассказать, что он не должен отправлять конкретный запрос на основе URL?

4b9b3361

Ответ 1

Вы можете написать собственное промежуточное программное обеспечение для удаления дубликатов и добавить его в настройки

import os

from scrapy.dupefilter import RFPDupeFilter
from scrapy.utils.request import request_fingerprint

class CustomFilter(RFPDupeFilter):
"""A dupe filter that considers specific ids in the url"""

    def __getid(self, url):
        mm = url.split("&refer")[0] #or something like that
        return mm

    def request_seen(self, request):
        fp = self.__getid(request.url)
        if fp in self.fingerprints:
            return True
        self.fingerprints.add(fp)
        if self.file:
            self.file.write(fp + os.linesep)

Затем вам нужно установить правильный DUPFILTER_CLASS в settings.py

DUPEFILTER_CLASS = 'scraper.duplicate_filter.CustomFilter'

После этого он должен работать

Ответ 2

Следуя примеру ytomar, я написал этот фильтр, который фильтруется только по URL-адресам, которые уже были просмотрены путем проверки набора в памяти. Я Python noob, поэтому дайте мне знать, если я что-то прикрутил, но, похоже, все в порядке:

from scrapy.dupefilter import RFPDupeFilter

class SeenURLFilter(RFPDupeFilter):
    """A dupe filter that considers the URL"""

    def __init__(self, path=None):
        self.urls_seen = set()
        RFPDupeFilter.__init__(self, path)

    def request_seen(self, request):
        if request.url in self.urls_seen:
            return True
        else:
            self.urls_seen.add(request.url)

Как упоминалось выше, не забудьте добавить константу DUPEFILTER_CLASS в settings.py:

DUPEFILTER_CLASS = 'scraper.custom_filters.SeenURLFilter'

Ответ 3

https://github.com/scrapinghub/scrapylib/blob/master/scrapylib/deltafetch.py

Этот файл может вам помочь. Этот файл создает базу данных уникального ключа delta fetch из url, пользовательский проход в scrapy.Reqeust(meta = {'deltafetch_key': uniqe_url_key}). Это позволит вам избежать повторных запросов, которые вы уже посещали в прошлом.

Пример реализации mongodb с использованием deltafetch.py ​​

        if isinstance(r, Request):
            key = self._get_key(r)
            key = key+spider.name

            if self.db['your_collection_to_store_deltafetch_key'].find_one({"_id":key}):
                spider.log("Ignoring already visited: %s" % r, level=log.INFO)
                continue
        elif isinstance(r, BaseItem):

            key = self._get_key(response.request)
            key = key+spider.name
            try:
                self.db['your_collection_to_store_deltafetch_key'].insert({"_id":key,"time":datetime.now()})
            except:
                spider.log("Ignoring already visited: %s" % key, level=log.ERROR)
        yield r

например. id = 345 scrapy.Request(URL, мета = {deltafetch_key: 345}, обратный вызов = синтаксический анализ)

Ответ 4

Вот моя собственная база фильтров на scrapy 0.24.6.

В этом фильтре он только заботится об идентификаторе в URL-адресе. например

http://www.example.com/products/cat1/1000.html?p=1 http://www.example.com/products/cat2/1000.html?p=2

рассматриваются как один и тот же URL. Но

http://www.example.com/products/cat2/all.html

не будет.

import re
import os
from scrapy.dupefilter import RFPDupeFilter


class MyCustomURLFilter(RFPDupeFilter):

    def _get_id(self, url):
        m = re.search(r'(\d+)\.html', url)
        return None if m is None else m.group(1)

    def request_fingerprint(self, request):
        style_id = self._get_id(request.url)
        return style_id