2025年使用Scrapy和Playwright解决网页抓取挑战的方案

0. 引言
随着互联网技术的发展,网页内容呈现方式越来越复杂,大量网站使用JavaScript动态渲染内容,这给传统的网络爬虫带来了巨大挑战。在2025年的网络爬虫领域,Scrapy和Playwright的结合为我们提供了一个强大的解决方案,能够有效处理现代网站的抓取需求。本文将详细介绍如何利用Scrapy-Playwright组合来解决网页抓取中的各种挑战,包括动态内容加载和验证码处理等问题。
1. Scrapy-Playwright介绍
1.1 什么是Scrapy-Playwright?
Scrapy-Playwright 是一款中间件,它将 Scrapy(一个快速且强大的Python网络抓取框架)与 Playwright(一个浏览器自动化库)集成在一起。这种组合使Scrapy能够通过利用Playwright渲染动态内容、与网页交互以及无缝管理浏览器上下文的能力来处理大量使用JavaScript的网站。
1.2 为什么使用Scrapy-Playwright?
虽然Scrapy在抓取静态网站方面非常出色,但许多现代网站严重依赖JavaScript来动态渲染内容。传统的Scrapy爬虫在处理这些网站时可能会遇到困难,经常会丢失关键数据或无法导航复杂的页面结构。Scrapy-Playwright通过使Scrapy能够控制无头浏览器来弥合这一差距,确保所有动态内容都已完全加载并可供抓取。
1.3 使用Scrapy-Playwright的优势
- JavaScript渲染: 轻松抓取使用JavaScript动态加载内容的网站。
- 无头浏览器: 在没有可见浏览器的情况下执行抓取任务,优化性能。
- 高级交互: 处理复杂的交互,例如点击按钮、填写表单和在页面之间导航。
- 异步操作: 利用Playwright的异步功能来加速抓取任务。
2. 安装与配置
2.1 安装
要开始使用Scrapy-Playwright,您需要安装Scrapy和Playwright。以下是设置环境的方法:
- 安装Scrapy:
pip install scrapy
- 安装Scrapy-Playwright:
pip install scrapy-playwright
- 安装Playwright浏览器:
安装Playwright后,您需要安装必要的浏览器二进制文件。
playwright install
2.2 配置环境
设置新的Scrapy项目
首先,如果您还没有,请创建一个新的Scrapy项目:
scrapy startproject myproject
cd myproject
配置Playwright
接下来,您需要在Scrapy项目的设置中启用Playwright。打开settings.py并添加以下配置:
# settings.py# 启用Playwright下载器中间件
DOWNLOADER_MIDDLEWARES = {'scrapy_playwright.middleware.ScrapyPlaywrightDownloadHandler': 543,
}# 为HTTP和HTTPS指定下载处理程序
DOWNLOAD_HANDLERS = {'http': 'scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler','https': 'scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler',
}# 启用Playwright设置
TWISTED_REACTOR = 'twisted.internet.asyncioreactor.AsyncioSelectorReactor'# Playwright设置(可选)
PLAYWRIGHT_BROWSER_TYPE = 'chromium' # 可以是'chromium'、'firefox'或'webkit'
PLAYWRIGHT_LAUNCH_OPTIONS = {'headless': True,
}
3. 基本用法
3.1 创建爬虫
设置完成后,让我们创建一个使用Playwright抓取JavaScript渲染网站的简单爬虫。为了说明,我们将抓取一个假设的网站,该网站动态加载内容。
在spiders目录中创建一个新的爬虫文件dynamic_spider.py:
# spiders/dynamic_spider.pyimport scrapy
from scrapy_playwright.page import PageCoroutineclass DynamicSpider(scrapy.Spider):name = "dynamic"start_urls = ["https://example.com/dynamic"]def start_requests(self):for url in self.start_urls:yield scrapy.Request(url,meta={"playwright": True,"playwright_page_coroutines": [PageCoroutine("wait_for_selector", "div.content"),],},)async def parse(self, response):# 在JavaScript渲染内容后提取数据for item in response.css("div.content"):yield {"title": item.css("h2::text").get(),"description": item.css("p::text").get(),}# 如果需要,处理分页或其他交互
3.2 处理JavaScript渲染的内容
在上面的示例中:
playwright: True: 通知Scrapy为此请求使用Playwright。playwright_page_coroutines: 指定要使用Playwright执行的操作。在这里,它等待选择器div.content,以确保动态内容在解析之前已加载。- 异步
parse方法: 利用异步功能来有效地处理响应。
4. 处理验证码挑战
4.1 验证码解决方案概述
网络抓取中的一项重大挑战是处理验证码,验证码旨在防止自动访问。在处理需要验证码的网站时,我们需要一个可靠的解决方案来自动识别和解决这些挑战,以保持抓取流程的连续性。
4.2 配置验证码解决方案
要配置验证码解决方案,您需要:
- 获取验证码解决扩展程序: 下载适合您使用的验证码解决方案的浏览器扩展程序,并将其放在项目目录中。
- 配置扩展程序:
- 在扩展程序目录中找到配置文件
./assets/config.json。 - 将选项
enabledForcaptcha设置为true,并将captchaMode调整为token以进行自动解决。
- 在扩展程序目录中找到配置文件
示例config.json:
{"enabledForcaptcha": true,"captchaMode": "token"// 其他设置保持不变
}
- 更新Scrapy设置以加载扩展程序:
# settings.pyimport os
from pathlib import Path# 现有的Playwright设置
PLAYWRIGHT_BROWSER_TYPE = 'chromium'
PLAYWRIGHT_LAUNCH_OPTIONS = {'headless': False, # 必须为False才能加载扩展程序'args': ['--disable-extensions-except={}'.format(os.path.abspath('CaptchaSolver.Extension')),'--load-extension={}'.format(os.path.abspath('CaptchaSolver.Extension')),],
}# 确保设置了Twisted反应器
TWISTED_REACTOR = 'twisted.internet.asyncioreactor.AsyncioSelectorReactor'
注意: 加载浏览器扩展程序需要浏览器以非无头模式运行,因此设置'headless': False。
4.3 创建处理验证码的爬虫
以下是处理验证码的爬虫代码示例:
# spiders/captcha_spider.pyimport scrapy
from scrapy_playwright.page import PageCoroutine
import asyncioclass CaptchaSpider(scrapy.Spider):name = "captcha_spider"start_urls = ["https://site.example/captcha-protected"]def start_requests(self):for url in self.start_urls:yield scrapy.Request(url,meta={"playwright": True,"playwright_page_coroutines": [PageCoroutine("wait_for_selector", "iframe[src*='captcha']"),PageCoroutine("wait_for_timeout", 1000), # 等待扩展程序处理],"playwright_context": "default",},callback=self.parse_captcha)async def parse_captcha(self, response):page = response.meta["playwright_page"]# 找到captcha复选框或框架并相应地进行交互try:# 等待captcha框架可用await page.wait_for_selector("iframe[src*='captcha']", timeout=10000)frames = page.framescaptcha_frame = Nonefor frame in frames:if 'captcha' in frame.url:captcha_frame = framebreakif captcha_frame:# 点击captcha复选框await captcha_frame.click("div#checkbox")# 等待解决验证码await page.wait_for_selector("div.captcha-success", timeout=60000) # 根据需要调整选择器self.logger.info("验证码已成功解决。")else:self.logger.warning("未找到captcha框架。")except Exception as e:self.logger.error(f"处理验证码时出错:{e}")# 在验证码解决后继续解析页面for item in response.css("div.content"):yield {"title": item.css("h2::text").get(),"description": item.css("p::text").get(),}# 如果需要,处理分页或其他交互
4.4 运行爬虫
确保所有依赖项都已安装,并使用以下命令运行您的爬虫:
scrapy crawl captcha_spider
5. 高级功能
当您熟悉基本功能后,Scrapy-Playwright提供了一些高级功能来增强您的抓取项目。
5.1 处理多个页面
使用Playwright的导航功能可以简化抓取多个页面或在网站中导航。
# spiders/multi_page_spider.pyimport scrapy
from scrapy_playwright.page import PageCoroutineclass MultiPageSpider(scrapy.Spider):name = "multipage"start_urls = ["https://example.com/start"]def start_requests(self):for url in self.start_urls:yield scrapy.Request(url,meta={"playwright": True,"playwright_page_coroutines": [PageCoroutine("wait_for_selector", "div.list"),PageCoroutine("evaluate", "window.scrollTo(0, document.body.scrollHeight)"),],},)async def parse(self, response):# 从第一个页面提取数据for item in response.css("div.list-item"):yield {"name": item.css("span.name::text").get(),"price": item.css("span.price::text").get(),}# 导航到下一页next_page = response.css("a.next::attr(href)").get()if next_page:yield scrapy.Request(response.urljoin(next_page),callback=self.parse,meta={"playwright": True,"playwright_page_coroutines": [PageCoroutine("wait_for_selector", "div.list"),],},)
5.2 使用Playwright上下文
Playwright允许创建多个浏览器上下文,这对于处理会话、cookie或并行抓取任务非常有用。
# settings.pyPLAYWRIGHT_CONTEXTS = {"default": {"viewport": {"width": 1280, "height": 800},"user_agent": "CustomUserAgent/1.0",},"mobile": {"viewport": {"width": 375, "height": 667},"user_agent": "MobileUserAgent/1.0","is_mobile": True,},
}
在您的爬虫中,指定上下文:
# spiders/context_spider.pyimport scrapyclass ContextSpider(scrapy.Spider):name = "context"start_urls = ["https://example.com"]def start_requests(self):yield scrapy.Request(self.start_urls[0],meta={"playwright": True,"playwright_context": "mobile",},)async def parse(self, response):# 您的解析逻辑在这里pass
5.3 与中间件集成
Scrapy-Playwright可以与其他中间件集成,以增强功能,例如处理重试、代理管理或自定义标头。
# settings.pyDOWNLOADER_MIDDLEWARES.update({'scrapy.downloadermiddlewares.retry.RetryMiddleware': 550,'scrapy_playwright.middleware.ScrapyPlaywrightDownloadHandler': 543,
})# 设置自定义标头的示例
DEFAULT_REQUEST_HEADERS = {'User-Agent': 'MyCustomAgent/1.0','Accept-Language': 'en-US,en;q=0.9',
}
6. 最佳实践
为了充分利用Scrapy-Playwright,请考虑以下最佳实践:
- 优化Playwright使用: 仅对需要JavaScript渲染的请求使用Playwright,以节省资源。
- 管理浏览器上下文: 尽可能重复使用浏览器上下文,以提高性能并减少开销。
- 优雅地处理超时: 设置适当的超时和错误处理,以管理加载缓慢的页面。
- 尊重Robots.txt和服务条款: 始终确保您的抓取活动符合目标网站的政策。
- 实施节流和延迟: 通过实施礼貌的抓取实践,防止过度加载目标服务器。
- 安全存储敏感信息: 安全地存储敏感信息(例如API密钥),并避免在脚本中对其进行硬编码。
- 监控和记录抓取活动: 记录您的抓取操作,以便快速识别和解决问题。
7. 结语
Scrapy-Playwright是网络抓取领域的革命性组合,它弥合了静态内容和动态内容提取之间的差距。通过利用Scrapy强大的框架和Playwright先进的浏览器自动化的力量,您可以轻松地处理最具挑战性的抓取任务。
在2025年的网络环境中,随着网站变得越来越复杂,结合使用这些工具将是高效数据采集的关键。通过合理配置验证码解决方案,您还能够克服验证码挑战,确保从最受保护的网站中持续收集数据。
无论您是在抓取电子商务网站、社交媒体平台还是任何大量使用JavaScript的网站,掌握Scrapy-Playwright都将为您提供成功所需的工具。通过遵循本文介绍的最佳实践并利用这些强大的集成,您可以构建高效、可靠和可扩展的网络抓取解决方案,以满足您在2025年及以后的数据采集需求。
相关文章:
2025年使用Scrapy和Playwright解决网页抓取挑战的方案
0. 引言 随着互联网技术的发展,网页内容呈现方式越来越复杂,大量网站使用JavaScript动态渲染内容,这给传统的网络爬虫带来了巨大挑战。在2025年的网络爬虫领域,Scrapy和Playwright的结合为我们提供了一个强大的解决方案ÿ…...
可靠消息投递demo
以下是一个基于 Spring Boot RocketMQ 的完整分布式事务实战 Demo,包含事务消息、本地事务、自动重试、死信队列(DLQ) 等核心机制。代码已充分注释,可直接运行。 一、项目结构 src/main/java ├── com.example.rocketmq │ …...
阻止 Mac 在运行任务时进入休眠状态
掌握Caffeinate命令:让您的 Mac 保持清醒以完成关键任务 开发人员经常发现自己在 Mac 上运行持续时间较长的进程。无论是大量文件上传、广泛的数据分析脚本,还是复杂的构建过程,我们最不希望的就是我们的机器在任务中途进入睡眠状态。输入 c…...
Copilot提示词库用法:调整自己想要的,记住常用的,分享该共用的
不论你是 Microsoft 365 Copilot 的新用户还是熟练运用的老鸟,不论你是使用copilot chat,还是在office365中使用copilot,copilot提示词库都将帮助你充分使用copilot这一划时代的产品。它不仅可以帮助你记住日常工作中常用的prompt提示词&…...
Python实战(3)-数据库操作
前面说过,可用的SQL数据库引擎有很多,它们都有相应的Python模块。这些数据库引擎大都作为服务器程序运行,连安装都需要有管理员权限。为降低Python DB API的使用门槛,我选择了一个名为SQLite的小型数据库引擎。它不需要作为独立的…...
LeetCode 160 Intersection Of Two Linked Lists 相交链表 Java
题目:找到两个相交列表的起始点,如图c1开始为A和B两个链表的相交点 举例1:8为两个链表的相交点。 注意:相交不止是数值上的相同。 举例2:2为相交点 举例3:没有相交点 解题思路: 相交证明最后一…...
AI Agent中的MCP详解
一、协议定义与核心价值 MCP(Model Context Protocol,模型上下文协议)是由Anthropic公司于2024年11月推出的开放标准协议,其核心目标是通过建立统一接口规范,解决AI模型与外部系统集成效率低下的行业痛点。该协议通过标准化通信机制,使大型语言模型(LLM)能够无缝对接数…...
win系统上自动化安装配置WSL linux和各种生信工具教程
windows系统上自动化安装配置WSL linux系统和各种生信工具教程 高通量测序原始数据的上游分析模块介绍 我开发的OmicsTools软件的这些分析测序原始数据的上游处理分析模块需要使用到linux和linux系统中的一些生信工具,在这里我开发了在windows系统中自动化安装WSL …...
统计可重复列表中的TOP N
文章目录 方案1:HashMap统计 全排序实现步骤:代码实现:优缺点: 方案2:HashMap统计 最小堆(优先队列)实现步骤:代码实现:优缺点: 方案3:Java Str…...
PowerBI纯小白如何驾驭DAX公式一键生成:copilot for fabric
在2025年2月份更新中,powerbi desktop里的copilot功能还新增了一个非常强大的功能:一键生成多个度量值,并直接加载到模型。 直接上示例展示: 打开DAX查询视图,在copilot窗格中直接输入想要生成多个度量值,…...
Pytest的夹具
1、pytest的前置后置夹具 fixture 有些内容是在每个用例执行之前都要运行操作:-- 用例前置 接口:购物车模块先登录 --登录结果 【token鉴权】 UI: 每次用例 打开浏览器 --driver 有些内容在每个用例之后都要运行操作:–用例后置 接口: 数据清除 UI:关闭浏览器 叫做用例的…...
两市总的净流出和净流入来分析情况
为了排查数据干扰,只从两市总的净流出和净流入来分析情况。 净流出才对应资金抽离:若净流入为负(即净流出),则意味着资金从股市中撤出,例如主动卖出的金额超过主动买入金额。净流入反映市场信心࿱…...
GitHub在push推送到远程仓库的时候显示Logon failed登录失败
具体问题描述 git.exe push --progress "origin" master:master Logon failed, use ctrlc to cancel basic credential prompt. remote: Support for password authentication was removed on August 13, 2021. 这是因为Git 推送失败的原因是 GitHub 已经不支持密码认…...
如何在SQL中高效使用聚合函数、日期函数和字符串函数:实用技巧与案例解析
文章目录 聚合函数group by子句的使用实战OJ日期函数字符串函数数学函数其它函数 聚合函数 函数说明COUNT([DISTINCT] expr)返回查询到的数据的 数量SUM([DISTINCT] expr)返回查询到的数据的 总和,不是数字没有意义AVG([DISTINCT] expr)返回查询到的数据的 平均值&…...
AutoGen :使用 Swarm 构建自治型多智能体团队
👉👉👉本人承接各类AI相关应用开发项目(包括但不限于大模型微调、RAG、AI智能体、NLP、机器学习算法、运筹优化算法、数据分析EDA等) !!!👉👉👉 有意愿请私信!!!AutoGen 的 AgentChat 模块提供了一种强大的方法来构建多智能体协作系统。 在之前的文章中,我们探讨了…...
RK3568平台设备树文件功能解析(鸿蒙系统篇)
鸿蒙设备树驱动修改时候发现目录下有很多的rk3568 的设备树,由于对这些设备树功能不太熟悉,所以索性就整理一下不同设备树的功能 rk3568-evb1-ddr4-v10.dts rk3568-evb4-lp3-v10.dts rk3568-evb6-ddr3-v10-rk628-rgb2hdmi.dts …...
k8s-coredns-CrashLoopBackOff 工作不正常
本文作者: slience_me 问题描述 # 问题描述 # rootk8s-node1:/home/slienceme# kubectl get pods --all-namespaces # NAMESPACE NAME READY STATUS RESTARTS AGE # kube-flannel kube-flannel-ds-66bcs …...
【Android性能】Systrace分析
1,分析工具 1,Systrace新UI网站 Perfetto UI 2,Systrace抓取 可通过android sdk中自带的systrace抓取,路径一般如下,..\AppData\Local\Android\Sdk\platform-tools, 另外需要安装python2.7,…...
Unity导出WebGL,无法显示中文
问题:中文无法显示 默认字体无法显示中文 在编辑器中设置了中文和英文的按钮,中文按钮无法显示 导出后无法显示中文 解决办法: 自己添加字体,导入项目,并引用 示例 下载一个字体文件,这里使用的阿里…...
oracle事务的组成
1)数据库事务由以下的部分组成: 一个或多个DML 语句 ; 一个 DDL(Data Definition Language – 数据定义语言) 语句; 一个 DCL(Data Control Language – 数据控制语言)语句; 2)事务的执行开始: 以第一个 DML 语句的执行作为开始 ,…...
【如何在OpenWebUI中使用FLUX绘画:基于硅基流动免费API的完整指南】
如何在OpenWebUI中使用FLUX绘画:基于硅基流动免费API的完整指南 注册并获取硅基流动秘钥OpenWebUI中使用函数配置自定义模型-提示词配置效果验证 ) FLUX绘画是一种强大的AI绘图工具,本文将详细介绍如何在OpenWebUI中集成并使用FLUX绘画功能,…...
QT 磁盘文件 教程04-创建目录、删除目录、遍历目录
【1】新建目录 bool CreateDir(QString name){QString fileName name ;QDir dir(fileName);if (dir.isEmpty()) {dir.mkdir(fileName);return true;}else{qDebug()<<"文件夹已存在";return false;} } 【2】删除目录 bool DeleteDir(QString fileName){if (…...
Event driven agentic document workflows 笔记 - 2
代理文档工作流(ADW)- 课程笔记 Agentic Document Workflows (ADW) 1. 课程目标 介绍 代理文档工作流(ADW) 背后的核心概念,包括: RAG(检索增强生成)代理工作流 探讨如何利用 事件…...
Facebook 如何影响元宇宙的发展趋势
Facebook 如何影响元宇宙的发展趋势 引言 元宇宙(Metaverse)这个概念,曾经只存在于科幻小说中,如今正逐渐成为现实。它是一个由多个 3D 虚拟世界组成的网络,用户可以在其中进行社交、游戏、工作等活动。Facebook&…...
1.5.7 掌握Scala内建控制结构 - 变量作用域
本次实战深入理解了Scala中变量作用域的概念,通过两个任务演示了作用域的基本规则。在任务1中,我们创建了一个名为ScopeDemo01的对象,展示了内部作用域能够访问外部作用域的变量。通过在if语句块中访问在外部定义的message变量,我…...
RAID磁盘阵列管理
一. 什么是RAID RAID是英文Redundant Array of Independent Disks的缩写,中文翻译过来就是“独立冗余磁盘阵列”。简单的说,RAID是一种把多块独立的硬盘(物理硬盘)按不同的方式组合起来形成一个硬盘组(逻辑硬盘&#…...
利用ffmpeg库实现音频AAC编解码
AAC(Advanced Audio Coding)是一种音频编码技术,出现于1997年,基于MPEG-2的音频编码技术。AAC具有高效的数据压缩能力和较高的音质,适用于各种音频应用场景。例如,在智能设备中,AAC技术被广泛…...
微博ip属地不发微博会不会变
随着社交媒体的普及,微博作为其中的佼佼者,一直备受关注。而且微博上线了显示用户IP属地的功能,这一功能旨在减少冒充热点事件当事人、恶意造谣、蹭流量等不良行为,确保传播内容的真实性和透明度。然而,这也引发了一些…...
appium之Toast元素识别
Appium之Toast元素识别教程与实例 一、Toast简介 Toast是Android系统中的轻量级消息提示框,以浮动形式短暂显示(通常2-3秒),无法被点击且不会获取焦点。常见于登录失败、操作提示等场景,如“密码错误”或“网络异常”。…...
「JavaScript深入」WebSocket:高效的双向实时通信技术
WebSocket WebSocket 的特点1. 全双工通信2. 持久连接3. 低延迟4. 二进制和文本支持5. 连接管理6. 二进制数据传输 WebSocket 协议详解1. 握手过程2. 数据帧结构 WebSocket 的实现服务器端实现(Node.js ws库)1. 基础服务器2. 广播功能实现3. 心跳机制客…...
