我从另一个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);
}
})();
Typescript编译器抱怨executablePath
方法选项对象的launch
属性,因为它必须是string
类型,而不是Electron
类型。那么如何将电子铬可执行路径传递给操纵up呢?
答案 0 :(得分:2)
没有一些变通办法和标志更改,您不能直接将电子可执行文件与Puppeteer一起使用。他们在API方面有很多差异。特别是电子不具有所有的 chrome。* API,这是Chrome浏览器正常工作所需的API,许多标志仍然没有适当的替代物,例如the headless flag。
下面您将看到两种方法。但是,您需要确保两点,
puppeteer-in-electron
有很多变通办法,但是最近有一个puppeteer-in-electron软件包,可让您使用电子在电子应用程序中运行木偶。
首先,安装依赖项,
npm install puppeteer-in-electron puppeteer-core electron
然后运行它。
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();
另一种方法是获取电子应用程序的远程调试端口并连接到它。 trusktr on electron forum共享此解决方案。
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()
})
以上两种解决方案均使用 webSocketDebuggerUrl 解决此问题。
添加此注释是因为大多数人使用电子来捆绑应用程序。
如果要构建木偶内核和电子木偶,则需要使用hazardous
和electron-builder
来确保get-port-cli
有效。
在main.js顶部添加危险
// main.js
require ('hazardous');
确保已解压缩get-port-cli脚本,在package.json上添加以下内容
"build": {
"asarUnpack": "node_modules/get-port-cli"
}
构建后的结果
答案 1 :(得分:0)
还有另一个选项,适用于电子5.x.y及更高版本(目前适用于电子7.x.y,我尚未在8.x.y beta中对其进行测试):
// const assert = require("assert");
const electron = require("electron");
const kill = require("tree-kill");
const puppeteer = require("puppeteer-core");
const { spawn } = require("child_process");
let pid;
const run = async () => {
const port = 9200; // Debugging port
const startTime = Date.now();
const timeout = 20000; // Timeout in miliseconds
let app;
// Start Electron with custom debugging port
pid = spawn(electron, [".", `--remote-debugging-port=${port}`], {
shell: true
}).pid;
// Wait for Puppeteer to connect
while (!app) {
try {
app = await puppeteer.connect({
browserURL: `http://localhost:${port}`,
defaultViewport: { width: 1000, height: 600 } // Optional I think
});
} catch (error) {
if (Date.now() > startTime + timeout) {
throw error;
}
}
}
// Do something, e.g.:
// const [page] = await app.pages();
// await page.waitForSelector("#someid")//
// const text = await page.$eval("#someid", element => element.innerText);
// assert(text === "Your expected text");
// await page.close();
};
run()
.then(() => {
// Do something
})
.catch(error => {
// Do something
kill(pid, () => {
process.exit(1);
});
});
获取pid
和使用kill
是可选的。对于在某些CI平台上运行脚本没有关系,但是对于本地环境,每次尝试失败后,您都必须手动关闭电子应用。
请参阅此sample repo。
答案 2 :(得分:0)
最好的答案对我来说不起作用,使用电子 11 和 puppeteer-core 8。 但是在主进程中启动 puppeteer 然后在渲染器进程中对我有用。您可以使用 ipcMain 和 ipcRenderer 相互通信。下面的代码
main.ts(主进程代码)
import { app, BrowserWindow, ipcMain } from 'electron';
import puppeteer from 'puppeteer-core';
async function newGrabBrowser({ url }) {
const browser = await puppeteer.launch({
headless: false,
executablePath:
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
});
const page = await browser.newPage();
page.goto(url);
}
ipcMain.on('grab', (event, props) => {
newGrabBrowser(JSON.parse(props));
});
home.ts(渲染进程代码)
const { ipcRenderer } = require('electron');
ipcRenderer.send('grab',JSON.stringify({url: 'https://www.google.com'}));