百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

如何使用 Scrapy 执行 JavaScript

itomcoil 2025-02-19 12:22 6 浏览

大多数现代网站都使用客户端 JavaScript 框架,例如 React、Vue 或 Angular。在没有服务器端渲染的情况下从动态网站抓取数据通常需要执行 JavaScript 代码。

我已经抓取了数百个网站,而且我总是使用 Scrapy。Scrapy 是一个流行的 Python 网页抓取框架。与其他 Python 抓取库(例如 Beautiful Soup)相比,Scrapy 帮助您根据一些最佳实践来构建代码。Scrapy 负责并发、收集统计数据、缓存、处理重试逻辑和许多其他问题。

在本文中,我比较了使用 Scrapy 执行 JavaScript 的最流行的解决方案,包括如何扩展无头浏览器,并介绍了与 ScrapingBee API 的开源集成以支持 JavaScript 和代理轮换。

使用 Scrapy 抓取动态网站

使用 Scrapy 抓取客户端呈现的网站曾经很痛苦。我经常自己检查浏览器网络工具上的 API 请求并从 JavaScript 变量中提取数据。虽然这些 hack 可能适用于某些网站,但我发现这些代码比传统的 XPATH 更难理解和维护。但要直接从 HTML 中抓取客户端数据,您首先需要执行 JavaScript 代码。

用于无头浏览器的 Scrapy 中间件

无头浏览器是没有图形用户界面的网络浏览器。我使用了三个库来使用 Scrapy 执行 JavaScript:scrapy-selenium、scrapy-splash 和 scrapy-scrapingbee。

所有三个库都集成为 Scrapy下载器中间件。一旦在您的项目设置中进行配置,您就不会从您的spiders产生一个正常的 Scrapy 请求,而是产生一个 SeleniumRequest、SplashRequest 或 ScrapingBeeRequest。

使用 Selenium 在 Scrapy 中执行

在本地,您可以使用带有scrapy-selenium中间件的 Scrapy 与无头浏览器交互。Selenium 是一个与浏览器交互的框架,通常用于测试应用程序、网页抓取和截屏。

Selenium 需要一个Web 驱动程序来与浏览器交互。例如,Firefox 要求您安装 geckodriver。然后,您可以在 Scrapy 项目设置中配置 Selenium。



from shutil import which

SELENIUM_DRIVER_NAME = 'firefox'

SELENIUM_DRIVER_EXECUTABLE_PATH = which('geckodriver')

SELENIUM_DRIVER_ARGUMENTS=['-headless']

DOWNLOADER_MIDDLEWARES = {

    'scrapy_selenium.SeleniumMiddleware': 800

}

在你的spiders中,你可以产生一个 SeleniumRequest。

from scrapy_selenium import SeleniumRequest

yield SeleniumRequest(url, callback=self.parse)

Selenium 允许您使用 Python 和 JavaScript 与浏览器进行交互。驱动程序对象可以从 Scrapy 响应中访问。有时在单击按钮后检查 HTML 代码会很有用。在本地,您可以使用 ipdb 调试器设置断点来检查 HTML 响应。

def parse(self, response):


    driver = response.request.meta['driver']
    driver.find_element_by_id('show-price').click()


    import ipdb; ipdb.set_trace()
    print(driver.page_source)

否则,可以从响应对象访问 Scrapy XPATH 和 CSS 选择器以从 HTML 中选择数据。

def parse(self, response):
    title = response.selector.xpath(
        '//title/@text'
    ).extract_first()

SeleniumRequest 接受一些额外的参数,例如在返回响应之前等待的 wait_time,等待 HTML 元素的 wait_until,截取屏幕截图的屏幕截图和用于执行自定义 JavaScript 脚本的脚本。

在生产中,scrapy-selenium 的主要问题是没有简单的方法来设置Selenium 网格以在远程机器上运行多个浏览器实例。接下来,我将比较两种使用 Scrapy 大规模执行 JavaScript 的解决方案。

使用 Splash 在 Scrapy 中执行 JavaScript

Splash是一种带有 API 的 Web 浏览器即服务。它由 Scrapy 的主要贡献者 Scrapinghub 维护,并通过scrapy-splash中间件与 Scrapy 集成。它也可以由 Scrapinghub 托管。

Splash 创建于 2013 年,在无头 Chrome 和其他主要无头浏览器于 2017 年发布之前。从那时起,其他流行的项目(如 PhantomJS)已停止使用,转而支持 Firefox、Chrome 和 Safari 无头浏览器。

您可以使用 Docker 在本地运行 Splash 实例。

docker run -p 8050:8050 scrapinghub/splash`

配置 Splash 中间件需要添加多个中间件并在项目设置中更改 HttpCompressionMiddleware 的默认优先级。

SPLASH_URL = 'http://192.168.59.103:8050'


DOWNLOADER_MIDDLEWARES = {
    'scrapy_splash.SplashCookiesMiddleware': 723,
    'scrapy_splash.SplashMiddleware': 725,
    'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,
}


SPIDER_MIDDLEWARES = {
    'scrapy_splash.SplashDeduplicateArgsMiddleware': 100,
}


DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter'
HTTPCACHE_STORAGE = 'scrapy_splash.SplashAwareFSCacheStorage'

然后你可以产生一个带有可选参数 wait 和 lua_source 的 SplashRequest。

from scrapy_splash import SplashRequest

yield SplashRequest(url, callback=self.parse, args={
	'wait': 0.5,
    'lua_source': script
})

Splash 是一种流行的解决方案,因为它已经推出了很长时间,但它有两个主要问题:它使用自定义的无头浏览器,并且需要在 Lua 中编码才能与网站交互。由于这两个问题,在我的最后一个抓取项目中,我决定为 ScrapingBee API 创建一个中间件。

使用 ScrapingBee 在 Scrapy 中执行 JavaScript

ScrapingBee是一个 Web 抓取 API,可以为您处理无头浏览器和代理。ScrapingBee 使用最新的无头 Chrome 版本并支持 JavaScript 脚本。

与其他两个中间件一样,您可以简单地使用 pip 安装scrapy-scrapingbee中间件。

pip install scrapy-scrapingbee

首先,您需要创建一个 ScrapingBee 帐户以获取 API 密钥。然后你可以根据你的项目设置中的 ScrapingBee 计划添加下载器中间件并设置并发。

SCRAPINGBEE_API_KEY = 'REPLACE-WITH-YOUR-API-KEY'

DOWNLOADER_MIDDLEWARES = {
    'scrapy_scrapingbee.ScrapingBeeMiddleware': 725,
}

CONCURRENT_REQUESTS = 1

然后你可以从 ScrapingBeeSpider 继承你的蜘蛛并产生一个 ScrapingBeeRequest。

from scrapy_scrapingbee import ScrapingBeeSpider, ScrapingBeeRequest

class HttpbinSpider(ScrapingBeeSpider):
    name = 'httpbin'
    start_urls = [
        'https://httpbin.org',
    ]


    def start_requests(self):
        for url in self.start_urls:
            yield ScrapingBeeRequest(url)


    def parse(self, response):
        …

ScrapingBeeRequest 采用可选的 params 参数来执行 js_snippet,在返回响应之前设置自定义等待,或者使用 wait_for 在 HTML 代码中等待 CSS 或 XPATH 选择器。

在某些网站中,当您滚动浏览页面时,HTML 会异步加载。您可以使用下面的 JavaScript 片段滚动到页面末尾。

JS_SNIPPET = 'window.scrollTo(0, document.body.scrollHeight);'

yield ScrapingBeeRequest(url, params={
           'js_snippet': JS_SNIPPET,
           # 'wait': 3000,
           # 'wait_for': '#swagger-ui',
       })

ScrapingBee 收集了其他常见的 JavaScript 片段,以便与ScrapingBee 文档中的网站进行交互。

在幕后,scraping-scrapingbee 中间件将原始请求转换为转发到 ScrapingBee API 的请求,并对 URL 查询字符串中的每个参数进行编码。API 端点记录在您的 Scrapy 日志中,并且 api_key 被 ScrapingBeeSpider 隐藏。

2020-06-22 12:32:07 [scrapy.core.engine] DEBUG: Crawled (200)  (referer: None)

在您的蜘蛛的解析方法中,中间件将 response.url 解析为传递给 ScrapingBeeRequest 的原始 URL。

def parse(self, response):
    assert response.url == 'https://httpbin.org'

使用 ScrapingBee 的另一个优点是您可以使用以下参数访问不同国家的住宅代理和开箱即用的代理轮换。

yield ScrapingBeeRequest(url, params={
   'premium_proxy': True,
   'country_code': 'fr',
})

使用 Scrapy 缓存和并发来更快地抓取

Scrapy 在底层使用了 Twisted,这是一个异步网络框架。Twisted 使 Scrapy 快速并且能够同时抓取多个页面。但是,要执行 JavaScript 代码,您需要使用真正的浏览器或无头浏览器来解析请求。无头浏览器有两个挑战:它们速度较慢且难以扩展。

在无头浏览器中执行 JavaScript 并等待所有网络调用每页可能需要几秒钟。抓取多个页面时,它会使抓取器显着变慢。希望 Scrapy 提供缓存来加速生产运行的开发和并发请求。

在本地,在开发爬虫时,您可以使用 Scrapy 的内置缓存系统。由于响应存储在计算机上的隐藏文件夹 .scrapy/httpcache 中,它将使后续运行更快。您可以在项目设置中激活 HttpCacheMiddleware:

HTTPCACHE_ENABLED = True

无头浏览器的另一个问题是它们会为每个请求消耗内存。在生产环境中,您需要一个可以处理多个浏览器的环境。要同时发出多个请求,您可以修改项目设置:

CONCURRENT_REQUESTS = 1

使用 ScrapingBee 时,请记住根据您的 ScrapingBee 计划设置并发。

结论

我比较了三个使用 Scrapy 渲染和执行 JavaScript 的 Scrapy 中间件。Selenium 允许您在所有主要的无头浏览器中使用 Python 与 Web 浏览器进行交互,但可能难以扩展。Splash 可以使用 Docker 在本地运行或部署到 Scrapinghub,但依赖于自定义浏览器实现,您必须在 Lua 中编写脚本。ScrapingBee 使用最新的 Chrome 无头浏览器,允许您在 JavaScript 中执行自定义脚本,并为最难抓取的网站提供代理轮换。


scrapy-selenium

scrapy-splash

scrapy-scrapingbee

本地运行

是的

是的,使用 Docker

远程扩展

使用Selenium Grid

使用 Scrapinghub

使用ScrapingBee

脚本语言

JavaScript、Python

lua

JavaScript

浏览器支持

Chrome, Firefox, Edge, Safari

Splash

Latest Headless Chrome

代理轮换

由另一项服务 Crawlera 提供

是的,由相同的中间件提供

相关推荐

tesseract-ocr 实现图片识别功能

最近因为项目需要,接触了一下关于图像识别的相关内容,例如Tesseract。具体如何安装、设置在此不再赘述。根据项目要求,我们需要从省平台获取实时雨水情况数据,原以为获取这样的公开数据比较简单,上去一...

跨平台Windows和Linux(银河麒麟)操作系统OCR识别应用

1运行效果在银河麒麟桌面操作系统V10(SP1)上运行OCR识别效果如下图:2在Linux上安装TesseractOCR引擎2.1下载tesseract-ocr和leptonicahttps:...

JAVA程序员自救之路——SpringAI文档解析tika

ApacheTika起源于2007年3月,最初是ApacheLucene项目的子项目,于2010年5月成为Apache组织的顶级项目。它利用现有的解析类库,能够侦测和提取多种不同格式文档中的元数据...

Python印刷体文字识别教程

在Python中实现印刷体文字识别(OCR),通常使用TesseractOCR引擎结合Python库。以下是详细步骤和示例:1.安装依赖库bashpipinstallpytesseractp...

图片转文字--四种OCR工具的安装和使用

本文仅测试简单的安装和使用,下一步应该是测试不同数据集下的检测准确率和检测效率,敬请期待。作者的系统环境是:笔记本:ThindPadP520OS:win11显卡:QuadroP520一、EasyO...

mac 安装tesseract、pytesseract以及简单使用

一.tesseract-OCR的介绍1.tesseract-OCR是一个开源的OCR引擎,能识别100多种语言,专门用于对图片文字进行识别,并获取文本。但是它的缺点是对手写的识别能力比较差。2.用te...

【Python深度学习系列】Win10下CUDA+cuDNN+Tensorflow安装与配置

这是我的第292篇原创文章。一、前置知识安装GPU版本的pytorch和tensorflow之前需要理清楚这几个关系:显卡(电脑进行数模信号转换的设备,有的电脑可能是双显卡,一个是inter的集成显卡...

手把手教你本地部署AI绘图Stable Diffusion!成功率100%!

导语:无需每月付费订阅,无需高性能服务器!只需一台普通电脑,即可免费部署爆火的AI绘图工具StableDiffusion。本文提供“极速安装包”和“手动配置”双方案,从环境搭建到模型调试,手把手教你...

本地AI Agent Hello World(Python版): Ollama + LangChain 快速上手指南

概要本文将用最简洁的Python示例(后续还会推出Java版本),带你逐步完成本地大模型Agent的“HelloWorld”:1、介绍核心工具组件:Ollama、LangChain和...

python解释器管理工具pyenv使用说明

简介pyenv可以对python解释器进行管理,可以安装不同版本的python,管理,切换不同版本很方便,配置安装上比anaconda方便。pyenv主要用来对Python解释器进行管理,可以...

Deepseek实战:企业别只会用Ollama,也可以用SGLang

SGLang:企业级的“性能之王”优点吞吐量碾压级优势通过零开销批处理调度器、缓存感知负载均衡器等核心技术,SGLang的吞吐量提升显著。例如,在处理共享前缀的批量请求时,其吞吐量可达158,59...

用LLaMA-Factory对Deepseek大模型进行微调-安装篇

前面的文章已经把知识库搭建好了,还通过代码的形式做完了RAG的实验。接下来呢,咱们要通过实际操作来完成Deepseek的另一种优化办法——微调。一、环境因为我这台电脑性能不太好,所以就在Au...

碎片时间学Python-03包管理器

一、pip(Python官方包管理器)1.基础命令操作命令安装包pipinstallpackage安装特定版本pipinstallnumpy==1.24.0升级包pipinstall-...

ubuntu22/24中利用国内源部署大模型(如何快速安装必备软件)

本地AI部署的基础环境,一般会用到docker,dockercompose,python环境,如果直接从官网下载,速度比较慢。特意记录一下ubuntu使用国内源快速来搭建基础平台。一,docke...

还不会deepseek部署到本地?这篇教程手把手教会你

一、为什么要把DeepSeek部署到本地?新手必看的前置知识近期很多读者在后台询问AI工具本地部署的问题,今天以国产优质模型DeepSeek为例,手把手教你实现本地化部署。本地部署有三大优势:数据隐私...