Как добавление аргумента dont_filter = True в scrapy.Request заставляет мой метод синтаксического анализа работать?

Вот простой скрап-паук

import scrapy

class ExampleSpider(scrapy.Spider):
    name = "dmoz"
    allowed_domains = ["https://www.dmoz.org"]
    start_urls = ('https://www.dmoz.org/')

    def parse(self,response):
        yield scrapy.Request(self.start_urls[0],callback=self.parse2)

    def parse2(self, response):
        print(response.url)

Когда вы запускаете программу, метод parse2 не работает и не выводит response.url. Затем я нашел решение этой проблемы в ветке ниже.

Почему мой второй запрос не вызывается в методе синтаксического анализа моего scrapy spider

Просто мне нужно было добавить dont_filter = True в качестве аргумента в методе запроса, чтобы функция parse2 работала.

yield scrapy.Request(self.start_urls[0],callback=self.parse2,dont_filter=True)

Но в примерах, приведенных в документации по scrapy и во многих учебных пособиях по YouTube, они никогда не использовали аргумент dont_filter = True в методе scrapy.Request, и все же их вторая функция синтаксического анализа работает.

Взгляните на это

def parse_page1(self, response):
    return scrapy.Request("http://www.example.com/some_page.html",
                      callback=self.parse_page2)

def parse_page2(self, response):
    # this would log http://www.example.com/some_page.html
    self.logger.info("Visited %s", response.url)

Почему мой паук не может работать, если не добавлен dont_filter = True? Что я делаю неправильно ? Какие повторяющиеся ссылки мой паук отфильтровал в моем первом примере?

P.S. Я мог бы решить эту проблему в ветке QA, которую я опубликовал выше, но мне не разрешено комментировать, если у меня нет 50 репутации (бедный я !!)


person Uchiha Madara    schedule 15.08.2016    source источник
comment
Есть ли причина, по которой вы загружаете одну и ту же страницу дважды? Scrapy фильтрует ваши запросы, чтобы вы не сканировали одни и те же страницы, dont_filter буквально означает игнорировать этот фильтр для этого единственного запроса.   -  person Granitosaurus    schedule 15.08.2016
comment
Не имеет отношения к вашему вопросу, но скоро может вас укусить: allowed_domains должен указывать домены, а не URL-адреса, поэтому это должно быть allowed_domains = ["dmoz.org"]   -  person paul trmbrth    schedule 16.08.2016


Ответы (1)


arrow_upward
11
arrow_downward

Краткий ответ: вы делаете повторяющиеся запросы. Scrapy имеет встроенную фильтрацию дубликатов, которая включена по умолчанию. Вот почему parse2 не вызывается. Когда вы добавляете этот dont_filter=True, scrapy не отфильтровывает повторяющиеся запросы. Итак, на этот раз запрос обрабатывается.

Более длинная версия:

В Scrapy, если вы установили start_urls или определили метод start_requests(), паук автоматически запрашивает эти URL-адреса и передает ответ методу parse, который является методом по умолчанию, используемым для синтаксического анализа запросов. Теперь вы можете создавать новые запросы отсюда, которые снова будут анализироваться Scrapy. Если вы не установите обратный вызов, снова будет использован метод parse. Если вы установите обратный вызов, этот обратный вызов будет использован.

Scrapy также имеет встроенный фильтр, который предотвращает дублирование запросов. То есть, если Scrapy уже просканировал сайт и проанализировал ответ, даже если вы передадите другой запрос с этим URL-адресом, scrapy не обработает его.

В вашем случае у вас есть URL-адрес в start_urls. Scrapy начинается с этого URL. Он сканирует сайт и передает ответ parse. Внутри этого метода parse вы снова отправляете запрос на тот же URL (который только что обработал scrapy), но на этот раз с parse2 в качестве обратного вызова. Когда этот запрос выполнен, scrapy видит в нем дубликат. Таким образом, он игнорирует запрос и никогда его не обрабатывает. Таким образом, никаких звонков на parse2 не производится.

Если вы хотите контролировать, какие URL-адреса следует обрабатывать и какой обратный вызов использовать, я рекомендую вам переопределить start_requests() и вернуть список scrapy.Request вместо использования одного атрибута start_urls.

person masnun    schedule 15.08.2016
comment
Я думаю, вы имеете в виду переопределение start_requests, поскольку get_start_urls не фигурирует в вашем последнем абзаце. - person Granitosaurus; 15.08.2016
comment
Мое плохое, да, обновляю ответ. Я писал по памяти и забыл имя. - person masnun; 15.08.2016
comment
Я никогда не думал, что URL-адреса в start_urls анализируются автоматически. Большое спасибо за вашу помощь и время - person Uchiha Madara; 15.08.2016
comment
Разве фильтрация не распространяется и на scrapy.FormRequest? - person user1941390; 07.09.2017