使用Playwright与JS Path获取网站数据无响应的问题排查
问题
我尝试使用JavaScript和Playwright库获取在线赌场游戏的结果,已正常完成登录并跳转至游戏指定页面。在控制台中通过JS Path检查结果元素可正常获取数据,但将该JS Path复制到代码中运行时却无响应。以下是我用于获取结果的代码:
import {firefox, webkit, chromium} from 'playwright' (async () => { const browser = await firefox.launch({ headless: false }) const page = await browser.newPage() await page.goto('https://www.playpix.com/'); await page.goto('https://www.playpix.com/pb/'); await page.waitForLoadState('networkidle'); await page.getByRole('button', { name: 'Aceitar' }).click(); await page.getByRole('button', { name: 'Entrar' }).click(); await page.getByLabel('Email / Usuário').click(); await page.getByLabel('Email / Usuário').fill('mrooc@me.com'); await page.getByLabel('Email / Usuário').press('Tab'); await page.getByLabel('Senha').click(); await page.getByLabel('Senha').fill('thepassword'); await page.locator('form').getByRole('button', { name: 'Entrar' }).click(); await page.waitForLoadState('networkidle'); await page.waitForTimeout(4000) await page.goto('https://www.playpix.com/pb/?openGames=217032-real&gameNames=Football%20Studio'); await page.waitForTimeout(20000) while (true) { // Wait for the element to be visible var result = document.querySelector("#root > div > div.app--2c5f6 > div > div.content--82383 > div.footerWrapper--3a742 > div > div.footer--0ff51.right--c3d03 > div > div > div > div:nth-child(1) > svg > g > text"); // Print the text content console.log(result.textContent()); } })();
我使用while循环尝试获取每隔约30秒更新一次的结果,请问我遗漏了什么?
解决方案
- DOM访问方式错误:直接在Node.js代码中调用
document.querySelector无效,这是浏览器端API,Playwright的Node.js环境无法直接访问浏览器DOM。必须通过page.evaluate()将代码注入浏览器上下文执行,或者使用Playwright官方定位器API(如page.locator())。 - 选择器过于脆弱:长层级选择器依赖页面DOM结构和类名,一旦页面更新(比如类名变更)就会失效。建议改用更稳定的定位方式,比如基于元素的唯一属性、文本内容,或者相对父元素定位。
- 无限循环无合理等待:
while(true)会持续占用CPU,且未处理元素更新逻辑。应设置匹配结果更新频率的等待间隔,或监听元素内容变化,避免无效轮询。
修改后的示例代码(使用page.evaluate):
import { firefox } from 'playwright'; (async () => { const browser = await firefox.launch({ headless: false }); const page = await browser.newPage(); // 登录流程保持不变 await page.goto('https://www.playpix.com/'); await page.goto('https://www.playpix.com/pb/'); await page.waitForLoadState('networkidle'); await page.getByRole('button', { name: 'Aceitar' }).click(); await page.getByRole('button', { name: 'Entrar' }).click(); await page.getByLabel('Email / Usuário').fill('mrooc@me.com'); await page.getByLabel('Senha').fill('thepassword'); await page.locator('form').getByRole('button', { name: 'Entrar' }).click(); await page.waitForLoadState('networkidle'); await page.waitForTimeout(4000); await page.goto('https://www.playpix.com/pb/?openGames=217032-real&gameNames=Football%20Studio'); await page.waitForLoadState('networkidle'); // 等待目标元素加载完成,替代固定超时 await page.waitForSelector('#root .footer--0ff51.right--c3d03 svg g text'); let lastResult = ''; while (true) { try { // 在浏览器上下文执行DOM查询 const currentResult = await page.evaluate(() => { const element = document.querySelector('#root .footer--0ff51.right--c3d03 svg g text'); return element ? element.textContent.trim() : null; }); // 仅当结果更新时打印 if (currentResult && currentResult !== lastResult) { console.log('最新结果:', currentResult); lastResult = currentResult; } } catch (err) { console.error('获取结果失败:', err.message); } // 匹配结果更新频率,等待30秒后再次检查 await page.waitForTimeout(30000); } })();
更推荐的Playwright定位器API写法:
// 替换原循环部分 const resultLocator = page.locator('#root .footer--0ff51.right--c3d03 svg g text'); await resultLocator.waitFor(); let lastResult = ''; while (true) { try { const currentResult = await resultLocator.textContent(); const trimmedResult = currentResult?.trim() || null; if (trimmedResult && trimmedResult !== lastResult) { console.log('最新结果:', trimmedResult); lastResult = trimmedResult; } } catch (err) { console.error('获取结果失败:', err.message); } await page.waitForTimeout(30000); }
内容的提问来源于stack exchange,提问作者Marco Almeida
相关产品推荐
相关产品推荐

