#python #web-scraping #scrapy
#python #веб-очистка #scrapy
Вопрос:
У меня возникла проблема с обходом следующей кнопки, я попробовал базовую, но после проверки html-кода она использует javascript, я пробовал разные правила, но ничего не работает вот ссылка на веб-сайт.
https://www2.hm.com/en_us/sale/shopbyproductladies/view-all.html
Название следующей кнопки — «Загрузить больше продуктов»
вот мой рабочий код
def parse(self, response):
for product_item in response.css('li.product-item'):
url = "https://www2.hm.com/" product_item.css('a::attr(href)').extract_first()
yield scrapy.Request(url=url, callback=self.parse_subpage)
def parse_subpage(self, response):
item = {
'title': response.xpath("normalize-space(.//h1[contains(@class, 'primary') and contains(@class, 'product-item-headline')]/text())").extract_first(),
'sale-price': response.xpath("normalize-space(.//span[@class='price-value']/text())").extract_first(),
'regular-price': response.xpath('//script[contains(text(), "whitePrice")]/text()').re_first("'whitePrice's?:s?'([^'] )'"),
'photo-url': response.css('div.product-detail-main-image-container img::attr(src)').extract_first(),
'description': response.css('p.pdp-description-text::text').extract_first()
}
yield item
Комментарии:
1. Scrapy не запускает JavaScript — возможно, вам придется использовать Selenium для управления веб-браузером, который будет загружать страницу и JavaScript. Или используйте DevTools в Chrome / Firefox, чтобы увидеть, какой URL используется при нажатии кнопки. И затем вы можете загрузить с этого URL. В основном он будет отправлять данные в формате JSON, поэтому получить данные будет намного проще. JSON можно легко преобразовать в словарь Python
2. Эта кнопка использует URL www2.hm.com/en_us/sale/women/view-all/_jcr_content/main /…
3. @furas как перейти на следующую страницу во время очистки?
4. вы не переходите на следующую страницу — вы создаете
Reqest()
с URL, который использует button. И Scrapy будет считывать данные JSON, как это делает button. Вы могли бы даже использовать этот URL для чтения первой страницы — в URL есть параметрoffset
, который, вероятно, может читать разные страницы.5. Попробуйте это
https://www2.hm.com/en_us/sale/shopbyproductladies/view-all.html?sort=stockamp;image-size=smallamp;image=stillLifeamp;offset=0amp;page-size=3002
, чтобы получить их все так, как вы уже пробовали. Основным ключом здесь является эта часть,page-size=
которая увеличивается36
каждый раз, когда вы нажимаете на эту кнопку, пока она не будет3002
.
Ответ №1:
Как уже указывалось в комментариях, нет необходимости включать JavaScript вообще. Если вы посетите страницу и откроете инструменты разработчика вашего браузера, вы увидите, что выполняются запросы XHR, подобные этому:
https://www2.hm.com/en_us/sale/women/view-all/_jcr_content/main/productlisting_b48c.display.json?sort=stockamp;image-size=smallamp;image=stillLifeamp;offset=36amp;page-size=36
Эти запросы возвращают данные JSON, которые затем отображаются на странице с использованием JavaScript. Итак, вы можете просто очистить данные из этих URL-адресов, используя что-то вроде json.dumps(response.text)
. Управляйте продуктами, возвращаемыми с помощью offset
и page-size
параметров. Я предполагаю, что вы закончили, когда получили пустой JSON. Или вы можете установить offset=0
и page-size=9999
для получения данных за один раз ( 9999
это просто произвольное число, которого достаточно в данном конкретном случае).
Комментарии:
1. Привет @tomas спасибо, что ответили мне, интересно, могу ли я динамически изменять размер страницы на основе заданного html. я получу это через response.css, возможно ли это? Я пробую код, но ничего не происходит
2. @ChristianRead Вам вообще не нужно возиться с HTML, насколько я могу судить, вся информация находится в формате JSON, возвращаемом вызовом API. Ответ JSON также содержит поле,
total
которое вы можете использовать для определения момента остановки (например,(offset 1) * page-size <= 3002
где3002
значениеtotal
возвращаемого в данный момент поля.3. Извините и спасибо, что помогли мне @Tomas, но моя проблема в том, что размер страницы постоянно меняется, поэтому, например, 3002 можно изменить на 3004, поэтому мне интересно, могу ли я сделать 3002 динамическим. Общее количество страниц отображается в html, поэтому я думаю, что могу его использовать.
4. Ну, чем просто разбивать страницы на страницы, как вы обычно делаете, т. Е. вызываете API с
offset
увеличением и фиксированнымpage-size
значением, например, 100. Каждый ответ содержитtotal
поле, чтобы вы могли проверить, находитесь ли вы в конце. Кроме того, он возвращаетitemsShown
счетчик, который также можно использовать для этого. Есть несколько способов.