如何将 puppeteer-core 与电子一起使用?

pou*_*uya 8 javascript typescript electron puppeteer

我从另一个 Stackoverflow 问题中得到了这段代码:

import electron from "electron";
import puppeteer from "puppeteer-core";

const delay = (ms: number) =>
  new Promise(resolve => {
    setTimeout(() => {
      resolve();
    }, ms);
  });

(async () => {
  try {
    const app = await puppeteer.launch({
      executablePath: electron,
      args: ["."],
      headless: false,
    });
    const pages = await app.pages();
    const [page] = pages;

    await page.setViewport({ width: 1200, height: 700 });
    await delay(5000);
    const image = await page.screenshot();
    console.log(image);
    await page.close();
    await delay(2000);
    await app.close();
  } catch (error) {
    console.error(error);
  }
})();
Run Code Online (Sandbox Code Playgroud)

Typescript 编译器抱怨方法选项对象的executablePath属性,launch因为它需要是 typestring而不是Electron。那么如何将电子铬可执行路径传递给 puppeteer 呢?

Md.*_*her 8

如果没有一些变通方法和标志更改,则不能直接将电子可执行文件与 Puppeteer 一起使用。他们在 API 上有很多不同之处。特别是电子没有所有的chrome.* API,这是Chrome浏览器正常工作所需的,许多标志仍然没有适当的替代品,例如无头标志

您将在下面看到两种方法。但是你需要确定两点,

  • 在启动应用程序之前,请确保 puppeteer 已连接。
  • 确保为在 Electron 中运行的 Chrome 版本获得正确的 puppeteer 或 puppeteer-core 版本!

puppeteer-in-electron

有很多解决方法,但最近有一个puppeteer-in-electron包,它允许您使用电子在电子应用程序中运行 puppeteer。

首先,安装依赖项,

npm install puppeteer-in-electron puppeteer-core electron
Run Code Online (Sandbox Code Playgroud)

然后运行它。

import {BrowserWindow, app} from "electron";
import pie from "puppeteer-in-electron";
import puppeteer from "puppeteer-core";

const main = async () => {
  const browser = await pie.connect(app, puppeteer);

  const window = new BrowserWindow();
  const url = "https://example.com/";
  await window.loadURL(url);

  const page = await pie.getPage(browser, window);
  console.log(page.url());
  window.destroy();
};

main();
Run Code Online (Sandbox Code Playgroud)

获取调试端口并连接到它

另一种方法是获取电子应用程序的远程调试端口并连接到它。此解决方案由trusktr 在电子论坛上共享。

import {app, BrowserWindow, ...} from "electron"
import fetch from 'node-fetch'

import * as puppeteer from 'puppeteer'

app.commandLine.appendSwitch('remote-debugging-port', '8315')

async function test() {
    const response = await fetch(`http://localhost:8315/json/versions/list?t=${Math.random()}`)
    const debugEndpoints = await response.json()

    let webSocketDebuggerUrl = debugEndpoints['webSocketDebuggerUrl ']

    const browser = await puppeteer.connect({
        browserWSEndpoint: webSocketDebuggerUrl
    })

    // use puppeteer APIs now!
}

// ... make your window, etc, the usual, and then: ...

  // wait for the window to open/load, then connect Puppeteer to it:
  mainWindow.webContents.on("did-finish-load", () => { 
    test()
  })
Run Code Online (Sandbox Code Playgroud)

上述两种解决方案都使用webSocketDebuggerUrl来解决该问题。

额外的

添加此注释是因为大多数人使用电子来捆绑应用程序。

如果您想构建 puppeteer-core 和 puppeteer-in-electron,您需要使用hazardouselectron-builder确保get-port-cli工作正常。

在 main.js 之上添加危险

// main.js
require ('hazardous');
Run Code Online (Sandbox Code Playgroud)

确保 get-port-cli 脚本已解压,在 package.json 上添加以下内容

"build": {
  "asarUnpack": "node_modules/get-port-cli"
}
Run Code Online (Sandbox Code Playgroud)

构建后的结果: