使用Playwright+Node.js爬取网站时$未定义错误的解决办法
解决Playwright中page.evaluate里「$ is not defined」的问题
问题根源
你在Node环境里require('jquery')拿到的$,和Playwright控制的浏览器上下文完全是两个独立的环境——page.evaluate()里的代码是跑在浏览器页面中的,根本访问不到Node端的$。偶尔成功的原因是目标网站本身可能也引入了jQuery:当页面的jQuery加载完成后,你的代码执行时就能拿到$;如果页面的jQuery加载慢了一步,你的代码先跑了,就会抛出「$ is not defined」的错误。
解决方案
方案1:用浏览器原生Fetch替代jQuery Ajax(推荐)
不需要依赖页面或外部的jQuery,直接用浏览器原生的Fetch API发起请求,兼容性和稳定性都更好:
const { test } = require('@playwright/test'); test('Running website parser...', async ({ page }) => { try { await page.goto('https://www.testwebsite.com'); const data = await page.evaluate(() => { return fetch('/Test/DailyDataAsync', { method: 'POST' }) .then(response => { if (!response.ok) throw new Error('请求失败'); return response.json(); // 根据实际返回格式调整,比如text() }); }); if (Object.keys(data).length) { console.log(data); } } catch (error) { console.log(error); } });
方案2:手动在浏览器上下文注入jQuery
如果一定要用jQuery Ajax,可以通过page.addScriptTag()把jQuery注入到浏览器页面中,确保执行ajax前jQuery已加载:
const { test } = require('@playwright/test'); test('Running website parser...', async ({ page }) => { try { await page.goto('https://www.testwebsite.com'); // 注入jQuery,用CDN或本地文件路径都可以 await page.addScriptTag({ url: 'https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js' }); const data = await page.evaluate(() => { return new Promise((resolve, reject) => { $.ajax({ url: '/Test/DailyDataAsync', type: 'POST', success: resolve, error: (xhr, status, error) => reject(error) }); }); }); if (Object.keys(data).length) { console.log(data); } } catch (error) { console.log(error); } });
额外说明
- 不要混淆Node环境和浏览器环境:Playwright的
page.evaluate()相当于在浏览器控制台里执行代码,只能访问页面中已有的变量或你注入的资源。 - 优先用原生API:Fetch现在已经是浏览器标配,不需要额外引入库,能避免依赖冲突或加载问题。
内容的提问来源于stack exchange,提问作者Lino Asmolo Jr
相关产品推荐
相关产品推荐

