使用Electron構建跨平臺的抓取桌面程序(electron抓包)

使用Electron構建跨平臺的抓取桌面程序

談起桌面應用開發技術, 我們會想到.Net下的WinForm, Java下的JavaFX以及Linux下的QT. 這些技術對于Web應用程序員來說一般比較陌生, 因為大多Web應用程序員的開發技能是前端的JavaScript和后端的Java,PHP等語言.

如果Web應用程序員想開發桌面應用怎么辦? 主流的桌面應用開發技術的學習曲線不低, 上手比較困難. 而Electron的出現給Web應用程序員帶來了福音.

Electron簡介:

Electron 是 Github 發布跨平臺桌面應用開發工具,支持 Web 技術開發桌面應用開發,其本身是基于 C 開發的,GUI 核心來自于 Chrome,而 JavaScript 引擎使用 v8…

簡單的說, Electron平臺就是用Javascript把UI和后臺邏輯打通, 后臺主進程使用NodeJs豐富的API完成復雜耗時的邏輯, 而UI進程則借助Chrome渲染html完成交互.

我之前使用SpringBoot開發了一套市長信箱抓取Web應用. 由于沒服務器部署, 所以我現在想把同樣的功能移植到桌面端, 作成一個桌面應用. 對于開發平臺我有以下需求:

  1. 能利用我現有的技術棧: Web前端JavaScript, 服務端的Java或者NodeJs.
  2. 能跨平臺, 既能編譯成Mac下的DMG安裝程序,又能編譯成windows平臺下的exe文件, 滿足不足場景的使用.

而Electron作為開發平臺正好能滿足我的這些需求, 通過一天的摸索, 我完成了這個桌面應用, 并最終打包出Mac平臺下的DMG安裝文件. 工程代碼: https://github.com/ybak/watcher

使用Electron構建跨平臺的抓取桌面程序(electron抓包)

下面將介紹我是如何使用Electron平臺開發這個桌面應用.

回顧: 市長信箱郵件抓取Web應用

動手之前, 我先分析一下之前所做的抓取Web應用. 它的架構如下:

使用Electron構建跨平臺的抓取桌面程序(electron抓包)

應用分可為四部分:

  1. 抓取程序:使用Java的OkHttp作為Http請求類庫獲取網頁內容,并交給Jsoup進行解析, 得到郵件內容.
  2. 數據庫:用Mysql實現, 用來保存抓取后的網頁內容, 并提供檢索查詢服務.
  3. 靜態交互頁面:一個簡單的HTML頁面, 使用jQuery發起ajax與后端交互, 并使用handlebar作為展示模板.
  4. 通信: 使用SpringBoot提供了交互所需的API(搜索服務,全量抓取和更新郵件).

設計: 使用Electron構建抓取桌面應用

將要實現的桌面應用, 同樣也需要需要完成這四部分的工作. 我做了以下設計:

使用Electron構建跨平臺的抓取桌面程序(electron抓包)

Electron主進程借助NodeJs豐富的生態系統完成網頁抓取與數據存儲與搜索的功能, UI進程則完成頁面的渲染工作.

  1. 抓取程序: 使用NodeJs的request, cheerio, async完成.
  2. 數據庫: 使用NodeJs下的nedb存儲, 作為應用內嵌數據庫可以方便的集成進桌面應用.
  3. UI: 使用HTML與前端JavaScript類庫完成, 重用之前Web應用中的靜態頁面.
  4. 通信: 使用Electron提供的IPC,完成主進程與UI進程的通信.

實現: 使用Electron構建抓取桌面應用

1. 抓取程序的實現:

市長信箱郵件多達上萬封, JavaScript異步的特點, 會讓人不小心就寫出上千并發請求的程序, 短時間內大量試圖和抓取目標服務器建立連接的行為會被服務器拒絕服務, 從而造成抓取流程失敗. 所以抓取程序要做到:

  1. tcp連接復用
  2. 并發頻率可控

我使用以下三個NodeJs組件:

  1. Request http客戶端, 利用了底層NodeJs的Http KeepAlive特性實現了tcp連接的復用.
  2. async 控制請求的并發以及異步編程的順序性.
  3. cheerio html的解析器.

代碼: crawlService.js

//使用request獲取頁面內容request(\’http://12345.chengdu.gov.cn/moreMail\’, (err, response, body) => { if (err) throw err; //使用cheerio解析html var $ = cheerio.load(body), totalSize = $(\’div.pages script\’).html().match(/iRecCount = d /g)[0].match(/d /g)[0]; …… //使用async控制請求并發, 順序的抓取郵件分頁內容 async.eachSeries(pagesCollection, function (page, crawlNextPage) { pageCrawl(page, totalPageSize, updater, crawlNextPage); })});

2. 數據庫的實現:

抓取后的內容存儲方式有較多選擇:

  1. 文本文件
  2. 搜索引擎
  3. 數據庫

文本文件雖然保存簡單, 但不利于查詢和搜索, 顧不采用.

搜索引擎一般需要獨立部署, 不利于桌面應用的安裝, 這里暫不采用.

獨立部署的數據庫有和搜索引擎同樣的問題, 所以像連接外部Mysql的方式這里也不采用.

綜合考慮, 我需要一種內嵌數據庫. 幸好NodeJs的組件非常豐富, nedb是一個不錯的方案, 它可以將數據同時保存在內存和磁盤中, 同時是文檔型內嵌數據庫, 使用mongodb的語法進行數據操作.

代碼: dbService.js

//建立數據庫連接const db = new Datastore({filename: getUserHome() \’/.electronapp/watcher/12345mails.db\’, autoload: true});……//使用nedb插入數據db.update({_id: mail._id}, mail, {upsert: true}, function (err, newDoc) {});……//使用nedb進行郵件查詢let match = {$regex: eval(\’/\’ keyword \’/\’)}; //關鍵字匹配var query = keyword ? {$or: [{title: match}, {content: match}]} : {};db.find(query).sort({publishDate: -1}).limit(100).exec(function (err, mails) { event.sender.send(\’search-reply\’, {mails: mails});//處理查詢結果});

3. UI的實現:

桌面應用的工程目錄如圖:

使用Electron構建跨平臺的抓取桌面程序(electron抓包)

我將UI頁面放到static文件夾下. 在Electron的進行前端UI開發和普通的Web開發方式一樣, 因為Electron的UI進程就是一個Chrome進程. Electron啟動時, 主進程會執行index.js文件, index.js將初始化應用的窗口, 設置大小, 并在窗口加載UI入口頁面index.html.

代碼:index.js

function createMainWindow() { const win = new electron.BrowserWindow({ width: 1200, height: 800 });//初始應用窗口大小 win.loadURL(`file://${__dirname}/static/index.html`);//在窗口中加載頁面 win.openDevTools();//打開chrome的devTools win.on(\’closed\’, onClosed); return win;}

在UI頁面開發的過程中, 有一點需要注意的是: 默認情況下頁面會出現jQuery, require等組件加載失敗的情況, 這是因為瀏覽器window加載了NodeJs的一些方法, 和jQuery類庫的方法沖突. 所以我們需要做些特別的處理, 在瀏覽器window中把這些NodeJs的方法刪掉:

代碼:preload.js

// 解決require沖突導致jQuery等組件不可用的問題window.nodeRequire = require;delete window.require;delete window.exports;delete window.module;// 解決chrome調試工具devtron不可用的問題window.__devtron = {require: nodeRequire, process: process}

4. 通信的實現:

在Web應用中, 頁面和服務的通信都是通過ajax進行, 那我們的桌面應用不是也可以采用ajax的方式通信? 這樣理論雖然上可行, 但有一個很大弊端: 我們的應用需要打開一個http的監聽端口, 通常個人操作系統都禁止軟件打開http80端口, 而打開其他端口也容易和別的程序造成端口沖突, 所以我們需要一種更優雅的方式進行通信.

Electron提供了UI進程和主進程通信的IPC API, 通過使用IPC通信, 我們就能實現UI頁面向NodeJs服務邏輯發起查詢和抓取請求,也能實現NodeJs服務主動向UI頁面通知抓取進度的更新.

使用Electron的IPC非常簡單.

首先, 我們需要在UI中使用ipcRenderer, 向自定義的channel發出消息.

代碼: app.js

const ipcRenderer = nodeRequire(\’electron\’).ipcRenderer;//提交查詢表單$(\’form.searchForm\’).submit(function (event) { $(\’#waitModal\’).modal(\’show\’); event.preventDefault(); ipcRenderer.send(\’search-keyword\’, $(\’input.keyword\’).val());//發起查詢請求});ipcRenderer.on(\’search-reply\’, function(event, data) {//監聽查詢結果 $(\’#waitModal\’).modal(\’hide\’); if (data.mails) { var template = Handlebars.compile($(\’#template\’).html()); $(\’div.list-group\’).html(template(data)); }});

然后, 需要在主進程執行的NodeJs代碼中使用ipcMain, 監聽之前自定義的渠道, 就能接受UI發出的請求了.

代碼: crawlService.js

const ipcMain = require(\’electron\’).ipcMain;ipcMain.on(\’search-keyword\’, (event, arg) => { ….//處理查詢邏輯});ipcMain.on(\’start-crawl\’, (event, arg) => { ….//處理抓取邏輯});

桌面應用打包

解決完以上四個方面的問題后, 剩下的程序寫起來就簡單了. 程序調試完后, 使用electron-builder, 就可以編譯打包出針對不同平臺的可執行文件了.

版權聲明:本文內容由互聯網用戶自發貢獻,該文觀點僅代表作者本人。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如發現本站有涉嫌抄襲侵權/違法違規的內容, 請發送郵件至 舉報,一經查實,本站將立刻刪除。

(0)
上一篇 2024年5月1日 下午3:05
下一篇 2024年5月1日 下午3:17

相關推薦

国产乱人视频在线播放| 人妻无码一区二区视频| 精品综合久久久久久888蜜芽| 国产成人精品一区二区三区| 麻豆国产VA免费精品高清在线 | 国产精品网站在线观看免费传媒| 中文字幕一区二区三区永久 | 两个人看的www视频免费完整版| 少妇大叫太大太爽受不了| 中文字幕激情视频| 岳一夜要我六次| 一本大道香蕉中文在线高清| 天天干天天操天天操| gdianav| 国产麻豆91网在线看| 91视频综合网| 国产欧美综合一区二区| 露脸国产自产拍在线观看| 国产做无码视频在线观看浪潮 | 国产在线拍揄自揄视精品不卡| 色偷偷91综合久久噜噜app| 国产ts在线播放| 精品亚洲A∨无码一区二区三区| 十七岁免费完整版bd| 蜜桃成熟时仙子| 国产一区二区不卡老阿姨| 精品久久久久久无码中文字幕| 免费观看激色视频网站(性色)| 波多野结衣在线不卡| 亚洲精品国偷自产在线| 欧美人与性动交另类| 亚洲s色大片在线观看| 欧美在线xxx| 亚洲伊人久久大香线蕉影院| 日韩中文字幕在线免费观看| 久久国产精品老人性| 成人18视频日本| 一本色道久久88亚洲精品综合| 在异世界迷宫开后迷宫无修改版动漫| 99久久无色码中文字幕人妻蜜柚| 国产精品久久免费视频|