Electron23+Vue开发爬虫爬取网页数据

前言

之前用的是Electron9-13的版本,现在Electron23很多API发生了变化,所以这里重新记录一下。

官方文档:

https://electron.nodejs.cn/docs/latest/

使用Electron开发的时候常见有两种方式

  1. 使用VUE脚手架创建项目后添加vue-cli-plugin-electron-builder插件来构建Vue单页项目
  2. 直接加载本地HTML,HTML中可以引用vue.js

注意

本文基于Electron23版本,10以后的版本remote组件废弃了,需要单独引用。

替代方案:https://www.psvmc.cn/article/2023-09-13-electron-remote.html

创建项目

尽量用图形化界面创建项目 安装插件也方便

1
vue ui

安装插件

vue-cli-plugin-electron-builder

插件官网地址: https://nklayman.github.io/vue-cli-plugin-electron-builder/

Choose Electron Version选择默认即可

运行报错

INFO Launching Electron…

Failed to fetch extension, trying 4 more times

Failed to fetch extension, trying 3 more times

Failed to fetch extension, trying 2 more times

Failed to fetch extension, trying 1 more times

Failed to fetch extension, trying 0 more times
Vue Devtools failed to install: Error: net::ERR_CONNECTION_TIMED_OUT

这是因为Devtools的安装需要翻墙

注释掉src/background.js中的以下代码就行了

1
2
3
4
5
6
7
8
if (isDevelopment && !process.env.IS_TEST) {
// Install Vue Devtools
try {
await installVueDevtools();
} catch (e) {
console.error("Vue Devtools failed to install:", e.toString());
}
}

升级版本

默认vue-cli-plugin-electron-builder安装的Electron版本最高支持13.0.0

1
"electron": "23.1.3",

调试框分离

1
win.webContents.openDevTools({ mode: "detach" });

安装本地Dev-Tools插件

插件下载地址

链接:https://pan.baidu.com/s/19BzaBnZsWZxN_thHHvSYBw
提取码:psvm

插件放在项目根目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
app.on("ready", async () => {
if (isDevelopment && !process.env.IS_TEST) {
try {
// 安装vue-devtools
const { session } = require("electron");
session.defaultSession.loadExtension(
path.resolve(__dirname, "../vue-devtools") //这个是插件目录
);
} catch (e) {
console.error("Vue Devtools failed to install:", e.toString());
}
}
createWindow();
});

隐藏菜单栏

1
2
import { Menu } from "electron";
Menu.setApplicationMenu(null);

设置标题

窗口加载页面之前用的是窗口的title,加载之后用的是页面的title,所以最好两处都设置。

窗口的标题

1
2
3
4
5
6
7
8
9
10
11
12
const win = new BrowserWindow({
width: 1200,
height: 600,
title: "爬虫",
webPreferences: {
webviewTag: true,
webSecurity: false,
enableRemoteModule: true,
nodeIntegration: true,
contextIsolation: false,
},
});

页面的标题

1
2
3
4
5
6
7
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>新华字典爬虫</title>
</head>

预加载脚本

这里使用webview加载页面,使用预加载加载脚本实现数据的获取。

窗口设置

配置中开启webview标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
const path = require("path");

const { ipcMain } = require("electron");
ipcMain.on("getGlobalValue", (event, arg) => {
event.returnValue = global.shareObject[arg];
});

async function createWindow() {
global.shareObject = {
preloadPath: path.join(__dirname, "..", "public", "mypreload.js"),
};

// Create the browser window.
const win = new BrowserWindow({
width: 1280,
height: 800,
webPreferences: {
webviewTag: true,
webSecurity: false,
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
},
});

if (process.env.WEBPACK_DEV_SERVER_URL) {
await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL);
if (!process.env.IS_TEST) win.webContents.openDevTools({ mode: "detach" });
} else {
createProtocol("app");
win.loadURL("app://./index.html");
}
}

注意不要在BrowserWindow设置预加载脚本,这里设置的在webview中无效

1
2
3
4
5
6
7
8
9
10
11
const win = new BrowserWindow({
width: 1280,
height: 800,
webPreferences: {
webviewTag: true,
webSecurity: false,
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
preload: path.join(__dirname, "..", "public", "mypreload.js"),
},
});

预加载JS

文件放在public下

加载要调用的JS

根目录/public/mypreload.js

mypreload.js

文件放在了项目根目录的public文件夹下

1
2
3
4
5
6
7
8
9
10
11
12
13
const { contextBridge } = require("electron");

contextBridge.exposeInMainWorld("electronAPI", {
showData: () => {
const a_arr = document.getElementsByTagName("a");
let urlArr = [];
for (let i = 0; i < a_arr.length; i++) {
let aItem = a_arr[i];
urlArr.push(aItem.href);
}
return JSON.stringify(urlArr);
},
});

注意

  1. Electron-Vue项目在运行时页面是以URL加载的,那么加载preload.js就必须用file://协议加载
  2. 一定要先设置preload再打开页面,当然同时设置也是可以的
  3. preload.js方法返回的数据不能是DOM,否则报错

渲染页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<template>
<div class="wv_outer">
<webview
ref="mwv"
class="webview"
nodeintegration
disablewebsecurity
></webview>

<div class="btn_outer">
<button @click="readData">获取数据</button>
</div>
</div>
</template>

<script>
const { ipcRenderer } = window.require("electron");

export default {
name: "HomeView",
components: {},
data() {
return {
weburl: "https://www.qcc.com/web/bigsearch/tec-search",
url_arr: [],
};
},
mounted() {
this.loadPreloadJs();
this.openUrl();
},
methods: {
loadPreloadJs() {
//获取值
let preloadPath = ipcRenderer.sendSync("getGlobalValue", "preloadPath");
const mwv = this.$refs["mwv"];
mwv.preload = "file://" + preloadPath;
},
openUrl() {
const mwv = this.$refs["mwv"];
mwv.src = this.weburl;
mwv.addEventListener("dom-ready", () => {
// mwv.openDevTools();
});
},
readData() {
const mwv = this.$refs["mwv"];
mwv
.executeJavaScript("window.electronAPI.showData();")
.then(function (data) {
console.info(data);
});
},
},
};
</script>

<style>
.wv_outer {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
webview {
height: 0;
flex: auto;
}

.btn_outer {
height: 40px;
flex: none;
}

.btn_outer button {
width: 100px;
height: 36px;
background: #42b983;
color: white;
border: none;
border-radius: 8px;
}
</style>

打包设置

打包

如果使用vue-cli-plugin-electron-builder,直接打包就行。

vue.config.js 中配置

生成文件夹

直接生成文件夹比较快,生成后我们可以用专门的打包软件进行打包。

个人比较喜欢使用这种方式。因为默认使用NSIS打包安装效果不太好。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const { defineConfig } = require("@vue/cli-service");
module.exports = defineConfig({
transpileDependencies: true,
pluginOptions: {
electronBuilder: {
builderOptions: {
productName: "爬虫客户端",
copyright: "Copyright © 2025 psvmc",
appId: "cn.psvmc.crawler_client",
win: {
target: [
{
target: "dir",
arch: ["x64"],
},
],
icon: "public/icons/app.ico",
},
},
},
},
});

生成单一执行文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const { defineConfig } = require("@vue/cli-service");
module.exports = defineConfig({
transpileDependencies: true,
pluginOptions: {
electronBuilder: {
builderOptions: {
productName: "爬虫客户端",
copyright: "Copyright © 2025 psvmc",
appId: "cn.psvmc.crawler_client",
win: {
target: [
{
target: "portable",
arch: ["x64"],
},
],
icon: "public/icons/app.ico",
},
},
},
},
});

生成EXE

这里使用NSIS来打包EXE,打包过程中会下载依赖,会比较费时。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const { defineConfig } = require("@vue/cli-service");
module.exports = defineConfig({
transpileDependencies: true,
pluginOptions: {
electronBuilder: {
builderOptions: {
productName: "爬虫客户端",
copyright: "Copyright © 2025 psvmc",
appId: "cn.psvmc.crawler_client",
win: {
target: [
{
target: "nsis",
arch: ["x64"],
},
],
icon: "public/icons/app.ico",
},
artifactName: "${productName}-${version}-${platform}-${arch}.${ext}",
},
},
},
});

生成32位和64位

1
arch: ["x64", "ia32"],

打包

1
npm run electron:build

打包注意事项

  • 打包win环境下nsis需要图标为ico格式。
  • 图标大小最好512*512 打包mac要求。
  • 打包nsis的LICENSE.txt不能为空,文件编码为GBK,否则乱码。

依赖无法下载

手动下载放到对应位置

Mac

1
cd ~/Library/Caches/electron-builder

Linux

1
cd ~/.cache/electron-builder

Windows

1
cd %LOCALAPPDATA%\electron-builder\cache

相关下载地址

链接: https://pan.baidu.com/s/15YnlnLIrt_16Xvrmo3LLMQ 密码: 0hk3

下载的文件

nsis-3.0.4.1.7z

nsis-resources-3.4.1.7z

winCodeSign-2.6.0.7z

wine-4.0.1-mac.7z

最终目录结构

  • nsis

    • nsis-3.0.4.1
    • nsis-resources-3.4.1
  • winCodeSign

    • winCodeSign-2.6.0
  • wine
    • wine-4.0.1-mac