初步折腾 Playwright,被 AI 带偏

2025-06-17

来我司搞前端开发,什么奇奇怪怪的东西和需求都要做。这次需要做一个使用服务端完成渲染 SVG 智能图形(不知道这是什么?请看 智能图形,正式发布!)的需求,只有两套方案,一个是改造原程序需要花时间,另外一个就是无头浏览器。在 AI 的建议下尝试了无头浏览器方案 Playwright,类似于 Puppeteer,模拟正常用户操作但没有任何用户界面。

我让 AI 来实现我的需求,在页面上注入脚本,执行一段 window.postMessage 代码,之后原来的页面应用将会请求数据,请求完成后开始渲染,渲染成功后页面将会出现某个 DOM 元素,最后再次执行一段 window.postMessage 代码,让应用生成对应 SVG 图的 Base64 版本数据,返回到服务端侧。

const browser = await playwright.chromium.launch({ headless: false });
const context = await browser.newContext();

const finalDataPromise = new Promise(async (resolve, reject) => {
  // 服务端接收数据,页面应用发送过来
  await context.exposeFunction("onGraphicData", (data) => {
    console.log("onGraphicData", data);
  });

  // 这段代码不起作用,浏览器啥都没输出
  await context.addInitScript(() => {
    console.log("Inited");

    window.addEventListener("message", (event) => {
      // requestImageData 接收到后会发送另一条消息
      if (event.data && event.data.type) {
        window.onGraphicData(event.data);
      }
    });
  });
});

const page = await context.newPage();
await page.goto("http://localhost:5173", { waitUntil: "domcontentloaded" });

// 发送初始化信息
await page.evaluate((payload) => {
  window.postMessage(payload, "*");
}, graphicInitPayload);

// 等待图形加载完成
await page.waitForSelector(".editor-controls", { timeout: 30000 });

// 请求图片数据
await page.evaluate(() => {
  window.postMessage({ type: "requestImageData" }, "*");
});

const graphicData = await finalDataPromise;
console.log("Graphic data received.");

上述代码是 AI 生成的(我做了简化,可能实际上无法直接运行)但是它自带 Bug,你发现了吗?AI 写的东西,果然还是仅供参考,完全没接触过的东西直接让它写,还是特别容易踩坑

这段代码执行不成功,其实是 context.addInitScript 这里的代码根本就没执行,没打印出 Inited。它的执行时机应该在页面加载出来之前,没细看过 文档 直接问 AI(这里我看在浏览器的控制台并没有显示出来,可能是什么原因),它居然认为是前端页面执行了 console.clear,而不是它没有被执行。

当然实际上上面的代码还能做减法,例如 requestImageData 之后,直接让页面应用调用 onGraphicData 就可以了。接下来就看如何实现 Base64 图片内容的转存,当然这已经不属于 Demo 的范畴,如果他们确认要这么干用无头浏览器的方案,就让后端去具体实现吧!

中雨 一般
概览页 时间轴
奇趣音乐盒 技术源于 Kico Player
Emmm,这里是歌词君