На основании ответа Галласио. Альтернативным вариантом является использование process_request
из 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
в промежуточном программном обеспечении 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
и включите промежуточное ПО Downloader в settings.py
.
Чтобы убедиться в этом, вы можете добавить некоторый проверочный код в process_item
вашего сканера, чтобы убедиться, что не было сделано никаких запросов на сайты, не входящие в сферу действия.