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

PhantomJS 的替代方案:现在该用什么以及如何迁移

Sorin-Gabriel Marica最后更新于 7 min read
PhantomJS 的替代方案:现在该用什么以及如何迁移
简而言之:最佳的 PhantomJS 替代方案取决于您的旧脚本是做什么的,因为 PhantomJS 已于 2018 年 3 月暂停开发。大多数新项目请使用 Playwright;如果只需要 Chrome,Puppeteer 是迁移到 Node.js 最快捷的方式;如果您的测试已经运行在 WebDriver 网格上,请使用 Selenium。如果页面是服务端渲染的,一个 HTTP 客户端加一个解析器就够了。

最佳的 PhantomJS 替代方案取决于您原有的脚本功能。对于大多数新项目,建议使用 Playwright。 如果您使用 Node.js 且仅需 Chrome 浏览器,Puppeteer 是迁移路径最简便的选择。如果您的测试已经在 WebDriver 网格上运行,请切换到使用无头 Chrome 或 Firefox 的 Selenium。如果页面是服务器端渲染的,您可能根本不需要浏览器,仅需一个 HTTP 客户端和解析器即可。

你需要寻找替代方案,因为 PhantomJS 的开发已于 2018 年 3 月暂停,其 GitHub 仓库现已归档。本指南确认了相关日期,将每项旧任务与相应工具进行匹配,逐行映射了 PhantomJS 的调用到 Playwright 和 Puppeteer,并展示了如何移除构建中残留的、仍依赖 PhantomJS 的包。

关键要点

  • PhantomJS 已于 2018 年 3 月停止开发。其最后一个版本为 2.1.1(2016 年 1 月发布),且该代码库已于 2023 年 5 月转为只读状态。
  • CasperJS 和 Zombie.js 同样已被归档,因此无法作为替代方案。
  • Playwright 是最接近的通用替代方案,其 WebKit 引擎与 PhantomJS 的渲染效果最为接近。
  • 大多数 PhantomJS 调用都有直接对应的等效写法: page.open 变为 page.goto,而 page.render 变为 page.screenshot 或 page.pdf.
  • 如果数据已在初始 HTML 中,HTTP 客户端的速度会比任何浏览器都快。

PhantomJS 是否已停止维护?

是的。PhantomJS 的开发已于 2018 年 3 月暂停,此前其首席维护者于 2017 年卸任。最后一个稳定版本是 2016 年 1 月发布的 2.1.1,其 GitHub 仓库已于 2023 年 5 月归档为只读状态。 已知的文件读取漏洞 CVE-2019-17221 目前尚无修复版本。

PhantomJS 是一款基于 QtWebKit 构建、可通过 JavaScript 控制的可脚本化无头浏览器。Ariya Hidayat 于 2011 年发布该软件,多年来它一直是无显示环境下抓取 JavaScript 页面、截取屏幕截图、渲染 PDF 以及在持续集成(CI)中运行前端测试的默认方式。 随后,Chrome 推出了自己的无头模式,维护独立 WebKit 构建版本的必要性便逐渐消失。

日期

事件

来源

2011年1月

首次公开发布

项目历史(首次提交于2010年12月)

2016年1月23日

PhantomJS 2.1 发布。2.1.1 版本于 2016 年 1 月 24 日发布,并一直是该项目的最后一个稳定版本

phantomjs.org 发布版本,GitHub 标签

2017年4月

维护者Vitaly Slobodin卸任,此前不久Chrome 59版本中推出了无头Chrome

PhantomJS 邮件列表

2018年3月3日

问题 #15344 宣布“项目归档:暂停开发”

GitHub 问题

2019

CVE-2019-17221:通过 file:// URL page.open(),CVSS 3.1 评分 7.5(高),暂无修复方案

NVD

2023年5月30日

GitHub 仓库已归档(只读)

GitHub 代码库横幅

实际上,“已停用”意味着四点:不会发布任何安全修复程序,因此上述 CVE 仍处于未解决状态;不会推出新的 Web 平台功能,因为该引擎是 2016 年的 WebKit 构建版本,缺少近年来 CSS 和 JavaScript 的更新;npm 封装库已被弃用。 Selenium 已移除对 PhantomJS 的支持,因此基于它的测试套件无法升级。旧版二进制文件仍可启动并加载简单页面,但它们已无人维护,且在处理您无法控制的页面时存在安全隐患。

CasperJS 是否已停止维护?

是的。CasperJS 的 GitHub 仓库已于 2020 年 6 月归档,并声明该项目不再积极维护。其最后一个版本 1.1.4-2 发布于 2017 年 11 月。 CasperJS 是一个运行在 PhantomJS 或 SlimerJS 之上的脚本层,因此无法替代 PhantomJS。请将 CasperJS 脚本迁移至 Playwright 或 Puppeteer。

CasperJS 脚本由一系列导航步骤组成,因此易于移植。每个 then 步骤都变成了一个需要等待的调用,而 Playwright 的定位器会自行等待元素,因此大多数显式的等待操作不再需要:

CasperJS

Playwright (Node)

casper.start(url) / casper.thenOpen(url)

await page.goto(url)

casper.thenClick(sel)

await page.locator(sel).click()

casper.waitForSelector(sel, fn)

await page.locator(sel).waitFor()

casper.capture('shot.png')

await page.screenshot({ path: 'shot.png' })

Zombie.js 也已存档。其最后一个版本 6.1.4 发布于 2018 年 11 月。它从来都不是真正的浏览器:它是在 Node.js 内部模拟 DOM,因此无法渲染页面或截取屏幕截图。为其编写的测试用例最适合移植到 Playwright 的测试运行器中。

基于 Gecko 且与 PhantomJS 共享 API 的 SlimerJS 项目,已多年处于停滞状态。这三种工具都不适合用于新项目。

应该用什么来替代 PhantomJS?

请根据您的 PhantomJS 脚本原有的功能来选择。 若需进行数据抓取、截图和跨浏览器测试,请使用 Playwright;若需仅在 Node 环境下进行 Chrome 自动化操作及处理 PDF,请使用 Puppeteer;若您的测试已部署在 WebDriver 网格上,请使用 Selenium WebDriver。如果数据位于页面的初始 HTML 中,请跳过浏览器,直接使用 HTTP 客户端。

大多数团队使用 PhantomJS 完成的是以下几种任务之一。请在左侧列表中找到您团队的情况:

您的 PhantomJS 脚本曾执行哪些任务

现在应使用

原因

抓取由 JavaScript 渲染的页面

Playwright 或 Puppeteer

最新的 Chromium 内核、内置等待功能,以及 page.evaluate 工作原理相同

抓取服务器渲染的页面

HTTP 客户端加 HTML 解析器

无需浏览器,因此运行速度更快、成本更低

捕获的屏幕截图

Playwright 或 Puppeteer page.screenshot()

内置全屏和元素截图功能

生成的 PDF 文件

Puppeteer page.pdf() 或 Playwright page.pdf() (仅限Chromium)

“打印为 PDF”功能取代了 page.render('file.pdf')

在 Karma 中运行单元测试

短期内使用 Karma 的 Chrome 无头启动器,长期采用现代测试运行器

Karma 本身已被弃用

通过 GhostDriver 运行 Selenium 测试

Selenium 配合无头 Chrome 或 Firefox

Selenium 4 已移除对 PhantomJS 的支持

特别需要 WebKit 渲染引擎

Playwright WebKit

与 PhantomJS 的 QtWebKit 最接近的引擎

无需真实浏览器即可运行 Java 测试

HtmlUnit

一款受维护的、无图形界面的 Java 浏览器

没有单一工具能取代 PhantomJS。现代浏览器已具备真正的无头模式,且由一组库驱动。因此,针对每个脚本单独决策比全团队统一选用更有效。

哪些 PhantomJS 替代方案仍在维护中?

Playwright、Puppeteer 和 Selenium 均处于积极维护中,且几乎覆盖了 PhantomJS 的所有使用场景。 无头Chrome也可通过命令行独立运行。HtmlUnit专为无需真实浏览器的Java测试而持续维护。Splash虽仍面向Scrapy用户存在,但更新频率极低。CasperJS、Zombie.js以及PhantomJS本身均已归档。

工具

状态

协议

语言

引擎

最适合

Playwright

已启用

Chromium 平台使用 Chrome DevTools 协议;Firefox 和 WebKit 平台使用 Playwright 自有的协议

JavaScript/TypeScript、Python、Java、.NET

Chromium、Firefox、WebKit

大部分新工作、跨浏览器测试、WebKit兼容性

Puppeteer

活跃

Chrome DevTools 协议;适用于 Firefox 的 WebDriver BiDi

JavaScript/TypeScript

Chrome、Firefox

Node.jsChrome 自动化、PDF

Selenium WebDriver

Active

W3C WebDriver、WebDriver BiDi

Java、Python、C#、Ruby、JavaScript

所有主流浏览器

现有的测试套件、测试集群及多种编程语言

无界面版Chrome(CLI)

已启用

命令行参数;Chrome DevTools 协议

任意(shell)

Chrome

一次性截图、PDF、DOM 转储

HtmlUnit

已启用(5.6.0,2026年10月)

进程内

Java

自带引擎,不进行渲染

无需浏览器的Java测试

Splash

活动较少(最近一次代码推送为2024年8月)

HTTP API 配合 Lua 脚本

任意(通过HTTP)

基于 WebKit

现有的Scrapy配置

CasperJS、Zombie.js、PhantomJS

已存档

不适用

不适用

不适用

迁移

Playwright

Playwright 由微软维护,并通过一个 API 驱动 Chromium、Firefox 和 WebKit。其定位器会在元素被附加、可见且状态稳定后才进行操作,从而消除了 PhantomJS 脚本中大部分的定时代码。 每个浏览器上下文都是隔离的,拥有独立的 Cookie 和存储空间,因此您可以在一个浏览器进程中运行多个会话。它还附带了一个测试运行器,支持跟踪、失败时截图以及并行工作线程。

对于 PhantomJS 用户而言,WebKit 引擎是关键所在。如果您需要复现旧版 PhantomJS 的截图,或检查页面在类似 Safari 的引擎中的渲染效果,请运行 webkit 代替 chromium ,并保持脚本其余部分不变。

Python 团队可通过 pip install playwright 后跟 playwright install,而 Java 开发团队可以添加 com.microsoft.playwright Maven 包。我们的 Playwright 网页抓取指南涵盖了选择器、分页和数据导出,而 Playwright 文档中列出了下面用到的所有 API。

Puppeteer

Puppeteer 由 Chrome 团队维护,并以 Node.js 为核心。它是从 PhantomJS JavaScript 移植过来的最简便方案,因为异步页面对象和 page.evaluate 使用体验相似,且典型脚本能保留原有结构。它在截图和PDF生成方面表现出色,目前除了Chrome外,还能通过WebDriver BiDi驱动Firefox。

PhantomJS 与 Puppeteer 的核心区别在于引擎。Puppeteer 驱动的是最新版本的 Chrome,而 PhantomJS 运行的是 2016 年的 WebKit 构建版本。那些因现代 JavaScript 或 CSS 而在 PhantomJS 中无法正常显示的页面,在 Puppeteer 中通常无需特殊处理即可正确渲染。

如需了解选择器、导航和数据提取的完整指南,请阅读我们关于使用 Puppeteer 和 Node.js 进行数据抓取的指南。Puppeteer 文档涵盖了启动选项,包括 headless: 'shell' 下文所述的模式。

Selenium WebDriver

Selenium 实现了 W3C WebDriver 标准,并提供了针对 Java、Python、C#、Ruby 和 JavaScript 的官方绑定。它支持所有主流浏览器,可通过 Selenium Grid 实现横向扩展,并正在添加 WebDriver BiDi 以支持双向事件(如控制台日志和网络活动)。 与 Puppeteer 不同,其核心命令并不依赖于 Chrome DevTools 协议。对于曾使用 PhantomJS 的 Java 和 Ruby 开发团队,以及通过 GhostDriver 运行 PhantomJS 的测试套件而言,Selenium 无疑是最佳选择。

Python 绑定在 3.8.1 版本中已弃用 PhantomJS,并在 4.0 Alpha 6 版本中将其移除,因此 webdriver.PhantomJS() 该组件已不复存在。只需使用无头模式切换至 Chrome 或 Firefox,您的定位器和断言仍可正常工作。在 Java 中,这意味着 new ChromeOptions().addArguments("--headless=new").

如果您正在 Python 领域从零开始,请参阅我们关于在 Python 中构建 Selenium 爬虫的指南。Selenium 文档涵盖了驱动程序、等待操作以及 Grid 的配置。

独立的无头 Chrome

Chrome 自 2017 年的 Chrome 59 起便支持无头模式。从 Chrome 112 开始,无头模式与常规 Chrome 采用相同的浏览器内核,只是没有可见窗口。较早的独立实现仍以名为 chrome-headless-shell (自 Chrome 132 起),Puppeteer 将其作为 headless: 'shell'.

一次性任务无需依赖库。一条命令即可替代一段简短的 PhantomJS 脚本:

google-chrome --headless --screenshot=shot.png --window-size=1280,800 https://books.toscrape.com/
google-chrome --headless --print-to-pdf=page.pdf https://books.toscrape.com/
google-chrome --headless --dump-dom https://books.toscrape.com/ > page.html

相关参数已在 Chrome 无头模式文档中详细说明。Python 开发者可参考我们关于 Python 无头浏览器的概述来对比各项选项。

HtmlUnit 和 Splash

HtmlUnit 是一款面向 Java 程序的无 GUI 浏览器。它能运行 JavaScript 但不渲染像素,因此适合用于检查页面逻辑和表单的 Java 测试,而非截图。该项目仍在积极发布新版本,最新版本 5.6.0 发布于 2026 年 10 月。

Splash 是一个支持脚本的渲染服务,提供 HTTP API 和 Lua 脚本,主要通过 Scrapy-Splash 进行调用。对于已经使用它的团队来说,它仍然有效,但自 2024 年以来,其代码更新频率已大幅降低。对于新的爬取项目,Playwright 是更稳妥的选择。

如果您是出于将 Puppeteer 与其竞争对手进行比较的目的,而非为了替代 PhantomJS,请参阅我们关于 Puppeteer 替代方案的对比分析。

PhantomJS 命令在 Playwright 和 Puppeteer 中如何对应?

大多数 PhantomJS 调用在 Playwright 和 Puppeteer 中都有一一对应的等效命令,因此移植工作主要涉及重命名。 page.open 变为 page.goto, page.render 变为 page.screenshot 或 page.pdf, page.evaluate 保持原名,回调函数则变为 async/await。真正的变化在于等待机制。请用选择器或加载状态等待来替换固定的超时设置。

PhantomJS

Playwright (Node.js)

Puppeteer

require('webpage').create()

const page = await browser.newPage()

const page = await browser.newPage()

page.open(url, callback)

await page.goto(url)

await page.goto(url)

page.evaluate(fn)

await page.evaluate(fn, arg)

await page.evaluate(fn, ...args)

page.render('shot.png')

await page.screenshot({ path: 'shot.png', fullPage: true })

await page.screenshot({ path: 'shot.png', fullPage: true })

page.render('doc.pdf') 与 page.paperSize

await page.pdf({ path: 'doc.pdf', format: 'A4' }) (仅限Chromium)

await page.pdf({ path: 'doc.pdf', format: 'A4' })

page.viewportSize = { width, height }

await page.setViewportSize({ width, height })

await page.setViewport({ width, height })

page.settings.userAgent = ua

await browser.newContext({ userAgent: ua })

await page.setUserAgent({ userAgent: ua })

phantom.addCookie(cookie)

await context.addCookies([cookie])

await browser.setCookie(cookie)

page.onConsoleMessage = fn

page.on('console', (msg) => …)

page.on('console', (msg) => …)

page.onResourceRequested = fn

await page.route('**/*', (route) => …)

await page.setRequestInterception(true) 以及 page.on('request', …)

page.injectJs(file) / page.includeJs(url)

await page.addScriptTag({ path }) 或 ({ url })

await page.addScriptTag({ path }) 或 ({ url })

page.sendEvent('click', x, y)

await page.locator(sel).click()

await page.click(sel)

setTimeout 等待 / page.onLoadFinished

await page.locator(sel).waitFor() 或 await page.waitForLoadState()

await page.waitForSelector(sel)

--proxy=host:port 命令行参数

chromium.launch({ proxy: { server: 'http://host:port' } })

puppeteer.launch({ args: ['--proxy-server=host:port'] })

system.args

process.argv

process.argv

phantom.exit()

await browser.close()

await browser.close()

在最近的 Puppeteer 版本中,有两行内容发生了变化。Cookie 现在存储在浏览器或浏览器上下文中(browser.setCookie)中,因为页面级别的 Cookie 方法已被废弃。此外, setUserAgent 该方法现在接受一个选项对象。旧版教程中调用的 page.setCookie 的旧教程虽然仍可运行,但会输出弃用警告。

以前:一个 PhantomJS 脚本

该脚本会打开“Books to Scrape”练习商店,读取页面标题和前五个图书链接,保存屏幕截图,然后退出:

// legacy.js (PhantomJS 2.1.1): run with `phantomjs legacy.js`
var page = require('webpage').create();
var url = 'https://books.toscrape.com/';

page.viewportSize = { width: 1280, height: 800 };

page.open(url, function (status) {
  if (status !== 'success') {
    console.log('Failed to load ' + url);
    phantom.exit(1);
  }
  var data = page.evaluate(function () {
    var links = document.querySelectorAll('article.product_pod h3 a');
    return {
      title: document.title.trim(),
      books: Array.prototype.slice.call(links, 0, 5).map(function (a) {
        return { title: a.getAttribute('title'), href: a.href };
      })
    };
  });
  console.log(JSON.stringify(data, null, 2));
  page.render('books.png');
  phantom.exit();
});

之后:在 Playwright 中实现的相同脚本

使用以下命令安装 Playwright: npm install playwright 并 npx playwright install chromium,然后将端口作为 ES 模块运行:

// modern.mjs (Playwright for Node.js): run with `node modern.mjs`
import { chromium } from 'playwright';

const url = 'https://books.toscrape.com/';
const browser = await chromium.launch();
const page = await browser.newPage({ viewport: { width: 1280, height: 800 } });

try {
  await page.goto(url);
  await page.locator('article.product_pod').first().waitFor();

  const data = await page.evaluate(() => ({
    title: document.title.trim(),
    books: [...document.querySelectorAll('article.product_pod h3 a')]
      .slice(0, 5)
      .map((a) => ({ title: a.getAttribute('title'), href: a.href })),
  }));

  console.log(JSON.stringify(data, null, 2));
  await page.screenshot({ path: 'books.png', fullPage: true });
} finally {
  await browser.close();
}

两个脚本输出的数据完全一致:

{
  "title": "All products | Books to Scrape - Sandbox",
  "books": [
    {
      "title": "A Light in the Attic",
      "href": "https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html"
    },
    {
      "title": "Tipping the Velvet",
      "href": "https://books.toscrape.com/catalogue/tipping-the-velvet_999/index.html"
    },
    {
      "title": "Soumission",
      "href": "https://books.toscrape.com/catalogue/soumission_998/index.html"
    },
    {
      "title": "Sharp Objects",
      "href": "https://books.toscrape.com/catalogue/sharp-objects_997/index.html"
    },
    {
      "title": "Sapiens: A Brief History of Humankind",
      "href": "https://books.toscrape.com/catalogue/sapiens-a-brief-history-of-humankind_996/index.html"
    }
  ]
}

结构几乎没有变化。回调函数变成了顶级 await, try/finally 取代了分散的 phantom.exit() 调用,从而确保浏览器始终能关闭;同时,对商品卡片显式等待的处理,取代了寄希望于 page.open “触发得足够晚”的侥幸心理。你传递给 page.evaluate 仍会在页面内部运行,因此你的 DOM 代码可以原样迁移,并且可以省去诸如 Array.prototype.slice.call.

若要改用 Puppeteer,请导入 puppeteer,调用 puppeteer.launch(),使用 page.setViewport(),并将定位器等待替换为 page.waitForSelector('article.product_pod')。其余部分保持不变。

如何逐步迁移 PhantomJS 脚本?

先梳理每个脚本的功能,然后针对每个任务选择相应的替代方案。安装 Playwright 或 Puppeteer,并使用映射表移植调用。将固定延迟替换为选择器等待,并将输出结果与旧的截图或数据进行对比。 最后,从依赖项、CI 镜像和 Dockerfile 中移除 PhantomJS 二进制文件和封装包。

  1. 清点。在代码库中搜索 phantomjs, require('webpage'), casper, GhostDriver,以及 karma-phantomjs-launcher。同时检查 CI 配置和 Dockerfile,因为 PhantomJS 通常隐藏在构建步骤中,而非应用程序代码中。
  2. 按任务对每个脚本进行分类。请参考上文的快速选择表。即使在同一个仓库中,截图任务和 Selenium 测试套件也需要不同的替代方案。
  3. 安装替代方案。Playwright 会通过 npx playwright install,因此 CI 需要该步骤或官方 Docker 镜像。Python 团队使用 pip install playwright 和 playwright install 。
  4. 移植调用。参照映射表进行操作。回调函数将变为 async/await,而事件处理程序的属性(如 page.onConsoleMessage 则变为 page.on(...) 监听器。
  5. 修复等待操作。这是迁移后最常见的差异来源。替换所有 setTimeout 和 onLoadFinished 技巧,替换为对您实际需要的元素或加载状态的等待。
  6. 比较输出结果。将 HTML、提取的数据或截图与 PhantomJS 运行结果进行差异对比。预计会出现一些渲染差异,因为新引擎支持 2016 版 WebKit 未支持的字体、布局和 CSS。
  7. 更新 CI 和容器。安装新浏览器所需的系统库,并移除 PhantomJS 二进制文件以及 OPENSSL_CONF 或 fontconfig 变通方案。
  8. 删除残留文件。移除旧的软件包和启动器,具体方法将在下一节中介绍。

有什么可以替代 karma-phantomjs-launcher、phantomjs-prebuilt 和 GhostDriver?

用 Karma 的 Chrome 无头启动器替换 karma-phantomjs-launcher,随后计划迁移出 Karma(该框架本身已被废弃)。 移除 phantomjs-prebuilt(npm 已将其标记为弃用),并将相关脚本迁移至 Playwright 或 Puppeteer。用 Selenium 的 Chrome 或 Firefox 驱动程序(无头模式)替换 GhostDriver 会话,因为 Selenium 4 已移除了 PhantomJS。

这些残留组件通常是 PhantomJS 存活最久的地方,因为它们存在于测试和浏览器自动化工具中,在构建失败之前,通常无人问津。

Karma。karma-phantomjs-launcher 仓库在 2017 年最后一次活动后已被归档。快速解决方法是安装 karma-chrome-launcher 并设置 browsers: ['ChromeHeadless'] 在 karma.conf.js。这样虽能保持测试套件通过,但 Karma 才是更大的问题。Karma 的弃用通知指出,它不再接受新功能或常规错误修复。Angular 已将 Jest 和 Web Test Runner 作为迁移路径,二者均适用于此前在 PhantomJS 中运行的单元测试。

npm 包。 phantomjs-prebuilt (最新版本 2.1.16)在 npm 上已被标记为“此包现已弃用”,而较旧的 phantomjs 版本则指向该包。两者均会下载已不再维护的 2.1.1 二进制文件。请使用 npm uninstall phantomjs-prebuilt phantomjs,随后检查您的锁定文件,因为其他开发依赖项有时会引入它们。

Selenium 和 GhostDriver。 DesiredCapabilities.PHANTOMJS 和 webdriver.PhantomJS() 已从 Selenium 4 中移除。在 Python 中,替换只需三行代码:

from selenium import webdriver

options = webdriver.ChromeOptions()
options.add_argument("--headless=new")
driver = webdriver.Chrome(options=options)

Selenium Manager 会查找或下载匹配的驱动程序,因此您无需再单独提供 GhostDriver 二进制文件。Firefox 的处理方式与此相同,使用 FirefoxOptions 和 -headless 参数时,Firefox 也是如此。

Docker 镜像。请移除任何 apt-get install phantomjs 或全局安装的 PhantomJS。请使用官方的 Playwright 镜像,或遵循 Puppeteer 的指导,为容器中 Chrome 所需的系统库进行配置。

你真的需要无头浏览器吗?

通常不需要。许多 PhantomJS 爬虫是在渲染似乎更安全的时候编写的,但如果数据已经包含在页面的初始 HTML 中或 JSON 接口中,那么使用 HTTP 客户端加解析器会更快、更简单。请先检查页面源代码,仅当内容在 JavaScript 运行后才出现时才使用浏览器。

快速检查只需一分钟:

  1. 打开页面并查看其源代码,而不是检查 DOM。
  2. 在源代码中搜索你要提取的值,例如价格或产品名称。
  3. 如果未找到,请打开浏览器开发者工具中的“网络”标签页,查找返回 JSON 的 XHR 或 fetch 请求。

如果步骤 2 找到了该值,通过一个简单的 HTTP 请求和解析器即可获取,所需时间和内存仅为浏览器的一小部分。如果步骤 3 找到了 JSON 接口,直接调用它并跳过 HTML 解析。我们的 Cheerio 与 Puppeteer 对比测试在 Node.js 中并排展示了这两种方法。

将浏览器保留给确实需要它的任务:点击流程、登录、无限滚动、截图、PDF 处理以及视觉测试。

何时应停止自行运行浏览器?

当浏览器的维护成本超过脚本带来的价值时,就该停止自行托管。常见的迹象包括:大规模运行时的崩溃和内存泄漏、持续集成(CI)中的浏览器版本不一致、请求被阻塞,以及需要从多个国家和不同设备上检查页面。托管式 API 会运行浏览器,并通过纯 HTTP 请求返回 HTML、数据或截图。

运行一个无头浏览器很简单,但运行数百个则是另一回事。您需要管理并发限制、清理永不退出的 Chrome 进程、确保开发者笔记本电脑和 CI 环境中的浏览器版本保持同步,以及处理那些屏蔽数据中心流量的网站。如果您需要以其他国家/地区访客的视角查看页面,还需在该国/地区部署基础设施。

WebScrapingAPI 的浏览器 API 可将这些工作从您的服务器上卸载下来。您只需发送一个包含等待条件的 URL,例如 wait_until 或 wait_for_css,并包含页面操作(如点击、滚动、输入、选择和提交)。它将返回渲染后的 HTML、JSON 格式的 DOM、提取的字段或 base64 编码的截图。这是一个不涉及实时浏览器会话的请求-响应式 REST 接口,因此无需将其与 Puppeteer 或 Playwright 结合使用。 您只需在请求中描述操作步骤,即可获得结果。

对于 PhantomJS 通常处理的截图和 QA 任务,我们的跨市场和设备网站测试解决方案会按国家、设备和视口检查公开页面,并保留截图作为证据。

若您仅需渲染后的 HTML,请对比各类网页访问 API,以找到最简便的解决方案。

FAQ

PhantomJS 现在使用还安全吗?

对于不可信的页面,则不安全。自 2018 年暂停开发以来,PhantomJS 尚未收到任何安全修复,而 CVE-2019-17221 漏洞会使页面能够通过 page.open() ,且目前尚无修复版本。若您必须短期保留该工具,请仅在迁移期间,于隔离容器中对您控制的页面进行测试。

我还能从 npm 安装 PhantomJS 吗?

可以,但不建议这样做。该 phantomjs-prebuilt 该包在 npm 上已被标记为弃用,其二进制文件是已停止维护的 2.1.1 版本。新项目应改用 Playwright 或 Puppeteer。这两者都会下载最新的浏览器构建版本,且拥有活跃的维护者和完善的文档。

在替代 PhantomJS 方面,Playwright 和 Puppeteer 哪个更好?

Playwright 适合大多数团队。它支持 Chromium、Firefox 和 WebKit,提供 Python、Java 和 .NET 绑定,并能对元素进行自动等待。Puppeteer 则非常适合仅需 Chrome 的 Node 项目,或用于 PDF 生成。由于 page.evaluate 其工作原理相同。

Selenium 是否仍支持 PhantomJS?

不支持。Selenium 在 3.8.1 版本中已弃用 PhantomJS,并在 Selenium 4 中将其移除,因此 webdriver.PhantomJS() PhantomJS 和 GhostDriver 会话均已无法使用。请将相关测试切换至 Chrome 或启用无头模式的 Firefox。您的 WebDriver 定位器和断言大多保持不变,因此移植工作通常非常简单。

在 Karma 中,什么取代了 PhantomJS?

Karma 的 Chrome 无头启动器通常可直接替代 karma-phantomjs-launcher。不过,Karma 本身现已弃用。若要寻求长期解决方案,请将单元测试迁移至受维护的运行器,例如 Jest 或 Web Test Runner——Angular 已将其作为迁移路径提供。

哪种 PhantomJS 替代方案使用 WebKit?

Playwright。它除了提供 Chromium 和 Firefox 版本外,还附带一个 WebKit 构建版本,这使其渲染效果最接近 PhantomJS 的 QtWebKit 引擎。当需要复现旧版 PhantomJS 的截图或测试类似 Safari 的渲染效果时,请使用它。对于其他所有情况,Chromium 通常是默认选择。

应该选择哪种 PhantomJS 替代方案?

根据任务选择。大多数数据抓取、截图和跨浏览器测试使用 Playwright;Node.js 下的 Chrome 自动化和 PDF 处理使用 Puppeteer;而任何语言的现有 WebDriver 测试套件则使用 Selenium。 在移植爬虫程序之前,请先检查数据是否已包含在 HTML 中,因为“最快的浏览器就是你没运行的那个”。随后删除 PhantomJS 的二进制文件、封装程序和启动器,以确保没有任何组件将旧引擎重新引入你的构建中。

跳过浏览器维护

无需运行浏览器即可渲染 JavaScript 页面。向 Scraper API 发送 URL,即可获取渲染后的 HTML。免费提供 5,000 次请求。JavaScript 渲染和地理定位无需额外消耗积分,且失败的请求不会计费。

探索 Scraper API

关于作者

Sorin-Gabriel Marica, 全栈开发工程师 @ WebScrapingAPI

Sorin-Gabriel Marica

全栈开发工程师

索林·马里卡(Sorin Marica)是 WebScrapingAPI 的全栈及 DevOps 工程师,负责开发产品功能并维护确保平台平稳运行的基础设施。

开始构建

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

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