因为需要批量识别网页中的二维码,仅使用前端浏览器又存在跨域的问题。
首先考虑使用的是使用node,但是由于没有找到一款适合加载网页的库而放弃,找到的是只能加载第一次返回的页面,当页面中存在js跳转就不能正确的返回页面内容。
至于为什么不选择python,那是因为我不会。
最后采用的Electron,Electron可以使用javascript开放跨平台的应用,并且天生能加载网页,可以与浏览器进行交互,比如通信、截图、和三方网页交互,Electron中也集成了node,可以使用第三方库做额外的操作。
本次识别网页中的二维码没有开启禁用跨域功能,开启后的通信应该会少点,这个以后再试试,这里现在讲讲开发中遇到的问题
Electron 安装
参考我这里写的
electron 安装失败,Electron failed to install correctly - 掘金 (juejin.cn)
开发中的问题
完成这次开发主要加强了
BrowserWindow
ipcMain
ipcRenderer
的基本使用,包括主进程、渲染进程、加载内部页面、加载外部页面、页面开启node和electron环境、内部页面使用
ipcRenderer
与主进程通信、外部页面使用预加载与主进程通信、主进程要主动解绑事件或者方法绑定
主进程是
Electron
的主程序,控制着一切
渲染进程是加载的页面,包括外部和内部,也可以加载文件
加载网页有时需要设置
webPreferences
完成一些特定功能
想要和渲染进程完成通信,要开启
webPreferences
中的两个属性
nodeIntegration: true
启用Node integration
contextIsolation: true
在独立 JavaScript 环境中运行 Electron API和指定的
preload
脚本. 默认为
true
win.webContents.send('parse-code', params)
const { ipcRenderer } = require('electron')
ipcRenderer.on('parse-code', (event, arg) => {
......
从渲染器进程到主进程的异步通信,通过ipcRenderer
发送事件,主进程通过ipcMain
接收异步通知
const { ipcRenderer } = require('electron')
console.log(ipcRenderer.sendSync('synchronous-message', 'ping'))
ipcRenderer.send('asynchronous-message', 'ping')
const { ipcMain } = require('electron')
ipcMain.on('synchronous-message', (event, arg) => {
console.log(arg)
event.returnValue = 'pong'
ipcMain.on('asynchronous-message', (event, arg) => {
console.log(arg)
event.reply('asynchronous-reply', 'pong')
win.webContents.send('asynchronous-reply', 'pong')
当想和三方页面通信,需要通过preload
预加载一个js文件,并监听和发送事件
js文件必须是全路径preload: path.join(__dirname, 'viewPreload.js')
此时属于渲染进程,不是主进程
监听和发送事件通正常的加载内部页面,如果不成功这时就重启程序
const { ipcRenderer } = require('electron')
ipcRenderer.on('parse-code-pre', (event, params) => {
const htmlEl = document.querySelector(params.expression)
ipcRenderer.send('parse-code-end', {
...params,
expressionVal: htmlEl && htmlEl.innerHTML || ''
解绑主进程事件监听
当渲染进程被销毁时,如果主进程存在相应的事件监听,这时最好将其解绑,防止不必要的监听和错误引用
开发的功能
将功能分开到不同的页面,达到功能区分,使功能更容易区分
主要是设定页面加载多少次才显示二维码、延时识别时间。
首先需要去测试页面测试页面功能,然后再批量页面去批量处理数据。
需要在主页面添加好需要测试的url,然后去测试
监听窗口的ready-to-show
事件可以指定当前页面重新加载了多少次
页面加载好后不需要别的操作,只需要点击关闭
当点击关闭事件的时候首先阻止页面关闭event.preventDefault()
为了更好的识别券码,防止页面提前关掉
使用jsqr
处理win.webContents.capturePage()
获得的图片数据
这时图片不需要保存,只是需要转换一下image.toBitmap()
同时要传入文件的尺寸image.getSize()
jsqr
要在dependencies
中,打包的时候带上,否则运行起来找不到依赖包
向主页面渲染进程发送事件
带着数据加载次数、二维码解析值
销毁测试页面win.destroy()
测试页面成功以后就需要进行批量处理了,这里会进行连续的识别,当识别页面意外关闭也可以继续之前的位置进行识别,完成后可以进行批量的复制,复制的内容对不通的券码会进行换行。
后期需要加入的内容包括:缓存上次操作信息(确保意外关闭导致的数据丢失,加快解析速度)、excel导出缓存结果(做到有理可依)
基本功能和测试页面类似,主要加入了自动识别和自动循环相关的逻辑,测试页面创建的时候加载次数、延时时间已经保存好了
主进程接收加载页面的通知
判断达到加载次数和延时时间自动去识别券码
将识别的数据通知给批量页面渲染线程,并等待下一次加载通知
当批量页面发现没有需要识别的页面后,通知主线程隐藏显示页面
因为需要等待页面资源加载并且要加载达到一定次数,还要等待页面加载完成,所以每次加载都需要很长时间
这一次开发的工具,把electron的创建浏览器窗口和通信搞清楚了,其他的东西还没有过多的查看,最主要的是多看文档,特别是官方文档,看不明白的反复看,看别人是怎么做的。
无论是预加载文件,还是内部的网页使用Vue、React,都可以使用构建工具处理,这里因为文件结构比较简单,就不做处理了。
BrowserWindow | Electron (electronjs.org)
ipcMain | Electron (electronjs.org)
ipcRenderer | Electron (electronjs.org)