Загрузка файлов Item с ItemLoader в нескольких ответах - PullRequest
0 голосов
/ 09 января 2019

Это дополнительный вопрос к принятому ответу на вопрос Scrapy: заполнить элементы загрузчиками элементов на нескольких страницах . Я хочу использовать ItemLoader для сбора значений из нескольких запросов в один Item. Принятый ответ предполагает, что загруженный Item.load_item() должен быть передан следующему запросу через поле meta в request.

Однако я хотел бы применить output_processors ко всем собранным значениям одного поля при возврате загруженного объекта в конце сканирования.

Вопросы

  1. Каков наилучший способ достичь этого?
  2. Можно ли передать экземпляр ItemLoader через meta следующему request, не загружая его, а затем просто заменить элементы selector или response в ItemLoader при добавлении значений или xpath из следующего ответ

Пример:

def parse(self, response):
    loader = TheLoader(item=TestItems(), response=response)
    loader.add_xpath('title1', '//*[@id="firstHeading"]/text()')
    request = Request(
        "https://en.wikipedia.org/wiki/2016_Rugby_Championship",
        callback=self.parsePage1,
        meta={'loader': loader},
        dont_filter=True
    )
    yield request

def parsePage1(self, response):
    loader = response.meta['loader']
    loader.response = response
    loader.add_xpath('title1', '//*[@id="firstHeading"]/text()')
    return loader.load_item()

Игнорировать контекст реальных сайтов.

1 Ответ

0 голосов
/ 11 января 2019

Да, вы можете просто передать экземпляр ItemLoader.

Если я правильно помню это из чата irc или github давным-давно, могут иметь некоторые потенциальные проблемы с этим, такие как увеличение использования памяти или утечки из обработки ссылок, потому что вы переносите ссылки на объекты Экземпляры ItemLoader (и процессоры?) И, возможно, в течение длительного времени, в зависимости от порядка очередей загрузки, путем привязки этих экземпляров ItemLoader к этим запросам. Так что имейте это в виду и, возможно, остерегайтесь использования этого стиля на больших обходах или сделайте некоторую отладку памяти, чтобы быть уверенным.

Однако в прошлом я сам широко использовал этот метод (и все равно делал бы это при использовании ItemLoaders) и не видел никаких проблем с этим подходом сам.

Вот как я это делаю:

import scrapy
from myproject.loader import ItemLoader

class TheLoader(ItemLoader):
    pass

class SomeSpider(scrapy.Spider):
    [...]

    def parse(self, response):
        loader = TheLoader(item=TestItems(), response=response)
        loader.add_xpath('title1', '//*[@id="firstHeading"]/text()')
        request = Request("https://en.wikipedia.org/wiki/2016_Rugby_Championship",
            callback=self.parsePage1,
            dont_filter=True
        )
        request.meta['loader'] = loader
        yield request

    def parsePage1(self, response):
        loader = response.meta['loader']
        # rebind ItemLoader to new Selector instance
        #loader.reset(selector=response.selector, response=response)
        # skipping the selector will default to response.selector, like ItemLoader
        loader.reset(response=response)
        loader.add_xpath('title1', '//*[@id="firstHeading"]/text()')
        return loader.load_item()

Для этого необходимо использовать настроенный класс ItemLoader, который можно найти в мой помойный скребок , но соответствующая часть класса находится здесь:

from scrapy.loader import ItemLoader as ScrapyItemLoader

class ItemLoader(ScrapyItemLoader):
    """ Extended Loader
        for Selector resetting.
        """

    def reset(self, selector=None, response=None):
        if response is not None:
            if selector is None:
                selector = self.default_selector_class(response)
            self.selector = selector
            self.context.update(selector=selector, response=response)
        elif selector is not None:
            self.selector = selector
            self.context.update(selector=selector)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...