使用 python-Scrapy 抓取动态内容

Posted

技术标签:

【中文标题】使用 python-Scrapy 抓取动态内容【英文标题】:Scraping dynamic content using python-Scrapy 【发布时间】:2015-08-01 11:04:45 【问题描述】:

免责声明:我在 *** 上看到了许多其他类似的帖子,并尝试以相同的方式进行操作,但它们似乎不适用于该网站。

我正在使用 Python-Scrapy 从 koovs.com 获取数据。

但是,我无法获得动态生成的产品尺寸。具体来说,如果有人可以指导我从this 链接的下拉菜单中获取“不可用”尺寸标签,我将不胜感激。

我可以静态获取尺码列表,但这样做我只能获得尺码列表,而不是其中哪些是可用的。

【问题讨论】:

如果我错了,请纠正我,您可以获得尺码列表,但无法仅过滤可用尺码? 没错!我能够静态地获取它们并且这样做我只得到尺寸列表而不是它们中的哪些可用。我会把这个添加到问题中。 涉及硒可以吗? 我从来没有真正使用过 selenium,但如果它只需要获取一些数据而不是在实际抓取期间不需要,那么它很好。你能指导我如何使用它吗? This question 和 this one 帮助了我很多 【参考方案1】:

你也可以用ScrapyJS解决(不需要selenium和真正的浏览器):

该库使用 Splash 提供 Scrapy+javascript 集成。

按照SplashScrapyJS的安装说明,启动splash docker容器:

$ docker run -p 8050:8050 scrapinghub/splash

将以下设置放入settings.py

SPLASH_URL = 'http://192.168.59.103:8050' 

DOWNLOADER_MIDDLEWARES = 
    'scrapyjs.SplashMiddleware': 725,


DUPEFILTER_CLASS = 'scrapyjs.SplashAwareDupeFilter'

这是您的示例蜘蛛,它能够查看尺寸可用性信息:

# -*- coding: utf-8 -*-
import scrapy


class ExampleSpider(scrapy.Spider):
    name = "example"
    allowed_domains = ["koovs.com"]
    start_urls = (
        'http://www.koovs.com/only-onlall-stripe-ls-shirt-59554.html?from=category-651&skuid=236376',
    )

    def start_requests(self):
        for url in self.start_urls:
            yield scrapy.Request(url, self.parse, meta=
                'splash': 
                    'endpoint': 'render.html',
                    'args': 'wait': 0.5
                
            )

    def parse(self, response):
        for option in response.css("div.select-size select.sizeOptions option")[1:]:
            print option.xpath("text()").extract()

这是控制台上打印的内容:

[u'S / 34 -- Not Available']
[u'L / 40 -- Not Available']
[u'L / 42']

【讨论】:

两个很好的答案。这两种方法都有效。我想知道使用其中一个是否比另一个有优势? @PraveshJain 据我了解,如果您对这两种方法都满意,我会坚持使用 splash - 从理论上讲,这应该更快,因为它根本不涉及真正的浏览器。此外,您可以在非实屏无头环境中使用此选项。它也很容易设置,scrapy 代码几乎没有变化——关键部分是 scrapyjs 提供的中间件。希望对您有所帮助。 $ docker run -p 8050:8050 scrapinghub/splash - 这个命令..我怎样才能自动化这个命令以及 scrapy 使用 cron 作业调度程序来抓取数据.. 这显然不是一个好主意保持 docker 进程始终运行..在我在预定时间调用反应器之前可能是一些 sh ​​脚本? @Chelsea settings.py 应该存储在您的项目目录中。项目名称 > 项目名称 > settings.py @Plasmatiger 在 docker 中运行 docker-machine ip default 然后将您的 SPLASH_URL 更改为那个,为我解决了您的问题。【参考方案2】:

据我了解,大小可用性是在浏览器中执行的 javascript 中动态确定的。 Scrapy 不是浏览器,无法执行 javascript。

如果您可以切换到selenium browser automation tool,这里有一个示例代码:

from selenium import webdriver
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

browser = webdriver.Firefox()  # can be webdriver.PhantomJS()
browser.get('http://www.koovs.com/only-onlall-stripe-ls-shirt-59554.html?from=category-651&skuid=236376')

# wait for the select element to become visible
select_element = WebDriverWait(browser, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div.select-size select.sizeOptions")))

select = Select(select_element)
for option in select.options[1:]:
    print option.text

browser.quit()

打印出来:

S / 34 -- Not Available
L / 40 -- Not Available
L / 42

请注意,您可以使用 Chrome 或 Safari 等其他网络驱动程序来代替 Firefox。还可以选择使用无头 PhantomJS 浏览器。

如果需要,您还可以将 Scrapy 与 Selenium 结合使用,请参阅:

selenium with scrapy for dynamic page scrapy-webdriver seleniumcrawler

【讨论】:

【参考方案3】:

我遇到了这个问题,按照这些步骤轻松解决了

pip 安装启动 pip install scrapy-splash 点安装scrapyjs

下载并安装docker-toolbox

打开docker-quickterminal并进入

$ docker run -p 8050:8050 scrapinghub/splash

要设置 SPLASH_URL,请输入 $ docker-machine ip default(我的 IP 是 192.168.99.100)检查 docker 机器中配置的默认 ip

SPLASH_URL = 'http://192.168.99.100:8050'
DOWNLOADER_MIDDLEWARES = 
    'scrapyjs.SplashMiddleware': 725,


DUPEFILTER_CLASS = 'scrapyjs.SplashAwareDupeFilter'

就是这样!

【讨论】:

docker 工具箱链接已损坏... :.( @Anthony - 您可以从这里获取 docker:docker.com/get-docker Docker 工具箱适用于不符合 Docker for Mac 和 Docker for Windows 要求的旧 Mac 和 Windows 系统。【参考方案4】:

你要解释网站的json,例子 scrapy.readthedocs 和 testingcan.github.io

import scrapy
import json
class QuoteSpider(scrapy.Spider):
   name = 'quote'
   allowed_domains = ['quotes.toscrape.com']
   page = 1
   start_urls = ['http://quotes.toscrape.com/api/quotes?page=1']

   def parse(self, response):
      data = json.loads(response.text)
      for quote in data["quotes"]:
        yield "quote": quote["text"]
      if data["has_next"]:
          self.page += 1
          url = "http://quotes.toscrape.com/api/quotes?page=".format(self.page)
          yield scrapy.Request(url=url, callback=self.parse)

【讨论】:

以上是关于使用 python-Scrapy 抓取动态内容的主要内容,如果未能解决你的问题,请参考以下文章

Python-Scrapy创建第一个项目

discord.py-rewrite - 使用 PyQt5 的动态 Web 抓取无法正常工作

无法抓取动态内容(带有启动设置的抓取)

使用 python 抓取网页动态内容

使用 Python 抓取网页动态内容(动态 HTML/Javascript 表格)

使用 python 快速抓取动态内容