как мне очистить форму веб-сайта, на котором есть кнопка next, а также если он прокручивается?

#python #scrapy

#python #scrapy

Вопрос:

Я пытаюсь очистить все данные с веб-сайта под названием quotestoscrape. Но, когда я пытаюсь запустить свой код, он получает только одну случайную цитату. Он должен принимать по крайней мере все данные только с этой страницы, но он принимает только один. Кроме того, если каким-то образом я получу данные со страницы 1, теперь я хочу получить данные со всех страниц.

  1. Итак, как мне решить эту ошибку (которая должна принимать все данные со страницы1)?
  2. Как мне получить все данные, которые присутствуют на следующих страницах?

items.py файл

     import scrapy
    class QuotetutorialItem(scrapy.Item):

        title = scrapy.Field()
        author = scrapy.Field()
        tag = scrapy.Field()
 

quotes_spider.py файл

 import scrapy
from ..items import QuotetutorialItem

class QuoteScrapy(scrapy.Spider):
    name = 'quotes'
    start_urls = [
        'http://quotes.toscrape.com/'
    ]

    def parse(self, response):

        items = QuotetutorialItem()

        all_div_quotes = response.css('div.quote')

        for quotes in all_div_quotes:
            title = quotes.css('span.text::text').extract()
            author = quotes.css('.author::text').extract()
            tag = quotes.css('.tag::text').extract()

            items['title'] = title
            items['author'] = author
            items['tag'] = tag

        yield items
 

Пожалуйста, скажите мне, какие изменения я могу сделать?

Комментарии:

1. yield я считаю, что должен быть отступ

2. о, это сработало, спасибо. Теперь вы можете взглянуть на мою вторую проблему?

3. вторую страницу можно найти по адресу quotes.toscrape.com/page/2

4. О yield statement почему он не выдает мне ошибку отступа. Почему он возвращает только один элемент?

5. Поскольку там вполне допустимо иметь yield оператор, это просто не означает, что вы хотите, чтобы это означало. Дополнительный отступ помещает его в for цикл. Оставляя его там, где вы показали, он выводит его за пределы for цикла, но все еще внутри parse функции. В этом случае вы получаете только один элемент, потому yield что он достигается только один раз — после завершения цикла.

Ответ №1:

Как сообщалось, в вашем yield отсутствует уровень идентификатора. И чтобы перейти на следующие страницы, просто добавьте проверку для следующей кнопки и отправьте запрос после нее.

 import scrapy


class QuoteScrapy(scrapy.Spider):
    name = 'quotes'
    start_urls = [
        'http://quotes.toscrape.com/'
    ]

    def parse(self, response):

        items = {}

        all_div_quotes = response.css('div.quote')

        for quotes in all_div_quotes:
            title = quotes.css('span.text::text').extract()
            author = quotes.css('.author::text').extract()
            tag = quotes.css('.tag::text').extract()

            items['title'] = title
            items['author'] = author
            items['tag'] = tag

            yield items

        next_page = response.css('li.next a::attr(href)').extract_first()
        if next_page:
            yield response.follow(next_page)
 

Комментарии:

1. Должен ли я перейти на следующую страницу и запустить ее снова, чтобы сохранить данные следующей страницы?

2. Нет. Последние 3 строки извлекут ссылку из кнопки Next и отправят новый запрос на следующую страницу. Этот запрос будет проанализирован тем же методом синтаксического анализа, в результате чего будут получены все элементы, присутствующие на всех страницах. next_page = response.css('li.next a::attr(href)').extract_first() Итак, мы проверяем, есть ли следующая страница с помощью: if next_page Тогда мы выдаем новый запрос со строкой ниже. Обратите внимание на этот ответ. follow — это ярлык для urllib.urljoin(response.url, next_url) , потому что это относительный URL. выдайте ответ. следуйте (next_page)

3. Спасибо, это сработало. Кроме того, я хочу знать, нет ли на нем кнопки «Следующая страница», и вместо этого, если мне придется прокручивать страницы, будет ли это работать так же? или в этом есть другая логика?

4. В случае бесконечной прокрутки лучшим вариантом будет изучить API, который он использует для запроса данных при прокрутке вниз. Вы можете сделать это, открыв консоль разработчика (Ctrl Shift C) в Google Chrome, перейдя на вкладку «Сеть», отфильтруйте по запросам XHR и найдите запрос, который извлекает данные при прокрутке страницы вниз. Как только вы получили запрос API, вы можете использовать его на своем пауке для извлечения данных так же, как страница при прокрутке вниз.

Ответ №2:

Как @LanteDellaRovere правильно определил в комментарии, yield оператор должен выполняться для каждой итерации for цикла — вот почему вы видите только одну (предположительно последнюю) ссылку с каждой страницы.

Что касается чтения продолженных страниц, вы можете извлечь его из <nav> элемента внизу страницы, но структура очень проста — ссылки (когда не указан тег) имеют вид

 http://quotes.toscrape.com/page/N/
 

Вы обнаружите, что для N = 1 вы получаете первую страницу. Поэтому просто доступ к URL-адресам для увеличения значений N до тех пор, пока попытка не увидит возврат 404, должен работать как упрощенное решение.

Не зная много о Scrapy, я не могу дать вам точный код, но примеры на https://docs.scrapy.org/en/latest/intro/tutorial.html#following-links довольно полезны, если вам нужен более сложный и питонический подход.

Комментарии:

1. Привет, предположим, у меня есть 50 страниц, и я должен извлечь их все. Я не думаю, что это будет полезно в этой ситуации. Уверен, что это сработает, потому что у него ограниченные страницы. Есть ли какое-либо решение, которое вы можете подсказать?

2. На вашем месте я бы выбрал ответ от @Marcos — похоже, он основан на глубоких знаниях о том, как использовать Scrapy.