Scrap и селен, кажется, вмешиваются друг в друга - PullRequest
0 голосов
/ 13 января 2019

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

Краткая справка по моему коду: я пытался собрать информацию о продуктах с нескольких веб-сайтов, используя scrapy, и я также использую селен, потому что мне нужно нажимать кнопки «Просмотреть больше» и «Нет, спасибо» на веб-странице. Поскольку на веб-сайте есть раздел href для разных категорий, мне также нужно запросить эти «подссылки», чтобы убедиться, что я не пропускаю элементы, не показанные на корневой странице.

Проблема в том, что в цикле for l in product_links: я замечаю, что скрап и селен действуют странно. Например, я ожидаю, что response.url == self.driver.current_url всегда будет правдой. Тем не менее, они становятся другими в середине этого цикла. Кроме того, self.driver, кажется, захватывает некоторые элементы, не существующие в текущем URL в products = self.driver.find_elements_by_xpath('//div[@data-url]'), и затем не может получить их снова в sub = self.driver.find_elements_by_xpath('//div[(@class="shelf-container") and (.//div/@data-url="' + l + '")]//h2')

Большое спасибо. Я действительно смущен.

from webScrape.items import ProductItem
from scrapy import Spider, Request
from selenium import webdriver

class MySpider(Spider):
    name = 'name'
    domain = 'https://uk.burberry.com'

    def __init__(self):
        super().__init__()
        self.driver = webdriver.Chrome('path to driver')
        self.start_urls = [self.domain + '/' + k for k in ('womens-clothing', 'womens-bags', 'womens-scarves',
                                        'womens-accessories', 'womens-shoes', 'make-up', 'womens-fragrances')]
        self.pool = set()

    def parse(self, response):
        sub_links = response.xpath('//h2[starts-with(@class, "shelf1-section-title")]/a/@href').extract()
        if len(sub_links) > 0:
            for l in sub_links:
                yield Request(self.domain + l, callback = self.parse)
        self.driver.get(response.url)
        email_reg = self.driver.find_element_by_xpath('//button[@class="dc-reset dc-actions-btn js-data-capture-newsletter-block-cancel"]')
        if email_reg.is_displayed():
            email_reg.click()
        # Make sure to click all the "load more" buttons
        load_more_buttons = self.driver.find_elements_by_xpath('//div[@class="load-assets-button js-load-assets-button ga-shelf-load-assets-button"]')
        for button in load_more_buttons:
            if button.is_displayed():
                button.click()
        products = self.driver.find_elements_by_xpath('//div[@data-url]')
        product_links = [item.get_attribute('data-url') for item in products if item.get_attribute('data-url').split('-')[-1][1:] not in self.pool]
        for l in product_links:
            sub = self.driver.find_elements_by_xpath('//div[(@class="shelf-container") and (.//div/@data-url="' + l + '")]//h2')
            if len(sub) > 0:
                sub_category = ', '.join(set([s.get_attribute('data-ga-shelf-title') for s in sub]))
            else:
                sub_category = ''
            yield Request(self.domain + l, callback = self.parse_product, meta = {'sub_category': sub_category})

    def parse_product(self, response):
        item = ProductItem()
        item['id'] = response.url.split('-')[-1][1:]
        item['sub_category'] = response.meta['sub_category']
        item['name'] = response.xpath('//h1[@class="product-title transaction-title ta-transaction-title"]/text()').extract()[0].strip()
        self.pool.add(item['id'])
        yield item
        others = response.xpath('//input[@data-url]/@data-url').extract()
        for l in others:
            if l.split('-')[-1][1:] not in self.pool:
                yield Request(self.domain + l, callback = self.parse_product, meta = response.meta)

1 Ответ

0 голосов
/ 14 января 2019

Scrapy - это асинхронная структура. Код в ваших parse*() методах не всегда работает линейно. Везде, где есть yield, выполнение этого метода может останавливаться на некоторое время, пока выполняются другие части кода.

Поскольку в цикле есть yield, это объясняет, почему вы испытываете такое неожиданное поведение. На yield некоторый другой код вашей программы возобновляет выполнение и может переключить драйвер Selenium на другой URL, а когда код возобновляет цикл, URL-адрес драйвера Selenium изменился.

Если честно, насколько я понимаю, вам не нужен Selenium in Scrapy для вашего случая использования. В Scrapy такие вещи, как Splash или Selenium, используются только в очень специфических сценариях, например, для предотвращения обнаружения ботов.

Обычно лучше определить структуру HTML страницы и параметры, используемые в запросах, используя инструменты разработчика из вашего веб-браузера (Inspect, Network), а затем воспроизвести их в Scrapy.

...