Electron能否通过BrowserView读取网页DOM?附报错代码
Electron读取BrowserView加载页DOM内容问题解答
Electron完全支持读取BrowserView组件加载的指定URL对应网页的DOM内容,你运行时抛出的"An object could not be cloned"错误与权限无关,是返回值不符合跨进程传输规则导致的。
错误根因
view.webContents.executeJavaScript的代码运行在BrowserView独立的渲染进程中,执行结果需要通过IPC通道跨进程回传到主进程,回传前Electron会对结果做结构化克隆处理- 你当前代码执行
document.querySelector('body')返回的是原生DOM Element对象,这类对象不属于结构化克隆算法支持的可序列化类型,无法完成跨进程复制,因此抛出克隆失败错误
修复方法
不要直接返回DOM节点对象,在注入执行的JS代码块内,先把需要的DOM内容转换成基础可序列化类型(字符串、普通对象、数字等)再返回,同时要等页面加载完成后再执行DOM查询,避免DOM未渲染完成导致查询为空。修改后的可运行代码示例:
// Create the browser window. const mainWindow = new BrowserWindow({ height: 800, width: 1200, webPreferences: { preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY, }, }); const view = new BrowserView({ webPreferences: { webSecurity: false, allowRunningInsecureContent: true, }, }); mainWindow.setBrowserView(view); view.setBounds({ x: 200, y: 0, width: 900, height: 800 }); view.setAutoResize({ width: true, height: true }); view.webContents.loadURL("https://electronjs.org"); // 等待页面加载完成后再执行DOM操作 view.webContents.on('did-finish-load', () => { view.webContents .executeJavaScript(` // 提取需要的内容转为可序列化类型,例如此处取body的完整HTML字符串 document.querySelector('body').outerHTML `) .then((result) => { console.log("html", result); }) .catch((err) => console.log(err)); }) // and load the index.html of the app. mainWindow.loadURL(MAIN_WINDOW_WEBPACK_ENTRY); // Open the DevTools. mainWindow.webContents.openDevTools();
补充说明
- 如果需要获取DOM节点的特定属性、文本内容、计算样式,都可以在注入的JS逻辑中先提取为普通可序列化值再回传,禁止直接回传DOM节点、函数、Symbol这类不可结构化克隆的值
- 你已经在BrowserView的配置中关闭了
webSecurity、开启了不安全内容运行权限,跨域场景下读取DOM内容不会触发同源限制 - 如果页面存在异步渲染的内容,可以在
did-finish-load后加适当延时,或等待对应DOM节点出现后再做提取,避免拿到空结果
内容的提问来源于stack exchange,提问作者Jakub Radtke
相关产品推荐
相关产品推荐

