2016-02-11 3 views
3

Я использую простую реализацию CrawlSpider для обхода веб-сайтов. По умолчанию Scrapy следует за 302 перенаправлением в целевые местоположения и видом игнорирует первоначально запрошенную ссылку. На конкретном сайте я столкнулся с страницей, переадресованной на другую страницу. То, что я намереваюсь сделать, это зарегистрировать как исходную ссылку (которая отвечает 302), так и целевое местоположение (указанное в заголовке ответа HTTP) и обработать их в parse_item методе CrawlSpider. Пожалуйста, помогите мне, как я могу это достичь?Scrap handle 302 код ответа

Я столкнулся с решениями, использующими dont_redirect=True или REDIRECT_ENABLE=False, но на самом деле я не хочу игнорировать перенаправления, на самом деле я хочу рассмотреть (например, не игнорировать) страницу перенаправления.

например: я нахожу http://www.example.com/page1, который отправляет 302 ответ HTTP-перенаправления и перенаправляет на http://www.example.com/page2. По умолчанию scrapy игнорирует page1, следует за page2 и обрабатывает его. Я хочу обрабатывать как page1, так и page2 в parse_item.

EDIT Я уже использую handle_httpstatus_list = [500, 404] в классе определения паука обрабатывать 500 и 404 кодов ответа в parse_item, но то же не работает 302 если указать его в handle_httpstatus_list.

+0

Можете ли вы предоставить URL-адрес, который дает вам статус HTTP 302? – Rahul

ответ

6

Scrapy 1.0.5 (последний официальный, как я пишу эти строки) не использует handle_httpstatus_list во встроенной утилите RedirectMiddleware - см. this issue. От Scrapy 1.1.0 (1.1.0rc1 is available), the issue is fixed.

Даже если отключить переадресацию, вы можете имитировать его поведение в вашей функции обратного вызова, проверяя заголовок Location и возвращает Request к перенаправлению

Пример паук:

$ cat redirecttest.py 
import scrapy 


class RedirectTest(scrapy.Spider): 

    name = "redirecttest" 
    start_urls = [ 
     'http://httpbin.org/get', 
     'https://httpbin.org/redirect-to?url=http%3A%2F%2Fhttpbin.org%2Fip' 
    ] 
    handle_httpstatus_list = [302] 

    def start_requests(self): 
     for url in self.start_urls: 
      yield scrapy.Request(url, dont_filter=True, callback=self.parse_page) 

    def parse_page(self, response): 
     self.logger.debug("(parse_page) response: status=%d, URL=%s" % (response.status, response.url)) 
     if response.status in (302,) and 'Location' in response.headers: 
      self.logger.debug("(parse_page) Location header: %r" % response.headers['Location']) 
      yield scrapy.Request(
       response.urljoin(response.headers['Location']), 
       callback=self.parse_page) 

консоли журнала:

$ scrapy runspider redirecttest.py -s REDIRECT_ENABLED=0 
[scrapy] INFO: Scrapy 1.0.5 started (bot: scrapybot) 
[scrapy] INFO: Optional features available: ssl, http11 
[scrapy] INFO: Overridden settings: {'REDIRECT_ENABLED': '0'} 
[scrapy] INFO: Enabled extensions: CloseSpider, TelnetConsole, LogStats, CoreStats, SpiderState 
[scrapy] INFO: Enabled downloader middlewares: HttpAuthMiddleware, DownloadTimeoutMiddleware, UserAgentMiddleware, RetryMiddleware, DefaultHeadersMiddleware, MetaRefreshMiddleware, HttpCompressionMiddleware, CookiesMiddleware, ChunkedTransferMiddleware, DownloaderStats 
[scrapy] INFO: Enabled spider middlewares: HttpErrorMiddleware, OffsiteMiddleware, RefererMiddleware, UrlLengthMiddleware, DepthMiddleware 
[scrapy] INFO: Enabled item pipelines: 
[scrapy] INFO: Spider opened 
[scrapy] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min) 
[scrapy] DEBUG: Telnet console listening on 127.0.0.1:6023 
[scrapy] DEBUG: Crawled (200) <GET http://httpbin.org/get> (referer: None) 
[redirecttest] DEBUG: (parse_page) response: status=200, URL=http://httpbin.org/get 
[scrapy] DEBUG: Crawled (302) <GET https://httpbin.org/redirect-to?url=http%3A%2F%2Fhttpbin.org%2Fip> (referer: None) 
[redirecttest] DEBUG: (parse_page) response: status=302, URL=https://httpbin.org/redirect-to?url=http%3A%2F%2Fhttpbin.org%2Fip 
[redirecttest] DEBUG: (parse_page) Location header: 'http://httpbin.org/ip' 
[scrapy] DEBUG: Crawled (200) <GET http://httpbin.org/ip> (referer: https://httpbin.org/redirect-to?url=http%3A%2F%2Fhttpbin.org%2Fip) 
[redirecttest] DEBUG: (parse_page) response: status=200, URL=http://httpbin.org/ip 
[scrapy] INFO: Closing spider (finished) 

Обратите внимание, что вам понадобится http_handlestatus_list с 302 в нем, в противном случае вы увидите этот род d от log (от HttpErrorMiddleware):

[scrapy] DEBUG: Crawled (302) <GET https://httpbin.org/redirect-to?url=http%3A%2F%2Fhttpbin.org%2Fip> (referer: None) 
[scrapy] DEBUG: Ignoring response <302 https://httpbin.org/redirect-to?url=http%3A%2F%2Fhttpbin.org%2Fip>: HTTP status code is not handled or not allowed 
+0

Да, именно так я это сделал сейчас :) – bawejakunal

1

Средство перенаправления переназначения «поймает» ответ до того, как оно достигнет вашего промежуточного ПО httperror и запустит новый запрос с URL-адресом перенаправления. В то же время исходный ответ не возвращается, т. Е. Вы даже не видите «302-коды», так как они не достигают httperror. Таким образом, наличие 302 в handle_httpstatus_list не влияет.

Посмотрите на его источник в scrapy.downloadermiddlewares.redirect.RedirectMiddleware: В process_response() вы видите, что происходит. Он запускает новый запрос и заменяет исходный URL на redirected_url. Нет ответа «возврат» -> исходный ответ просто отбрасывается.

В основном вам просто нужно перезаписать функцию process_response(), добавив строку с «возвратным ответом», в дополнение к отправке другого запроса с помощью redirected_url.

В parse_item вы, вероятно, хотите установить некоторые условные операторы, в зависимости от того, является ли это перенаправлением или нет? Я полагаю, что это будет не совсем одинаково, так что, возможно, ваш товар тоже будет выглядеть совсем по-другому. Другим вариантом может быть также использование другого синтаксического анализа для любого ответа (в зависимости от того, является ли исходный или перенаправленный URL «специальными страницами»), все, что вам нужно, это иметь разную функцию синтаксического анализа, например parse_redirected_urls(), в вашем паук и вызовите эту функцию разбора через обратный вызов в запросе на перенаправление