跳至内容
免费开始
返回博客

Nodriver Python 教程:隐身浏览器爬取——从第一个脚本到投入生产

Suciu Dan最后更新于 5 min read
Nodriver Python 教程:隐身浏览器爬取——从第一个脚本到投入生产
简而言之:Nodriver 是一个异步 Python 库,通过 Chrome DevTools Protocol 驱动 Chromium,无需 Selenium 或 chromedriver 二进制文件。当一个更接近真实 Chrome 会话的自托管隐身浏览器比 WebDriver 技术栈更合适时,请使用它;但要知道,它本身并不能消除 IP、TLS 或行为层面的风险。本教程从第一个脚本讲到容器化生产部署以及托管的 Browser API。

Nodriver 是一个异步 Python 库,它通过 Chrome DevTools 协议驱动 Chromium——无需 Selenium,也无需 chromedriver 二进制文件。 当自托管的隐身浏览器(其体验更接近真实的 Chrome 会话)比经典的 WebDriver 架构更胜一筹时,您就可以考虑使用它。本指南将从公共沙盒中一个可运行的爬虫开始,逐步过渡到容器化的生产环境,最后探讨在何种情况下,相同的流程更适合使用托管式浏览器 API。

关键要点

  • Nodriver 直接与 CDP 通信;它本身不会消除 IP、TLS 或行为风险。
  • 锁定版本。在 0.50.3 版本配合 Chrome 154(2026-10-06)时, select 返回 None , wait_for 抛出异常,并 xpath 因 DOM.enable 缺失。
  • 首选 uc.loop() 而非 asyncio.run 以实现干净关机; browser.stop() 是同步的。
  • 对于对隐蔽性要求较高的工作,建议在 Xvfb 环境下使用带图形界面的 Chrome:无头模式仍会向 HeadlessChrome 用户代理信息。
  • 生产环境是爬虫容易出错的地方:容器、受限并发、重试、退出 IP 检查、输出验证。
  • 将等待/操作映射到浏览器 API 参数(wait_for_css, wait_until, js_instructions, …),当你无法再依靠自托管时。

nodriver 的定义(及其非定义)

CDP 直接调用与 WebDriver 对比

经典 Selenium 路径:

Your script  →  WebDriver protocol  →  chromedriver  →  Chrome

Nodriver 路径:

Your script  →  Chrome DevTools Protocol (websockets)  →  Chrome

跳过驱动程序二进制文件可以消除 WebDriver 特有的自动化标记,并避免一类因版本不一致导致的故障。但这并不能使您的 IP 地址变为住宅 IP,也不能使您的 TLS 堆栈变得独特,更无法让您的点击时机像人类一样自然。

源自 undetected-chromedriver

Nodriver 是与 undetected-chromedriver 出自同一作者血统的异步、CDP 优先的继任者。其模式从“修补驱动程序”转变为“永远不使用驱动程序”。仅限 Chromium 家族浏览器;仅支持异步 API。

它针对哪些检测层

检测层

防御方关注的重点

nodriver 带来的变化(模型)

JS 环境

navigator.webdriver、Chrome 对象的特殊行为

与原生 WebDriver 相比,优化了默认的 JS 自动化资源占用(仍需针对每个目标进行验证)

协议/驱动程序

ChromeDriver 指纹

通过使用 CDP 规避 WebDriver

TLS / HTTP2

JA3 / ALPN / HTTP2 指纹

不替换浏览器的网络堆栈

IP / ASN / 地理位置

数据中心范围、信誉

无法解决;需要代理 / 住宅路由

行为特征

时间间隔、鼠标轨迹、滚动模式

不会为您模拟人类行为

无头信号

HeadlessChrome 用户代理、缺失的插件等

取决于运行模式;请参阅我们的“无头模式”章节

您的团队是否应该基于 nodriver 进行开发?(决策框)

于 2026-10-06 发布准备阶段核查:

  • 许可证:我们安装的 PyPI 包采用 AGPL-3.0 许可证。这对修改并运行该代码的面向网络的服务至关重要。此处不构成法律建议——若您基于分支版本发布 SaaS 服务,请咨询法律顾问并仔细阅读 AGPL 条款。
  • API 形式:仅支持异步;适用于 Chromium 家族浏览器。
  • 维护情况:本指南核查的最新 PyPI 版本为 0.50.3(2026-05-13)。在锁定一项涉及多年平台投入的决策前,请于发布当天重新核查其星标数、问题数量及提交记录。
  • 测试覆盖率/Alpha分类:PyPI仍显示“开发状态 :: 3 - Alpha”。请做好Chrome更新导致功能中断的准备。
  • 分支:若您需要不同的维护模式,可选用 Zendriver 及其他 CDP 分支——请参阅后文的工具对照表。

需要多浏览器支持(Firefox/WebKit)、同步 API,或适用于商业产品且无需进行 AGPL 分析的宽松许可?Nodriver 可能并非合适的选择。

安装与验证(固定版本)

python3 -m venv venv
source venv/bin/activate
pip install 'nodriver==0.50.3'

安装检查清单:

  1. Python ≥ 3.9。
  2. 本地已安装的 Chrome/Chromium(请通过 google-chrome --version).
  3. 运行时依赖项将自动拉取: websockets>=14 , mss, deprecated.
  4. 请勿将脚本命名为 nodriver.py (会与包名冲突)。
  5. 烟雾测试:打开一个公开页面并等待选择器(脚本如下)。

您的首个爬虫

本文的沙盒:quotes.toscrape.com——这是一个与许多竞争对手教程中使用的商店前端不同的演示目标。

# 01_first_scraper.py — verified 2026-10-06 on nodriver 0.50.3
import nodriver as uc

async def main():
    browser = None
    try:
        browser = await uc.start(headless=True)
        tab = await browser.get("https://quotes.toscrape.com/")
        await tab.select("div.quote", timeout=15)  # wait for state, not time
        quotes = await tab.select_all("div.quote")
        for q in quotes:
            text_el = await q.query_selector("span.text")
            author_el = await q.query_selector("small.author")
            print((text_el.text or "").strip(), "—", (author_el.text or "").strip())
    finally:
        if browser is not None:
            browser.stop()  # sync on 0.50.3 — do not await

if __name__ == "__main__":
    # Package README recommends uc.loop(); see event-loop notes below
    uc.loop().run_until_complete(main())

可靠地选择和提取

选择器方法决策表(0.50.3)

需求

方法

未命中时(0.50.3,2026-10-06)

何时使用

等待 + CSS

await tab.select(css, timeout=…)

返回 None (不会触发异常;文档字符串有误)

默认就绪等待

单次 CSS

await tab.query_selector(css)

返回 None

您已经知道 DOM 已就绪

必须明确失败的等待

await tab.wait_for(selector=…)

抛出 TimeoutError

在继续之前触发硬门

文本搜索

await tab.find(text, best_match=True)

重试后出现软失败

CSS不稳定的按钮/标签

节点过多

await tab.select_all(css)

通过重试导致类似空列表的行为

列表/卡片

XPath

await tab.xpath(…)

在 0.50.3 版 + Chrome 154 版中出现故障 — ProtocolException: 'DOM.enable' wasn't found

优先使用 CSS 选择器

文本和属性辅助函数

def attr_get(el, name: str):
    if el is None:
        return None
    attrs = el.attrs  # ContraDict in nodriver 0.50.3
    if attrs is None:
        return None
    try:
        return attrs.get(name)
    except Exception:
        try:
            return attrs[name]
        except Exception:
            return None

# Observed: element.text and element.text_all both return usable strings

0.50.3 版搭配 Chrome 154 时的 XPath 状态

在 Chrome 154 + nodriver 0.50.3(2026-10-06)环境下调用时失败 DOM.enable时出现故障。在未进行重新验证的情况下,请勿在此组合环境下发布依赖 XPath 的爬虫程序。

动态页面

等待状态,而非时间

等待选择器、文本或网络静默条件。已修复 sleep 仅用于罕见的可视化调试——不适用于最终版爬虫。建议使用 select / wait_for 而非 tab.sleep 。

支持导航后的分页

点击“下一页”后,旧的元素句柄可能会脱离。每次尝试时都应重新查询控件;等待 URL 变化或新的内容选择器。

# Pagination retry pattern for quotes.toscrape.com-style next links
async def click_next_with_retry(tab, max_attempts=3) -> bool:
    for _ in range(max_attempts):
        next_link = await tab.select("li.next > a", timeout=5)
        if next_link is None:
            return False
        before = tab.url
        try:
            await next_link.click()
        except Exception:
            continue
        for _ in range(20):
            await tab.sleep(0.25)
            await tab.select("div.quote", timeout=2)
            if tab.url != before:
                return True
        if tab.url != before:
            return True
    return False

页面 1→2→3 顺利切换;作者信息按预期更新。

带停止条件的无限滚动

对于没有“下一页”链接控件的页面,请滚动至满足停止条件为止:结束标记、计数达到平台期或达到最大轮次。

async def scroll_until_plateau(tab, max_rounds=20):
    history = []
    plateau = 0
    for round_i in range(1, max_rounds + 1):
        items = await tab.select_all("div.item")
        count = len(items)
        end = await tab.query_selector("#end-marker")
        history.append(count)
        if end is not None:
            return {"reason": "end_marker", "count": count}
        if len(history) >= 2 and history[-1] == history[-2]:
            plateau += 1
        else:
            plateau = 0
        if plateau >= 2:
            return {"reason": "count_plateau", "count": count}
        await tab.evaluate("window.scrollTo(0, document.body.scrollHeight)")
        await tab.sleep(0.4)
    return {"reason": "max_rounds", "count": history[-1] if history else 0}

在 end_marker 4轮后,在第40项处停止。

点击、标签页、iframe 及 evaluate(简短)

  • 新标签页/窗口: browser.get(url, new_tab=True) / new_window=True (包 API)。
  • tab.evaluate(expr) 用于滚动/DOM 检测——尽可能优先使用选择器。
  • Cookie:将 JAR 文件视为机密信息;在日志中进行屏蔽处理(安全提示,并非深入的 Cookie 教程)。
  • 屏幕截图: await tab.save_screenshot(...) 在我们的诊断测试中有效。

身份识别:用户代理、无头模式和 Xvfb

固定身份与轮换身份

确保用户代理(UA)与实际启动的 Chrome 构建版本一致。若随机轮换的身份信息与 Chrome/154 (或您运行的任何其他浏览器)的随机轮换,很容易被识破。建议每个工作进程配置文件使用一个稳定的桌面身份。

Chrome 154(2026-10-06)上的无头模式信号

仅针对公共诊断页面(bot.sannysoft.com; areyouheadless 两种模式均返回 502 错误):

模式

navigator.userAgent

navigator.webdriver

headless=True

包含 HeadlessChrome/154.0.0.0

False

headless=False 在 Xvfb 下

包含 Chrome/154.0.0.0 (无无头模式)

False

这些 154.0.0.0 这些字符串中的“build”是Chrome的用户代理简写形式,相对于完整的 154.0.8037.57 二进制版本而言并非笔误。Nodriver 可在 navigator.webdriver ,而无头模式仍会通过用户代理字符串进行自我标识。仅此一点就足以满足许多简单的检测需求。

在 Xvfb 环境下作为默认模式,适用于对隐蔽性要求较高的工作

在没有物理显示器的 Linux 服务器上:

# pattern
xvfb-run -a python your_scraper.py
# or export DISPLAY to a running Xvfb and start(headless=False)

内部沙箱和持续集成(CI)请使用无头模式。当目标系统能识别无头模式的用户代理字符串时,请使用带Xvfb的带头模式。

不泄露 IP 的代理

未认证与已认证代理的区别

切勿直接套用其他博客中提到的 Chrome 实验性功能设置。在通过代理自动突破登录验证墙之前,请先在您的 Chrome 版本上验证:浏览器的出口 IP 是否为代理 IP——而非您主机的 IP。

始终验证出口 IP

# Guard pattern — wire to your proxy stack; always assert exit IP before scraping
async def assert_exit_ip(tab, expected_subnet_prefix: str | None = None):
    tab2 = await tab.browser.get("https://httpbin.org/ip")  # or your IP echo
    await tab2.select("body", timeout=15)
    body = (await tab2.get_content()) if hasattr(tab2, "get_content") else None
    # parse JSON IP; compare to expected proxy IP; fail closed
    return body

若检测到的出口 IP 是您的数据中心主机,则任务应判定为失败。即使代理“看起来已配置妥当”,在生产环境中也应执行此检查。

住宅代理与地理路由

当问题在于 IP 声誉或国家关联性(而非 DOM 自动化)时,请通过住宅代理进行路由,或将浏览器操作转换为使用 country set。

在生产环境中运行 nodriver

大多数教程到此就结束了。而这正是爬虫失败的关键所在。

容器配置指南(概要)

# Outline only — adapt paths and package names for your base image
FROM python:3.13-slim-bookworm
RUN apt-get update && apt-get install -y --no-install-recommends \
    wget gnupg ca-certificates fonts-liberation xvfb \
    && install Google Chrome / Chromium per your distro docs \
    && useradd -m scraper
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
USER scraper
ENV DISPLAY=:99
CMD ["sh", "-c", "Xvfb :99 -screen 0 1920x1080x24 & python worker.py"]

注意事项:以非root用户身份运行;了解受限容器中Chrome沙箱标志;若要复用来之不易的Cookie,请将配置文件保存在可写卷上;并在日志中对这些Cookie进行脱敏处理。

并发模型

单元

隔离

典型用途

同一浏览器中的标签页

共享进程/Cookie/指纹

同一会话中的相关步骤

多个浏览器

隔离性更强,内存更多

并行任务

多个进程/容器

最强的隔离性

工作器集群

通过 asyncio.Semaphore (或队列工作者)。在您的硬件上,针对类似生产环境的页面,测量每个浏览器的内存占用情况。

重试、超时和崩溃恢复

  • 按导航设置超时,并设定 wait_for / select 配额。
  • 对错误进行分类:超时、空壳页面、验证页面、Chrome 崩溃。
  • 在反复出现协议错误后重启浏览器进程——而不仅仅是重启标签页。
  • 通过抖动退避机制限制重试次数。

可观测性

  • 指标:按主机统计的成功/阻塞/超时/空请求。
  • 将失败时的屏幕截图保存到对象存储中。
  • 日志屏蔽:代理用户名/密码、 Cookie 请求头、存储数据转储。

输出验证

浏览器中类似HTTP的成功响应并非可用的HTML。在将数据写入数据仓库之前,需检测挑战标题、空应用壳以及缺失的必选选择器。将此与您更广泛的爬虫栈中的验证思路相结合(避免被封锁)。

反机器人现实检查

范围(2026-10-06):仅限公开的指纹识别/诊断页面。不针对商业性的 Cloudflare 或 DataDome 目标(依据本文的编辑政策)。

目标

结果

bot.sannysoft.com

已加载;可用于用户代理(UA)与WebDriver嗅探结果的对比

arh.antoinevastel.com/bots/areyouheadless

502 网关错误 — 无法确定

Cloudflare / DataDome / Turnstile 的商业页面

本指南未涵盖

Tab.verify_cf 辅助工具

存在于 0.50.3 版本;视为可选功能,请在目标系统上进行验证

对于任何未附带带日期和明确测试范围的“nodriver 绕过 X”的声明,均应视为营销宣传。对于安全防护严密的测试目标,请另参阅如何绕过 Cloudflare 的产品指南。

选择您的工具(按约束条件划分的矩阵)

版本信息基于 2026-10-06 通过 PyPI 索引核查。隐身状态为定性评估,并非评分。

工具

语言

浏览器

同步/异步

许可证(PyPI 信号)

隐身状态

运维负担

nodriver 0.50.3

Python

Chromium 家族

异步

AGPL-3.0

CDP,不支持 WebDriver

您运行 Chrome 并显示

zendriver 0.17.1

Python

Chromium系列

异步

AGPL

nodriver 分支的衍生版本

类似

Playwright 1.63.0

许多

Chromium、Firefox、WebKit

两者

Apache-2.0(项目)

强大的自动化功能,更易于按原样检测

驱动程序管理更轻量

Patchright 1.63.0

Python

Chromium/Chrome 通道

两者皆可

请查阅《许可协议》

Playwright 修补版

类似于 Playwright

Camoufox 0.5.7

Python

Firefox(自定义)

两者

MIT (PyPI)

Firefox 指纹角度

浏览器二进制操作

SeleniumBase 4.55.1(CDP 模式)

Python

Chromium

两者皆是

MIT

CDP 模式选项

框架体积

托管浏览器 API

任意(HTTP)

托管

不适用

商业

由提供商运营

本地运维成本最低

根据以下约束条件进行选择:许可证、浏览器引擎、同步需求以及谁负责保障系统正常运行时间。

自建与采购:自托管的nodriver还是托管式浏览器

成本驱动因素

  • 云虚拟机上的显示器/Xvfb/GPU异常
  • 每个并发 Chrome 实例的内存和 CPU 资源
  • 住宅代理或移动代理
  • Chrome 升级及选择器失效所需的工程维护时间
  • 阻塞处理与值班
  • 截图存储与个人身份信息(PII)脱敏
  • AGPL合规性审查

当您需要长时间交互会话、自定义扩展程序或与内部网络紧密耦合时,请选择自托管方案。若希望将请求/响应服务水平协议(SLA)、地理位置限制及浏览器维护等事务从您的肩上卸下,请选择购买服务。

Nodriver → 浏览器 API 映射表

浏览器 API 是一个对 https://api.webscrapingapi.com/v1——而非实时CDP套接字(产品确认)。参数名称已于2026年10月6日在API参数中验证:

Nodriver 模式

浏览器 API 参数

等待 CSS(select / wait_for)

wait_for_css

生命周期就绪

wait_until (domcontentloaded, load, networkidle0, networkidle2)

额外延迟

wait_for (毫秒)

点击/滚动/输入序列

js_instructions

屏幕截图

screenshot=1 (+ screenshot_options)

字段提取

extract_rules

地理上下文

country

设备 / 视口

device, window_width, window_height

文档:GET请求、渲染JavaScript。

当 Scraper API ( render_js=1 )已足够时

render_js=1)已足够时

如果您仅需渲染后的 HTML 快照,且无需多步骤交互脚本,请从 Scraper API 和 JavaScript 渲染开始。当您需要在单次请求中执行有序操作、选择器等待、截图或提取规则时,请转用 Browser API。请参阅“Web 访问 API”部分中的选项对比。

故障排除(症状 → 原因 → 解决方法)

根据我们在 2026-10-06 复现的错误:

症状

可能原因

解决方法

select 返回 None 超时后

选择器错误或内容从未渲染

修正选择器;若需要强制失败,请使用 wait_for 如果需要强制失败

TimeoutError 来自 wait_for

预期结果 — 超出预算后未命中

延长等待时间或截屏

ProtocolException: 'DOM.enable' wasn't found

xpath 在我们的 Chrome 154 + 0.50.3 版本上

使用 CSS;升级后重新测试 XPath

用户代理包含 HeadlessChrome

headless=True

针对敏感目标,在 Xvfb 环境下运行

待办任务 / Event loop is closed 脚本执行后

asyncio.run shutdown 与 nodriver 监听器

优先选择 uc.loop();确保 browser.stop() 在 finally

“success”后的引用列表为空

导航过早 / 页面错误

在内容选择器上重新等待;验证计数

分页卡住

“下一页”链接处理过时

重新select 每次尝试时重新处理“下一页”控件

代理“看似正常”,但网站检测到本地IP

认证/代理配置错误

抓取前启用出口IP防护

负责任的使用

仅抓取符合条件的公开页面,遵守机器人协议/服务条款及相关法律,尽量减少个人数据收集,并确保凭证安全。请阅读《负责任的网络数据采集》。关于更广泛的无头浏览场景,请参阅《Python 无头浏览器》。

常见问题

什么是 nodriver?

这是一个异步 Python 库,无需 Selenium 或 chromedriver,即可通过 CDP 控制 Chromium。本指南使用的是 0.50.3 版本(2026-10-06 核查)。

nodriver 与 undetected-chromedriver 及 Selenium 有何区别?

Selenium 使用 WebDriver 配合驱动程序二进制文件。Undetected-chromedriver 对该路径进行了修补。而 nodriver 则跳过 WebDriver,直接通过 CDP 进行异步通信。

nodriver 是否会被检测到?

它会屏蔽部分自动化信号,但无法消除 IP、TLS、行为或无头用户代理(UA)泄露。在我们的测试中, navigator.webdriver 曾 False,但无头模式下 HeadlessChrome 。

nodriver 在无头模式下有效吗?

在我们的沙箱环境中,用于功能性抓取时可以。对于对隐身性要求较高的目标,根据我们测量的用户代理差异,建议优先使用带界面的模式 + Xvfb。

如何在不泄露 IP 的情况下,在 nodriver 中使用经过身份验证的代理?

请根据您的 Chrome 版本配置代理,并在任务开始前始终验证出口 IP。

nodriver 能绕过 Cloudflare 或 DataDome 吗?

请勿将诊断页面的结果泛化到商业爬虫产品中。如果您使用 verify_cf 0.50.3 版本,请在依赖该功能前先在您的目标站点上进行验证。

Nodriver、Playwright 与 Zendriver:我该选择哪一个?

请根据许可证、浏览器引擎、同步/异步需求以及运维责任方进行选择——参见上方的对比表。Playwright 在多引擎支持方面更胜一筹;nodriver/zendriver 基于 AGPL 许可证,专为 CDP 隐身模式进行了优化;若您不希望使用 Chrome 浏览器集群,托管式浏览器 API 则是更优选择。

如何在 Docker 或 Linux 服务器上运行 nodriver?

安装 Chrome,在 Xvfb 环境下以 headed 模式运行(或接受无头模式的权衡),使用非 root 用户,并限制工作进程数量。以 Dockerfile 大纲为起点,并在您的环境中验证镜像。

我可以并行运行多少个 nodriver 浏览器?

请根据您的硬件配置和目标页面进行测试。在未获得自身测试数据前,请勿轻信有关并发能力的声明。

nodriver 是否适合商业使用(许可)?

我们安装的软件包采用 AGPL-3.0 许可。在将其嵌入网络服务之前,请咨询法律顾问进行审核。本文不构成法律建议。

何时应使用托管浏览器 API 代替 nodriver?

当您希望在不运行 Chrome 的情况下使用 REST 等待/操作/地理位置功能时,或者当代理服务器和维护成本占主导地位时。将您的 nodriver 等待操作转换为 wait_for_css / js_instructions 并比较单次请求的差异。

下一步

选取一个您的 nodriver 脚本已处理的页面,并通过单个 Browser API 请求将其发送,使用 wait_for_css (以及 js_instructions 若需滚动或点击操作)。比较工程耗时、故障模式及输出格式。若涉及海量数据、地理定位或托管交付,请联系 WebScrapingAPI 团队。


关于作者

Suciu Dan, 联合创始人 @ WebScrapingAPI

Suciu Dan

联合创始人

Suciu Dan 是 WebScrapingAPI 的联合创始人,他撰写了关于 Python 网页抓取、Ruby 网页抓取以及代理基础设施的实用指南,这些指南专为开发者而设计。

如何在搜索结果页面(SERP)抓取工具中处理 Google /goto 重定向 URL 和 CAES 令牌
网络爬虫技术

如何在搜索结果页面(SERP)抓取工具中处理 Google /goto 重定向 URL 和 CAES 令牌

TL;DR: Google 搜索会在搜索结果页面(SERP)中的结果与目标页面之间插入一个不透明的重定向。href 属性中可能不会直接显示 URL,而是显示包含 CAES 令牌的 google.com/goto——或者较旧的 /url 包装形式。了解如何在生产环境的 SERP 抓取工具中,无需解密 CAES 即可对这些重定向进行分类、去重和解析。

Suciu Dan4 min read
阅读文章
cURL 中的 HTTP 响应头:每个标记、技巧和脚本配方
网络爬虫技术

cURL 中的 HTTP 响应头:每个标记、技巧和脚本配方

TL;DR: 简要说明:cURL 默认隐藏响应头信息。使用 -i 可以看到响应头和正文,使用 -I 可以看到 HEAD 请求只返回响应头,使用 -v 可以看到完整的请求/响应调试,使用 -D 可以将响应头保存到文件中。对于现代脚本,cURL 7.83+ 允许提取单个头信息,或使用 -w write-out 选项将所有头信息转存为 JSON 格式。

Suciu Dan3 min read
阅读文章
什么是无头浏览器?架构、用例和顶级工具
网络爬虫技术

什么是无头浏览器?架构、用例和顶级工具

TL;DR: 简要说明:无头浏览器是一种网络浏览器,运行时没有可见的图形界面,完全由代码或命令行指令控制。开发人员将无头浏览器用于自动测试、网络扫描、性能监控,并越来越多地用于支持人工智能代理。本指南将介绍无头浏览器的内部工作原理、何时选择无头浏览器而非普通浏览器,以及哪些框架值得你花时间研究。

Suciu Dan2 min read
阅读文章

开始构建

准备好扩展您的数据收集规模了吗?

加入2,000多家企业,使用WebScrapingAPI在无需任何基础设施开销的情况下,以企业级规模提取网络数据。