#python #scrapy
#python #scrapy
Вопрос:
Я пытаюсь очистить все данные с веб-сайта под названием quotestoscrape. Но, когда я пытаюсь запустить свой код, он получает только одну случайную цитату. Он должен принимать по крайней мере все данные только с этой страницы, но он принимает только один. Кроме того, если каким-то образом я получу данные со страницы 1, теперь я хочу получить данные со всех страниц.
- Итак, как мне решить эту ошибку (которая должна принимать все данные со страницы1)?
- Как мне получить все данные, которые присутствуют на следующих страницах?
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.