#python #scrapy
#python #scrapy
Вопрос:
В Scrapy как я могу использовать разные функции обратного вызова для разрешенных доменов и запрещенных доменов.
Я использую следующие правила:
rules = [Rule(LinkExtractor(allow=(), deny_domains = allowed_domains), callback='parse_denied_item', follow=True),
Rule(LinkExtractor(allow_domains = allowed_domains), callback='parse_item', follow=True)]
В принципе, я хочу, parse_item
чтобы меня вызывали всякий раз, когда есть запрос от allowed_domain
(или поддомена одного из этих доменов). Затем я хочу, parse_denied_item
чтобы меня вызывали для всех запросов, которые не занесены в белый список allowed_domains
.
Как я могу это сделать?
Ответ №1:
Я считаю, что лучший подход — не использовать allowed_domains
on LinkExtractor
, а вместо этого разбирать домен из response.url
в вашем parse_*
методе и выполнять другую логику в зависимости от домена.
Вы можете сохранить отдельные parse_*
методы и метод сортировки, который в зависимости от доменов вызывает yield from self.parse_*(response)
(Python 3) соответствующий parse_*
метод:
rules = [Rule(LinkExtractor(), callback='parse_all', follow=True)]
def parse_all(self, response):
# [Get domain out of response.url]
if domain in allowed_domains:
yield from self.parse_item(response)
else:
yield from self.parse_denied_item(response)
Комментарии:
1. Можно ли использовать
process_request
атрибут aRule
для захвата запроса до его выполнения? Затем фильтровать с этой точки? docs.scrapy.org/en/latest/topics /…2. Действительно, я об этом не подумал. Пожалуйста, добавьте это как ответ на ваш собственный вопрос, я, например, проголосую за это.
Ответ №2:
Основано на ответе Gallaecio. Альтернативным вариантом является использование process_request
of Rule
. process_request
перехватит запрос до его отправки.
Насколько я понимаю (что может быть неверно) Scrapy будет сканировать только домены, перечисленные в self.allowed_domains
(при условии, что он используется). Однако, если на очищенной странице встречается удаленная ссылка, Scrapy в некоторых случаях отправит один запрос на эту удаленную ссылку [1]. Я не уверен, почему это происходит. Я думаю, это, возможно, происходит потому, что целевой сайт выполняет перенаправление 301 или 302, и поисковый робот автоматически следует по этому URL. В противном случае, это, вероятно, ошибка.
process_request
может использоваться для выполнения обработки запроса перед его выполнением. В моем случае я хотел регистрировать все ссылки, которые не просматриваются. Итак, я проверяю, включен ли разрешенный домен request.url
, прежде чем продолжить, и регистрирую любой из тех, которые не включены.
Вот пример:
rules = [Rule(LinkExtractor(), callback='parse_item', process_request='process_item', follow=True)]
def process_item(self, request):
found = False
for url in self.allowed_domains:
if url in request.url:
#an allowed domain is in the request.url, proceed
found = True
if found == False: #otherwise log it
self.logDeniedDomain(urlparse(request.url).netloc)
# according to: https://docs.scrapy.org/en/latest/topics/spiders.html#scrapy.spiders.Rule
# setting request to None should prevent this call from being executed (which is not the case for all)
# middleware is used to catch these few requests
request = None
return request
[1]: Если вы столкнулись с этой проблемой, использование process_request
промежуточного программного обеспечения in Downloader, по-видимому, решает ее.
Мое Downloader
промежуточное программное обеспечение:
def process_request(self, request, spider):
#catch any requests that should be filtered, and ignore them
found = False
for url in spider.allowed_domains:
if url in request.url:
#an allowed domain is in the request.url, proceed
found = True
if found == False:
print("[ignored] " request.url)
raise IgnoreRequest('Offsite link, ignore')
return None
Убедитесь, что вы также импортируете IgnoreRequest
:
from scrapy.exceptions import IgnoreRequest
и включите промежуточное программное обеспечение загрузчика в settings.py
.
Чтобы убедиться в этом, вы можете добавить некоторый проверочный код в process_item
вашего сканера, чтобы убедиться, что не было сделано запросов к сайтам вне области видимости.