Обратный звонок для перенаправленных запросов Scrapy

Я пытаюсь скрести, используя скребковые рамки. Некоторые запросы перенаправляются, но функция обратного вызова, установленная в start_requests, не вызывается для этих перенаправленных URL-запросов, но отлично работает для не перенаправленных.

У меня есть следующий код в функции start_requests:

for user in users:
    yield scrapy.Request(url=userBaseUrl+str(user['userId']),cookies=cookies,headers=headers,dont_filter=True,callback=self.parse_p)

Но этот self.parse_p вызывается только для не-302 запросов.

2 ответа

Решение

Я думаю, вы получите обратный вызов для последней страницы (после перенаправления). Перенаправления позаботились RedirectMiddleware, Вы можете отключить его, и тогда вам придется делать все перенаправления вручную. Если вы хотите выборочно отключить перенаправления для нескольких типов запросов, вы можете сделать это следующим образом:

request =  scrapy.Request(url, meta={'dont_redirect': True} callback=self.manual_handle_of_redirects)

Я не уверен, что промежуточные запросы / ответы очень интересны. Это тоже что RedirectMiddleware считает. В результате он выполняет перенаправление автоматически и сохраняет промежуточные URL-адреса (единственная интересная вещь) в:

response.request.meta.get('redirect_urls')

У вас есть несколько вариантов!

Пример паука:

import scrapy

class DimSpider(scrapy.Spider):
    name = "dim"

    start_urls = (
        'http://example.com/',
    )

    def parse(self, response):
        yield scrapy.Request(url="http://example.com/redirect302.php", dont_filter=True, callback=self.parse_p)

    def parse_p(self, response):
       print response.request.meta.get('redirect_urls')
       print "done!"

Пример вывода...

DEBUG: Crawled (200) <GET http://www.example.com/> (referer: None)
DEBUG: Redirecting (302) to <GET http://myredirect.com> from <GET http://example.com/redirect302.php>
DEBUG: Crawled (200) <GET http://myredirect.com/> (referer: http://example.com/redirect302.com/)
['http://example.com/redirect302.php']
done!

Если вы действительно хотите очистить 302 страницы, вы должны явно разрешить это. Например, здесь я разрешаю 302 и установить dont_redirect в True:

handle_httpstatus_list = [302]
def parse(self, response):
    r = scrapy.Request(url="http://example.com/redirect302.php", dont_filter=True, callback=self.parse_p)
    r.meta['dont_redirect'] = True
    yield r

Конечный результат:

DEBUG: Crawled (200) <GET http://www.example.com/> (referer: None)
DEBUG: Crawled (302) <GET http://example.com/redirect302.com/> (referer: http://www.example.com/)
None
done!

Этот паук должен вручную следовать 302 URL:

import scrapy

class DimSpider(scrapy.Spider):
    name = "dim"

    handle_httpstatus_list = [302]

    def start_requests(self):
        yield scrapy.Request("http://page_with_or_without_redirect.html",
                             callback=self.parse200_or_302, meta={'dont_redirect':True})

    def parse200_or_302(self, response):
        print "I'm on: %s with status %d" % (response.url, response.status)
        if 'location' in response.headers:
            print "redirecting"
            return [scrapy.Request(response.headers['Location'],
                                  callback=self.parse200_or_302, meta={'dont_redirect':True})]

Быть осторожен. Не пропустите настройку handle_httpstatus_list = [302] в противном случае вы получите "код состояния HTTP не обрабатывается или не допускается".

По умолчанию scrapy не следует 302 перенаправлениям.

В вашем пауке вы можете использовать атрибут custom_settings:

custom_settings Словарь настроек, которые будут переопределены в конфигурации всего проекта при запуске этого паука. Он должен быть определен как атрибут класса, так как настройки обновляются до создания экземпляра.

Задайте количество перенаправлений, на которые может быть перенаправлен URL-запрос, следующим образом:

class MySpider(scrapy.Spider):
  name = "myspider"
  allowed_domains = ["example.com"]
  start_urls = [ "http://www.example.com" ]

  custom_settings = { 'REDIRECT_MAX_TIMES': 333 }

  def start_requests(self):
      # Your code here

Я установил 333 в качестве примера ограничения.

Надеюсь, это поможет.

Другие вопросы по тегам