Как добавить ожидание при загрузке текста в веб-скрапинге? Почему?

Вопрос или проблема

https://adrianahoyos.com/our-products/living-room/sofa-loveseats/caramelo-tufted-sofa-140/
Сайт загружается через 5 секунд, показывая текст, но мне нужно получить текст из [“Загрузка..”]
по умолчанию установлен текст. Как мне дождаться получения правильного текста на сайте? Я добавил код ниже, чтобы проверить и подтвердить, чтобы написать ответ
ваш текст

Перед показом элементов через 5 секунд

Загрузка…

после 5 секунд показа элементов

CM12-140

   def parse_navigation(self, response):
        for level1 in response.xpath('//div[@id="en-menu-products"]//ul/li/a'):
            label1 = level1.xpath('text()').get().strip()  # Получить текст
            url = level1.xpath('@href').get()  # Получить атрибут href

            meta = deepcopy(response.meta)
            meta['cat'] = label1
            if label1 in ["Диваны и loveseat"]:
                yield response.follow(url, self.parse_collection, meta=meta)
    def parse_collection(self, response):
        # Выбрать как ссылки, так и заголовки вместе
        rug_items = response.css('.products .product')
        for rug in rug_items:
            # Извлечь имя коврика из правильного элемента
            name = rug.css('.woocommerce-loop-product__title::text').get(default="").strip()
            meta = deepcopy(response.meta)
            meta['product_name'] = name
            url = rug.css('.woocommerce-LoopProduct-link::attr(href)').get(default="")
            yield Request(url,self.parse_detail, meta=meta, dont_filter=True)

    def parse_detail(self, response):
        time.sleep(5)
        item = OrderedDict()
        item['category'] = response.meta['cat']
        item['name'] = response.meta.get('product_name', '')
        item['Url'] = response.url
        # item['Attr_Collection'] = ''
        sku = response.xpath('//div[@class="et_pb_text_inner"]//p[@id="sku-id"]/text()').get(default="").strip()
        item['SKU'] = sku  # Добавить SKU к элементу
        description = response.xpath('//div[@class="et_pb_text_inner"]//p[@id="description"]/text()').getall()
        print("Извлеченное описание:", description)  # Отладочная строка
        full_description = ' '.join(description).strip()
        item['Description'] = full_description  # Добавить описание к элементу

        # item['brand'] = 'Adriana Hoyos'
        # item['Original Price'] = ''
        item['MetaKeywords'] = response.css('[name="keywords"]::attr(content)').get('').strip()
        item['MetaDescription'] = response.css('[name="description"]::attr(content)').get('').strip()

        yield item

Проблема в следующем коде означает, что описание получает текст из загрузки
item[‘SKU’] = sku # Добавить SKU к элементу
description = response.xpath(‘//div[@class=”et_pb_text_inner”]//p[@id=”description”]/text()’).getall()
print(“Извлеченное описание:”, description) # Отладочная строка
full_description = ‘ ‘.join(description).strip()
item[‘Description’] = full_description # Добавить описание к элементу

Получить правильный текст для сайта

Ответ или решение

Чтобы правильно извлечь текст с веб-страницы, где есть задержка при загрузке контента (например, текст появляется через 5 секунд после загрузки), необходимо использовать более подходящий подход к ожиданию загрузки элементов, чем просто использование time.sleep(). В библиотеке Scrapy, на которой, как видно из вашего кода, вы работаете, можно использовать Scrapy и scrapy-selenium или scrapy-playwright для автоматизации взаимодействия с JavaScript на странице. Рассмотрим некоторые ключевые моменты.

Почему текст "Loading…" вам не подходит?

Когда вы делаете запрос к веб-странице, некоторые части контента могут загружаться асинхронно (с помощью JavaScript) и сначала вы видите текст "Loading…". Вам нужно дождаться завершения загрузки контента, прежде чем пытаться извлекать данные.

Как вы можете решить эту проблему?

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

  1. Установка scrapy-selenium или scrapy-playwright:
    Установите один из пакетов, чтобы интегрировать управление браузером в Scrapy. Для начала установим scrapy-selenium:

    pip install scrapy-selenium
  2. Настройка scrapy-selenium:

    В вашем settings.py добавьте следующий код:

    from shutil import which
    
    DOWNLOADER_MIDDLEWARES = {
       'scrapy_selenium.SeleniumMiddleware': 800,
    }
    
    SELENIUM_DRIVER_NAME = 'firefox'  # или 'chrome'
    SELENIUM_DRIVER_EXECUTABLE_PATH = which('geckodriver')  # укажите путь к geckodriver или chromedriver
    SELENIUM_DRIVER_ARGUMENTS = ['-headless']  # если вы хотите запустить браузер в фоновом режиме
  3. Измените ваш parse_detail метод:
    Вместо использования time.sleep(), вы можете немного подождать, чтобы дать возможность JavaScript загружать нужные элементы.

    from scrapy_selenium import SeleniumRequest
    
    def parse_collection(self, response):
       rug_items = response.css('.products .product')
       for rug in rug_items:
           name = rug.css('.woocommerce-loop-product__title::text').get(default="").strip()
           meta = deepcopy(response.meta)
           meta['product_name'] = name
           url = rug.css('.woocommerce-LoopProduct-link::attr(href)').get(default="")
           yield SeleniumRequest(url=url, callback=self.parse_detail, dont_filter=True, meta=meta)
    
    def parse_detail(self, response):
       # Здесь контейнер для ожидания загрузки 'Loading…'
       loading_element = response.xpath('//p[text()="Loading..."]')
       if loading_element:
           self.logger.info("Дождитесь завершения загрузки страниц...")
    
       sku = response.xpath('//div[@class="et_pb_text_inner"]//p[@id="sku-id"]/text()').get(default="").strip()
       description = response.xpath('//div[@class="et_pb_text_inner"]//p[@id="description"]/text()').getall()
    
       item = OrderedDict()
       item['category'] = response.meta['cat']
       item['name'] = response.meta.get('product_name', '')
       item['Url'] = response.url
       item['SKU'] = sku
       full_description = ' '.join(description).strip()
       item['Description'] = full_description
       item['MetaKeywords'] = response.css('[name="keywords"]::attr(content)').get('').strip()
       item['MetaDescription'] = response.css('[name="description"]::attr(content)').get('').strip()
    
       yield item

Пояснение изменений:

  • Мы заменили Request на SeleniumRequest, который работает с scrapy-selenium и позволяет вам взаимодействовать с JavaScript на странице.
  • Вместо простого ожидания 5 секунд, мы теперь дожидаемся, когда текст "Loading…" исчезнет, прежде чем продолжить с извлечением информации.

С помощью указанных выше шагов вы сможете получить нужный текст с сайта, избегая проблем с асинхронной загрузкой данных. Убедитесь, что ваш код протестирован, чтобы гарантировать его корректную работу.

Оцените материал
Добавить комментарий

Капча загружается...