Electron实战 -- 构建Windows桌面版Scrapydweb

背景

Scrapydweb是管理Scrapyd实例(一个爬虫工具)的Web应用,其运行依赖Scrapyd服务的运行,现计划利用Electron将其打包成一个桌面版应用。

思路如下:

  1. 利用pyinstaller将Scrapyd、Scrapydweb分别打包成可执行文件(one-folder bundle)
  2. 构建Electron app, 在其中先后启动Scrapyd和Scrapydweb
  3. 利用electron-forge对Electron app进行打包,构建最终的发布包

详细步骤

打包Scrapyd、Scrapydweb

本文所有操作均在Windows Powershell中进行
确保你的Windows中已安装python>=3.7

检查python版本

安装pyinstaller

pip install pyinstaller

安装Scrapyd

pip install scrapyd

打包Scrapyd

进入Scrapyd的安装目录(可以通过pip show scrapyd查看),观察到scrapyd的启动文件是scripts/scrapyd_run.py,于是执行下述打包指令。

kotlin 复制代码
# 生成spec文件
pyi-makespec `
--add-data "VERSION:scrapyd" `
--add-data "txapp.py:scrapyd" `
--add-data "default_scrapyd.conf:scrapyd" `
--hidden-import "scrapyd.app" `
--hidden-import "scrapyd.spiderqueue" `
--hidden-import "scrapyd.eggstorage" `
--hidden-import "scrapyd.jobstorage" `
--hidden-import "scrapyd.launcher" `
--hidden-import "scrapyd.website" `
--hidden-import "scrapyd.webservice" `
--hide-console "hide-early" `
scripts/scrapyd_run.py

# 按照spec文件打包
pyinstaller scrapyd_run.spec

程序启动(例如双击.exe文件)会弹出一个控制台窗口,如果想隐藏这个窗口,就可以像上面这样指定hide-console=hide-early

打包完成后,在当前目录下会看到dist目录,目录结构如下。其中,scrapyd_run.exe就是最终的可执行文件。由于我们是以one-folder模式打的包,_internal目录也是不可丢弃的。

安装Scrapydweb

pip install scrapydweb

打包Scrapydweb

由于Scrapydweb启动依赖一个配置文件,且Scrapydweb在第一次启动检查到该文件不存在时,会自动生成该配置文件。因此我们先启动一次Scrapyweb,在命令行直接运行 scrapydweb即可。 这时,可以在当前目录下看到新生成了scrapydweb_settings_v10.py。由于该示例中我们只会启动一个本地的scrapyd实例,因此需要修改一下该配置文件。将其中('username', 'password', 'localhost', '6801', 'group'),一行注释掉。

py 复制代码
SCRAPYD_SERVERS = [
    '127.0.0.1:6800',
    # 'username:password@localhost:6801#group',
    #('username', 'password', 'localhost', '6801', 'group'),
]

接下来类似打包Scrapyd的流程,先进入Scrapydweb的安装目录,观察到其启动文件是run.py,于是执行下述指令。

js 复制代码
# 生成spec文件
pyi-makespec `
--add-data "data:scrapydweb/data" `
--add-data "static:scrapydweb/scrapydweb/static" `
--add-data "templates:scrapydweb/templates" `
--hide-console "hide-early" `
run.py

# 按照spec文件打包
pyinstaller run.spec

再将上面得到的scrapydweb_settings_v10.py拷贝到dist/run目录下,目录结构如下。其中,run.exe是最终的可执行文件。

构建electron app

检查是否安装node、git

创建electron app

npm init electron-app@latest my-app

此时,可以看到在my-app目录下生成了若干目录和文件。编辑src/index.js,在其中启动scrapyd和scrapydweb子进程。最终完整的index.js如下:

javascript 复制代码
const { app, BrowserWindow } = require('electron');
const path = require('node:path');

// Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (require('electron-squirrel-startup')) {
  app.quit();
}

const backendScrapyd = require('child_process').spawn('scrapyd_run.exe',
{cwd: path.join(app.getPath('exe'), '../scrapyd_run')});

const backendScrapydweb = require('child_process').spawn('run.exe',
{cwd: path.join(app.getPath('exe'), '../run')});

const createWindow = () => {
  // Create the browser window.
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
    },
  });

  // and load the index.html of the app.
  // mainWindow.loadFile(path.join(__dirname, 'index.html'));
  mainWindow.loadURL('http://localhost:5000');

  // Open the DevTools.
  // mainWindow.webContents.openDevTools();
};

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
  createWindow();

  // On OS X it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow();
    }
  });
});

// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
  
  if (process.platform !== 'darwin') {
    backendScrapydweb.kill();
    backendScrapyd.kill();
    app.quit();
  }
});

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and import them here.

打包electron app

npm run make

这里make失败了,原因是ENOTEMPTY,类似错误参见github.com/electron/fo...

可以看到在当前目录下生成一个out目录,里面是构建好的文件。将上面打包好的scrapyd和scrapydweb复制到out目录,结构如下。my-app.exe就是最终的可执行文件,再将整个目录压缩即可得到一个完整的桌面版Scrapydweb安装包。

改进方向

  • 合并scrapyd和scrapydweb打包,减少体积
  • index.js中启动子进程之间作同步(考虑到scrapydweb依赖scrapyd)
  • electron-forge直接将外部文件打包进去(是否可以?),而不是通过手动压缩的方式
相关推荐
weifont20 小时前
聊一聊Electron中Chromium多进程架构
javascript·架构·electron
大得36920 小时前
electron结合vue,直接访问静态文件如何跳转访问路径
javascript·vue.js·electron
确实菜,真的爱1 天前
electron进程通信
前端·javascript·electron
曾经的你d5 天前
【electron+vue】常见功能之——调用打开/关闭系统软键盘,解决打包后键盘无法关闭问题
vue.js·electron·计算机外设
2501_915373886 天前
Electron 打包与发布指南:让你的应用运行在 Windows、macOS、Linux
windows·macos·electron
Lysun0016 天前
electron 结合 react(cra创建的) 创建桌面应用和打包桌面应用
javascript·react.js·electron
Hugh_W8 天前
Electron 设置Chrome Flags
electron
未脱发程序员8 天前
分享一款开源的图片去重软件 ImageContrastTools,基于Electron和hash算法
前端·javascript·electron
2501_915373888 天前
打造一个 Markdown 编辑器:Electron 项目实战教程
javascript·electron·编辑器
2501_9153738812 天前
Electron 从零开始:构建你的第一个桌面应用
前端·javascript·electron