Scrapy, ожидание перед конвейером

#python #html #scrapy

#python #HTML #scrapy

Вопрос:

(Я новичок в scrapy).

Контекст

Предположим, есть сайт https://example.com , и я хочу его очистить.

Он структурирован следующим образом:

 <body>
<ul>
    <li>
        title_foo
        <a href="https://example.com/title_foo">a desription</a>
    </li>
    <li>
        title_bar
        <a href="https://example.com/title_bar">an another desription</a>
    </li>
</ul>
</body>
  

перейдя по <a> ссылке, я могу получить описание, которое мне нужно перед созданием моих элементов, и отправить их в мой конвейер, который сохранит их в моей БД.

Например, допустим, что когда я следую https://example.com/title_foo , я возвращаю это описание в

 <div class="a-descrption">
    a description
</div>
  

В items.py , я:

 class MyItem(scrapy.Item):
    title = scrapy.Field()
    description = scrapy.Field()
  

И мой паук должен выглядеть так:

 import scrapy
from scrapy_project.items import MyItem

class MySpider(scrapy.Spider):
    name = "my_spider"

    def start_requests(self):
        urls = [
            'https://example.com',
        ]
        for url in urls:
            yield scrapy.Request(url=url, callback=self.parse)

    def parse(self, response):
        for li in response.xpath('//li/text()').getall()
            yield {"title": li }
  

По крайней мере, я надеюсь, что я не тестировал это, поправьте меня, если что-то не так.

Вопрос

Здесь есть своего рода механизм «ожидания». Я имею в виду, мне нужно сказать scrapy, чтобы он подождал, пока эта ссылка будет посещена, прежде чем выдавать мой элемент. Кажется, это распространенная проблема, и я уверен, что для решения этой проблемы существуют некоторые методы, но я не смог найти, как это сделать.

Как вы это делаете?

Ответ №1:

В вашем примере единственное очищенное поле title , так что я не совсем уверен, но похоже, что вы хотите очистить title at https://example.com , сделайте запрос на страницу сведений (например https://example.com/title_foo ) очистите описание там, а ЗАТЕМ yield элемент как с помощью, так description и title с помощью .

Если это так, общим решением для проблем такого типа является использование cb_kwargs или meta . (cb_kwargs — рекомендуемое решение, если вы используете Scrapy версии v1.7 )

cb_kwargs позволяет передавать произвольные данные в функцию обратного вызова запроса. Важно отметить, что данные передаются как аргумент ключевого слова. Так, например:

 class MySpider(scrapy.Spider):
    name = "my_spider"

    start_urls = ['https://example.com',]

    def parse(self, response):
        for li in response.xpath('//li'):
            title = li.xpath('text()').get()
            url_to_detail_page = li.xpath('a/@href').get()
            yield scrapy.Request(
                url=url_to_detail_page,
                callback=self.parse_detail_page,
                cb_kwargs={
                    'title': title
                })

    def parse_detail_page(self, response, title):  # Notice title as a keyword arg
        description = response.xpath('//div[@class="a-descrption"]//text()').getall()
        yield {
            'title': title,
            'description': description,
        }
  

Здесь данные, полученные на первой странице, сохраненные в title , «сопровождают» запрос на страницу сведений и при вызове функции обратного вызова title принимаются в качестве аргумента, поэтому вы можете получить к ним доступ из функции.