Может ли функция обратного вызова scrapy указывать на ту же функцию, в которой создается запрос - PullRequest
0 голосов
/ 16 февраля 2019

Я использую Scrapy для сканирования сайта.

У меня есть код, подобный следующему:

class mySpider(scrapy.Spider):
    def start_requests(self):
        yield SplashRequest(url=example_url,  
                                callback=self.parse,
                                cookies={'store_language':'en'},
                                endpoint='render.html',
                                args={'wait': 5}, 
                            )  

    def parse(self, response):
        try:
            self.extract_data_from_page(response)

            if (next_link_still_on_page(response):
                next_url = grok_next_url(response)

                yield SplashRequest(url=next_url, 
                                callback=self.parse,
                                cookies={'store_language':'en'},
                                endpoint='render.html',
                                args={'wait': 5}, 
                            )  

        except Exception:
            pass


    def extract_data_from_page(self, response):
        pass


    def next_link_still_on_page(self,response):
        pass


    def grok_next_url(self, response):
        pass

В методе parse() функция обратного вызова: parse() этона что следует возразить (например, логическая ошибка, приводящая к потенциальному переполнению стека?).

1 Ответ

0 голосов
/ 16 февраля 2019

Вы можете использовать тот же обратный вызов.С технической точки зрения это не проблема.Особенно, если данный запрос имеет ту же природу, что и текущий, в идеале он должен повторно использовать ту же логику.

Однако от человека, который должен прочитать источник-код перспектива, лучше иметь отдельные парсеры для разных задач или типов страниц (принцип единой ответственности).


Позвольте мне проиллюстрировать это на примере.Допустим, у вас есть веб-сайт со списком (вакансии, продукты и т. Д.), И у вас есть два основных класса URL:

  • Страницы результатов поиска: .../search?q=something&page=2
  • Страницы товара: .../item/abc

Страница результатов поиска содержит нумерацию страниц и элементы .Такая страница будет вызывать два вида запросов:

  1. Анализ следующей страницы
  2. Анализ элемента

Страница элемента не будет вызывать другой запрос.

Так что теперь вы можете вставить все это в один и тот же парсер и использовать его для каждого запроса:

def parse(self, response):
    if 'search' in response.url:
        for item in response.css('.item'):
            # ...
            yield Request(item_url, callback=self.parse)

        # ...
        yield Request(next_url, callback=self.parse)

    if 'item' in response.url:
        yield {
            'title': response.css('...'),
            # ...
        }

Это, очевидно, очень сжатый пример, нопо мере роста становится все труднее следовать.

Вместо этого разбивайте различные парсеры страниц:

def parse_search(self, response):
    for item in response.css('.items'):
        yield Request(item_url, callback=self.parse_item)

    next_url = response.css('...').get()
    yield Request(next_url, callback=self.parse_search)


def parse_item(self, response):
    yield {
        'title': response.css('...'),
        # ...
    }

Так что, в принципе, если это вопрос "другого такого же родастраница ", то это нормально использовать один и тот же обратный вызов для повторного использования той же логики.Если следующий запрос требует другого вида синтаксического анализа, лучше создайте отдельный анализатор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...