基于Electron构建带GUI界面的Node.js爬虫应用

作者:夜航船时间:2026-10-22 20:47:49浏览:152

本文介绍如何利用Electron框架开发带有图形界面的Node.js爬虫工具。内容涵盖环境配置、主进程与渲染进程间通过IPC进行通信以传递Cookie、使用superagent处理验证码获取及登录模拟,以及利用cheerio解析数据并导出为Excel文件。适合希望将脚本转化为可视化工具的开发者参考。

Electron简介

Electron是一个开源框架,允许开发者使用Web技术构建跨平台桌面应用程序。

它结合了JavaScript、HTML和CSS,使得开发者能够利用现有的Web技能创建原生桌面应用。

访问Electron官方网站获取更多信息:https://electronjs.org/

从技术本质上看,Electron封装了一个精简版的Webkit浏览器来渲染HTML页面,并通过中间层与操作系统进行交互,相当于为Web项目提供了一个Node.js运行环境的外壳。

项目背景与准备

前言

由于公司购买的推广服务缺乏后台API接口,手动操作效率低下且不够灵活,因此决定开发一个爬虫程序。考虑到目标用户群体对技术门槛较为敏感,提供一个图形用户界面(GUI)是必要的。虽然C#等语言适合快速构建界面,但Visual Studio体积庞大且启动缓慢,相比之下,使用Electron开发不仅轻量,还能借此机会深入学习该技术。

准备工作

首先需要确保系统中已安装Node.js环境。

接着通过npm安装Electron依赖。建议将npm源切换为国内镜像(如cnpm),以提高下载成功率并加速安装过程。

快速启动示例

Hello World示例

Electron官方提供了快速启动脚手架,开发者可根据需求选择最便捷的方式开始项目。

官方提供的快速启动仓库地址为:https://github.com/atom/electron-quick-start

将上述仓库克隆到本地目录。

Electron简介

克隆完成后,可以删除与Git相关的版本控制文件,因为对于本项目而言这些并非必需。

安装项目所需的依赖包,推荐使用yarn工具进行管理,因其性能更优。


yarn https://yarn.bootcss.com/

进入项目根目录。


cnpm install yarn
yarn

等待依赖包安装完成。


npm run start

若一切顺利,启动程序即可看到初始界面。

Electron简介

界面开发

界面编写

环境准备就绪后,开始进行核心功能的界面开发。

使用VS Code打开项目文件夹。值得注意的是,VS Code本身也是基于Electron开发的,其日益完善的体验证明了该框架的成熟度。

整理项目结构

Electron简介

此处省略繁琐的结构调整细节。

由于后台需要管理多个账号登录,因此设计一个专门的登录页面。

编辑index.html文件以构建前端界面。


<html>
<head>
 <meta charset="utf-8">
 <link href="http://apps.bdimg.com/libs/bootstrap/3.3.4/css/bootstrap.min.css" rel="external nofollow" rel="stylesheet">
</head>
<body>
 <div class="panel panel-default" style="margin: 10px">
  <div class="panel-body">
   <div class="form-horizontal" role="form">
    <div class="form-group">
     <label for="input_name" class="col-sm-2 control-label">登录帐号</label>
     <div class="col-sm-10">
      <input type="text" class="form-control" id="input_name" placeholder="请输入用户名">
     </div>
    </div>
    <div class="form-group">
     <label for="input_pass" class="col-sm-2 control-label">登录密码</label>
     <div class="col-sm-10">
      <input type="password" class="form-control" id="input_pass" placeholder="请输入登录密码">
     </div>
    </div>
    <div class="form-group">
     <label for="input_check" class="col-sm-2 control-label">验证码:</label>
     <div class="col-sm-6">
      <input type="text" class="form-control" id="input_check" placeholder="请输入验证码">
     </div>
     <div class="col-sm-2">
      <img id="img_code" src="code.png" />
     </div>
    </div>
    <div class="form-group">
     <div class="col-sm-offset-2 col-sm-2">
      <button id="btn_submit" class="btn btn-default">登录</button>
     </div>
     <div class="col-sm-2">
      <button id="btn_refresh" class="btn btn-default">刷新验证码</button>
     </div>
    </div>
   </div>
  </div>
 </div>
 <script>
  require('./index.js');
 </script>
</body>
</html>

界面代码主要使用基础HTML,为了提升视觉效果,引入了Bootstrap框架。

Electron支持调用Bootstrap和jQuery等前端库,这大大简化了开发流程。不过在使用jQuery时需注意一些兼容性问题。

本例中无需复杂特效,因此保持界面简洁。

在VS Code中使用快捷键Ctrl + `打开终端,运行项目。


npm run start

运行后即可看到刚才编写的网页界面。

Electron简介

验证码获取与依赖

下载验证码

登录过程通常需要验证码,因此需要实现验证码的下载功能。

具体流程为:请求验证码网站,将验证码图片保存至本地并显示,同时获取并保存验证码相关的Cookie,以便后续登录时使用。

安装所需的Node.js依赖库:superagent用于HTTP请求,fs-extra用于文件操作。

编辑main.js文件以实现后端逻辑。


const electron = require('electron')
const app = electron.app
const BrowserWindow = electron.BrowserWindow

const path = require('path')
const url = require('url')
// 爬虫
const superagent = require('superagent');
// 操作文件
const fs = require('fs-extra');

let mainWindow
// 验证码的cookie
var codeCookie
// 验证码网址
const codeUrl = '验证码地址';
// 头信息
const browserMsg = {
 'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36',
 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
};

function createWindow() {
 mainWindow = new BrowserWindow({
  width: 800,
  height: 600
 })
 superagent
  .get(codeUrl)
  .set(browserMsg)
  .end((err, res) => {
   codeCookie = res.header['set-cookie']
   console.log('codeCookie: ' + codeCookie)
   // 验证码图片保存到本地
   fs.outputFile(path.join(__dirname) + '/code.png', res.body, function (err) {})
  })
 mainWindow.loadURL(url.format({
  pathname: path.join(__dirname, 'index.html'),
  protocol: 'file:',
  slashes: true
 }))
 // 打开调试控制台
 mainWindow.webContents.openDevTools()

 mainWindow.on('closed', function () {
  mainWindow = null
 })

}
app.on('ready', createWindow)

app.on('window-all-closed', function () {
 if (process.platform !== 'darwin') {
  app.quit()
 }
})

app.on('activate', function () {
 if (mainWindow === null) {
  createWindow()
 }
})

下面介绍所安装的依赖库的作用。

fs-extra是Node.js原生fs模块的扩展,提供了更便捷的API,同时保留了原生fs的功能。

核心网络请求库为superagent,其官方文档地址为:https://www.npmjs.com/package/superagent

运行程序进行测试。

Electron简介

Electron简介

测试结果显示,验证码图片和对应的Cookie均已成功获取。

登录流程分析

分析登录流程

使用Fiddler抓包工具结合浏览器开发者控制台,分析目标网站的登录机制。

由于抓包细节非本文重点,此处略过具体步骤。

进程间通信机制

Electron进程间通信

渲染进程(即网页部分)在执行登录操作时,需要获取主进程中保存的验证码Cookie,这涉及到两个进程间的通信。

Electron中进程间通信主要使用IPC(Inter-Process Communication)机制。

主进程通过ipcMain模块监听消息,也可通过mainWindow.webContents发送消息。

渲染进程则通过ipcRenderer模块进行通信。

下面演示主进程如何向渲染进程发送Cookie数据。

在main.js文件中添加相关代码。


const ipcMain = electron.ipcMain;
ipcMain.on('notice', (e, msg) => {
 switch (msg) {
  case 'getcodeCookie':
   mainWindow.webContents.send('codeCookie',codeCookie)
   break
  default:
   break
 }
})

打开调试控制台,可以观察到消息输出。

在index.js文件中实现渲染进程的逻辑。


const electron = require('electron');
const ipcRenderer = electron.ipcRenderer;
// 获取控件
let btn_submit = document.getElementById("btn_submit");
btn_submit.addEventListener('click', (e) => {
  ipcRenderer.send('notice', 'getcodeCookie');
});
// 监听 codeCookie
ipcRenderer.on('codeCookie', (e, msg) => {
  codeCookie = msg;
  console.log('接受主进程发送的codeCookie: '+codeCookie);
});

运行程序并点击登录按钮。

此时在调试控制台中可以看到接收到的codeCookie数据。

Electron简介

模拟登录实现

模拟登录

为了顺利操作后台,需要先完成登录并获取登录后的Cookie。

编辑index.js文件以处理登录逻辑。


const electron = require('electron');
const ipcRenderer = electron.ipcRenderer;
const path = require('path');
const superagent = require('superagent');

// 链接
const urls = {
  loginUrl: "登录的地址",
  codeUrl: "验证码地址",
  targetUrl: "后台的地址"
};

// 头信息
const browserMsg = {
  "User-Agent": "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36",
  'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
};
// 验证码cookie
var codeCookie;
// 登录后的cookie
var tokenCookie;

// 获取控件
const btn_submit = document.getElementById("btn_submit");
const btn_refresh = document.getElementById("btn_refresh");
const input_name = document.getElementById("input_name");
const input_pass = document.getElementById("input_pass");
const input_code = document.getElementById("input_code");

// 登录按钮 点击事件
btn_submit.addEventListener('click', (e) => {
  ipcRenderer.send('notice', 'getcodeCookie');
  // 获取输入文本
  var name = input_name.value;
  var pass = input_pass.value;
  var code = input_check.value;
  // 校验输入
  if (name == "" || pass == "" || code == "") {
    alert("请输入");
  } else {
    // 校验通过 开始进行登录操作
    superagent
      .post(urls.loginUrl)
      .set('Cookie', codeCookie)
      .set(browserMsg)
      // 避免登录后的302重定向
      .redirects(0)
      .send({
        'LoginForm[username]': name
      }).send({
        'LoginForm[password]': pass
      }).send({
        logincode: code
      }).send({
        jz: '0'
      }).end((err, res) => {
        // 登录成功 获取tokenCookie
        // 获取tokenCookie
        tokenCookie = res.header['set-cookie'];
        superagent
          .get(urls.targetUrl)
          .set('Cookie',tokenCookie)
          .set(browserMsg)
          .end((err,res)=>{
            // 成功进入后台
            console.log(res.text);
          })
      });
  }

});

btn_refresh.addEventListener('click', (e) => {

});

ipcRenderer.on('codeCookie', (e, msg) => {
  codeCookie = msg;
  console.log('接受主进程发送的codeCookie: ' + codeCookie);
});

此处仅展示代码编写示例,实际获取Token或Cookie的过程可能因网站策略而异,需具体分析。

关键在于发起请求时必须携带正确的Cookie信息。

数据抓取与异步处理

数据抓取

成功登录后台后,即可开始抓取所需数据。这里使用cheerio库进行HTML解析。


cheerio https://cheerio.js.org/

cheerio可视为Node.js环境下的jQuery,其API与jQuery非常相似。

数据解析操作相对简单。

需要注意的是,Node.js是异步执行的,即使是for循环也是异步的,因此需小心处理异步逻辑。

若需等待多个请求完成后执行后续操作,应使用async/await语法。

数据导出功能

导出Excel表格

爬虫功能基本完成后,数据导出方式可根据需求灵活选择。

若需生成xls格式文件,可使用excel-export库,该库简单且满足基本需求。

此处推荐另一个更强大的库:better-xlsx。

下面演示如何调用系统保存对话框,将文件保存至本地。

编辑index.js文件以集成保存功能。


const remote = electron.remote;

btn_refresh.addEventListener('click', (e) => {

  const filepath =remote.dialog.showSaveDialog(remote.getCurrentWindow(), {
    // 过滤文件类型
    filters: [{
      name: "xls Files",
      extensions: ['xlsx']
    },
    {
      name: 'All Files',
      extensions: ['*']
    }
  ]
  });
  console.log(filepath);
});

运行程序,点击刷新验证码按钮后,即可看到系统标准的文件保存对话框。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

作者最新文章