Вот простой скрап-паук
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 репутации (бедный я !!)
Ответ 1 · рейтинг 11 · masnun
Краткий ответ: вы делаете повторяющиеся запросы. 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.