Как сделать следующую страницу, если она использует Javascript в Scrapy

#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 счетчик, который также можно использовать для этого. Есть несколько способов.