使用Playwright的page.on捕获数据时开头内容被截断的问题
解决Playwright捕获响应数据开头截断的问题
针对你遇到的响应数据开头固定位置截断的问题,结合谷歌地图接口特性和你的代码,给出以下排查方向与修复方案:
1. 处理谷歌接口的防XSS前缀
谷歌地图listentitiesreviews接口返回的是JSONP格式,开头会带有固定的防XSS前缀 )]}'\n,很多时候会被误认为是数据截断,实际是接口的标准格式。你可以先打印捕获内容的开头确认:
console.log(jsonData.slice(0, 10)); // 查看开头字符
如果确实存在该前缀,移除后再保存即可:
var jsonData = await ResponseData.text(); // 移除谷歌防XSS前缀 const cleanedData = jsonData.replace(/^\)]}'\n/, ''); saveData(cleanedData);
2. 等待响应完全接收后读取
虽然Playwright的text()方法理论上会等待响应完成,但保险起见,可以先等待响应进入finished状态,确保数据完整:
page.on("response", async (ResponseData) => { if (ResponseData.url().includes("https://www.google.com/maps/preview/review/listentitiesreviews?")) { console.log(ResponseData.url()); await ResponseData.finished(); // 等待响应完全结束 const jsonData = await ResponseData.text(); const cleanedData = jsonData.replace(/^\)]}'\n/, ''); saveData(cleanedData); } });
3. 避免异步写入的覆盖问题
你的saveData使用fs.writeFile是覆盖写入,如果同一个接口有多次请求(比如加载更多评论的二次请求),后续内容会覆盖之前的,导致开头缺失。可以改成两种方式:
方案A:追加写入
修改saveData函数:
function saveData(data) { fs.appendFile("data.json", data + "\n", "utf8", function (err) { if (err) { return console.log(err); } console.log("数据已追加到文件."); }); }
方案B:收集所有数据后一次性保存
async function run() { const browser = await chromium.launch({ headless: false }); const context = await browser.newContext(); const page = await context.newPage(); const allReviewsData = []; // 收集所有响应数据 await page.goto("https://www.google.com/maps/place/Hwy.+49+Sporting+Goods/@35.4973143,-80.2115411,15z/data=!4m8!3m7!1s0x885478b921983013:0x319ffde9405d2504!8m2!3d35.497264!4d-80.202698!9m1!1b1!16s%2Fg%2F1tkkvl5r?entry=ttu"); page.on("response", async (ResponseData) => { if (ResponseData.url().includes("https://www.google.com/maps/preview/review/listentitiesreviews?")) { console.log(ResponseData.url()); await ResponseData.finished(); const jsonData = await ResponseData.text(); const cleanedData = jsonData.replace(/^\)]}'\n/, ''); allReviewsData.push(cleanedData); } }); await page.waitForTimeout(8000); // 延长等待时间确保请求完成 // 一次性保存所有数据 fs.writeFile("data.json", allReviewsData.join("\n"), "utf8", (err) => { if (err) console.log(err); else console.log("所有数据已保存."); }); await context.close(); await browser.close(); }
4. 优化等待逻辑
固定5秒超时可能不足以让所有请求完成,建议延长超时时间,或者改用元素等待替代固定超时:
// 等待评论区元素加载完成,替代固定超时 await page.waitForSelector('[data-review-id]', { timeout: 10000 });
内容的提问来源于stack exchange,提问作者TboneSteakNeggs
相关产品推荐
相关产品推荐

