【问题标题】:Passing Selenium opened URL to Scrapy and scraping the data将 Selenium 打开的 URL 传递给 Scrapy 并抓取数据
【发布时间】:2018-04-03 17:37:49
【问题描述】:

我一直在尝试从 Steam 商店中抓取生化奇兵游戏并将其名称、价格和链接保存在 CSV 文件中。我知道如何通过使用 Scrapy 来做到这一点,但我真的很想知道是否有一种方法可以结合 Scrapy 和 Selenium 来做到这一点。我想使用 Selenium 只是为了摆脱某些游戏商店网站上弹出的年龄检查门。

Example of an age gate

Example of another age gate

所以我已经设法通过使用 Scrapy 来抓取没有年龄限制的游戏,并且我已经成功地使用 Selenium 绕过了年龄限制。

我遇到的问题是将 Selenium 通过绕过年龄门打开的游戏商店网站传递给 Scrapy,以便它可以抓取它。由于一切正常,我得出的结论是问题在于我不知道如何连接它们。

def parse_product(self, response):
    product = ScrapesteamItem()
    sel = self.driver
    #Passing first age gate
    if '/agecheck/app/' in response.url:
        sel.get(response.url)
        select = Select(sel.find_element_by_xpath("""//*[@id="ageYear"]"""))
        select.select_by_visible_text("1900")
        sel.find_element_by_xpath("""//*[@id="agecheck_form"]/a""").click()
        #Pass Selenium newly opened site to Scrapy
    #Passing second age gate
    elif '/agecheck' in response.url:
        sel.get(response.url)
        sel.find_element_by_xpath("""//*[@id="app_agegate"]/div[3]/a[1]""").click()
        #Pass Selenium newly opened site to Scrapy
    #Scraping the data with scrapy
    else:
        name = response.css('.apphub_AppName ::text').extract()
        price = response.css('div.game_purchase_price ::text, div.discount_final_price ::text').extract()
        link = response.css('head > link:nth-child(40) ::attr(href)').extract()

        for product in zip(name, price, link):
            scrapedInfo = {
                'NAME' : product[0],
                'PRICE' : product[1].rstrip().lstrip(),
                'LINK' : product[2]
            }

            yield scrapedInfo

我希望有人知道怎么做(如果可能的话)。

附:我知道有更好的方法来抓取 Steam 商店,我知道可能有一个 API,但在我去了解之前,我想知道是否有办法做到这一点,即使它不是最理想的。

【问题讨论】:

  • 我强烈建议使用BeautifulSoup 和selenium 的组合。使用selenium通过自动浏览器与网页进行交互,并将页面源HTML传递给BeautifulSoup以解析和提取您想要的内容。
  • 当然,我会试试的。你能告诉我如何在 Selenium 中传递页面源 HTML,为什么你更喜欢 BeautifulSoup 而不是 Scrapy?

标签: python selenium web-scraping scrapy


【解决方案1】:

直接的答案是:应用与使用 scrapy 抓取数据相同的抓取代码,即类似这样的内容:

from scrapy.spiders import xxxxxxxSpider

class MySpider(SitemapSpider):
    sitemap_urls = ['http://www.xxxxxxxSpider.com']
    sitemap_rules = [
        ('/product/', 'parse_product'),        
    ]

    def my_custom_parse_product(self, response):
        name = response.css('.apphub_AppName ::text').extract()
            price = response.css('div.game_purchase_price ::text, div.discount_final_price ::text').extract()
            link = response.css('head > link:nth-child(40) ::attr(href)').extract()

            for product in zip(name, price, link):
                scrapedInfo = {
                    'NAME' : product[0],
                    'PRICE' : product[1].rstrip().lstrip(),
                    'LINK' : product[2]
                }

                yield scrapedInfo

    def parse_product(self, response):
        product = ScrapesteamItem()
        sel = self.driver
        #Passing first age gate
        if '/agecheck/app/' in response.url:
            sel.get(response.url)
            select = Select(sel.find_element_by_xpath("""//*[@id="ageYear"]"""))
            select.select_by_visible_text("1900")
            sel.find_element_by_xpath("""//*[@id="agecheck_form"]/a""").click()
            #Pass Selenium newly opened site to Scrapy
            response = HtmlResponse(url=response.url, body=driver.page_source) 
            #scrapy.http.Response(url=response.url, body=driver.page_source) 
            self.parse(response);               
        #Passing second age gate
        elif '/agecheck' in response.url:
            sel.get(response.url)
            sel.find_element_by_xpath("""//*[@id="app_agegate"]/div[3]/a[1]""").click()
            #Pass Selenium newly opened site to Scrapy
            response = HtmlResponse(url=response.url, body=driver.page_source) 
            #scrapy.http.Response(url=response.url, body=driver.page_source) 
            self.parse(response); 
        #Scraping the data with scrapy
        else:
            my_custom_parse_product(response) #will actually scrap data

但看起来受年龄保护的页面将包含相同的数据,但在不同的元素中(例如,不在 response.css('.apphub_AppName ::text') 中)在这种情况下,您将需要为每种页面类型实现自己的抓取代码

【讨论】:

  • 遗憾的是由于某种原因它不起作用。它只是不会写入 CSV 文件。通过这样做,只有没有年龄限制的游戏才会被写入 CSV 文件。我认为这与您尝试传递给 my_custom_parse_product 函数的参数有关。您正在传递 Scrapy 提供的响应对象,而不是由 selenium 打开的响应对象。您传递的响应参数与 Selenium 一旦通过年龄门打开的网站无关。页面被打开,但没有被刮掉。没有显示错误,webdriver 打开它,Scrapy 什么也不做。
猜你喜欢
  • 1970-01-01
  • 2017-03-27
  • 2021-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多