You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Puppeteer与startsWith()时结果不一致的问题排查

问题原因与解决办法

这是个很典型的Puppeteer上下文隔离问题,我来给你捋清楚:

核心原因:上下文隔离

Puppeteer的$$eval()方法里的回调函数是在浏览器的前端上下文环境中执行的,而你定义的root变量是在Node.js的后端上下文里的——这两个环境是完全隔离的,浏览器环境根本访问不到Node.js里的root变量!

所以当你在回调里写link.startsWith(root)时,root实际是undefined,自然过滤不出任何匹配的链接;而直接写字符串'https://tiempone.com'时,这个字符串是直接在浏览器上下文里解析的,能正常匹配到目标链接,所以结果符合预期。

解决办法:传递变量到浏览器上下文

要让浏览器上下文能访问到Node.js里的变量,你可以利用$$eval()的第三个(及以后)参数,把Node端的变量传递过去。修改后的代码如下:

const root = 'https://tiempone.com';
const browser = await puppeteer.launch({headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox']});
const page = await browser.newPage();
await page.goto(root, {waitUntil: 'networkidle0'});

// 将root作为额外参数传入$$eval,让浏览器上下文可以访问到
let urlsToVisit_1 = await page.$$eval(
  'a', 
  (links, root) => links.map(link => link.href).filter(link => link.startsWith(root)), 
  root // 这里是传递给回调的参数
);
let urlsToVisit_2 = await page.$$eval('a', links => links.map(link => link.href).filter(link => link.startsWith('https://tiempone.com')));

console.log(urlsToVisit_1); // 现在和urlsToVisit_2结果完全一致
console.log(urlsToVisit_2); // ['https://tiempone.com/', 'https://tiempone.com/projects', ..., 'https://tiempone.com/privacy']

简单来说,page.$$eval(selector, pageFunction[, ...args])里的...args就是专门用来把Node.js环境的变量序列化后传递给浏览器端的pageFunction的,只要是可序列化的变量(字符串、数字、普通对象等)都可以用这种方式传递。

内容的提问来源于stack exchange,提问作者Erik Martín Jordán

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 18:47:35