Puppeter と Electron の組み合わせ。Electron を使用してビジュアル インターフェイスを作成します。

序文

前の記事: Puppeteer の基本、一般的なアプリケーションの開始、Google プラグインを使用した Puppeteer スクリプトの作成、Puppeteer の基本的な使用法とスクリプトの作成方法を簡単に紹介します。

ただし、スクリプトはノード環境で実行する必要があるため、開発者にとっては問題ないかもしれません。しかし、作成したスクリプトが開発者以外のユーザーが使用することを目的としていた場合はどうなるでしょうか? では、ビジュアルインターフェイスを作ることはできるでしょうか?

このとき思い出したのが Electron で、デスクトッププログラムを作るのに使えて、 と が埋め込まれているんですが、ChromeiumこれNode.jsでいいんじゃないでしょうか?
ここに画像の説明を挿入します

Electron ドキュメント
https://www.electronjs.org/

Puppeter ドキュメント
https://puppeteer.bootcss.com/

準備する

Electron プロジェクトを構築する

プロジェクトのビルドがより便利になり、Vite提供されたテンプレートを直接使用できるようになりました。それは個人の選択によるので、私はここを選択します

electron-vite-vue - Electron + Vite + Vue テンプレート。

テンプレートは比較的シンプルで、私のような初心者にとっても使いやすいです。もちろん、さらにいくつかのテンプレートをダウンロードして効果を確認し、利点を統合して、子供に適したテンプレートを開発することもできます。

テンプレートの選択

ここに画像の説明を挿入します
プロジェクトをダウンロードした後、依存関係をインストールして実行します。一般的に使用される依存関係がインストールされており、これはまだ非常に優れています。

# 安装依赖
npm install
# 运行
npm run dev
# 打包
npm run build

ランニングエフェクトの
ここに画像の説明を挿入します
インストール依存関係

これをインストールするとelement-plus、その後の開発と使用axiosが容易になりますvue-router

npm install element-plus  vue-router axios pinia  --save

設定ファイルを変更する

main.ts

import {
    
     createApp } from 'vue'
import "./style.css"
import App from './App.vue'
import './samples/node-api'

import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import {
    
     createPinia } from 'pinia'
import router from './router'

const app = createApp(App)
const store = createPinia()

app
  .use(ElementPlus)
  .use(store)
  .use(router)
  .mount('#app')
  .$nextTick(() => {
    
    
    postMessage({
    
     payload: 'removeLoading' }, '*')
  })

修正後

ここに画像の説明を挿入します
パペッティアをインストールする

npm install puppeteer.11.1

通信

スクリプトを vue で直接呼び出すことはできません。vue コンポーネントで Electron にメッセージを送信する必要があります。Electron はメッセージを受信した後、対応するコマンドを実行します。

electronこのディレクトリを見てみましょう。electon/mainこのディレクトリにはメイン プロセスが保存され、electon/preloadこのディレクトリにはプリロード スクリプトが保存されます。

メイン プロセス
メイン プロセスは Electron アプリケーションのメイン プロセスであり、すべてのレンダリング プロセスとウィンドウの作成と制御を担当します。これは Node.js 環境で実行されるプロセスであり、Electron が提供する API を使用して、基礎となるオペレーティング システム機能にアクセスできます。メイン プロセスは、アプリケーションのライフ サイクルの管理、システム レベルのイベントの処理、レンダリング プロセスの作成と破棄などを担当します。
メインプロセスは通常、JavaScript ファイル (通常は main.js という名前) を通じて定義および作成されます。メインプロセスでは、ウィンドウの作成、オペレーティングシステムリソースへのアクセス、システムレベルのイベントの処理など、Electron が提供する API を使用できます。

プリロードスクリプト

プリロード スクリプトは、レンダリング プロセスが実行される前にロードされて実行されるスクリプトです。レンダリングプロセスでNode.jsのAPIにアクセスできるため、メインプロセスと通信せずにレンダリングプロセスでElectronが提供する一部のAPIを利用できます。プリロード スクリプトは、レンダリング プロセスが作成される前に挿入され、Web ページの作成時にプリロード オプションを通じて指定できます。
プリロード スクリプトは通常、ファイル システムへのアクセスやデータベースの操作など、Node.js API の使用を必要とするレンダリング プロセスでの一部の操作を実行するために使用されます。レンダリング プロセスでいくつかの追加の機能と権限を提供できます。

プリロード スクリプトはレンダリング プロセスのサンドボックス環境で実行され、メイン プロセスから分離されているため、セキュリティと権限に関連する操作は注意して扱う必要があります。

vueとel​​ectron間の通信

vue は電子と通信します

まず、Vue コンポーネントで、Electron が提供するリモート モジュールを使用して現在のレンダリング プロセスの BrowserWindow インスタンス オブジェクトを取得し、このオブジェクトを使用してメイン プロセスにメッセージを送信します。サンプルコードは次のとおりです。

// 导入ipcRenderer模块
const {
    
     ipcRenderer } = window.require('electron')
// 向Electron主进程发送消息
ipcRenderer.send('toMain', 'message content')

次に、Electron メイン プロセスで toMain イベントをリッスンし、イベントを受信したときに対応するスクリプトを実行します。サンプルコードは次のとおりです。

import {
    
     ipcMain } from 'electron'
// 监听toMain事件
ipcMain.on('toMain', (event, message) => {
    
    
  // 执行相应的脚本
})

Electron は Vue と通信します

vueコンポーネントはメッセージをリッスンします

// 导入ipcRenderer模块
const {
    
     ipcRenderer } = window.require('electron')

// 监听来自Electron主进程的消息
ipcRenderer.on('fromMain', (event, message) => {
    
    
  // 处理从Electron主进程接收到的消息
})

電子がメッセージを送る

import {
    
     ipcMain } from 'electron'

// 监听来自Vue组件的消息
ipcMain.on('toMain', (event, message) => {
    
    
  // 执行相应的脚本

  // 获取所有打开的窗口
  const windows = BrowserWindow.getAllWindows()
  // 向所有窗口广播消息
  windows.forEach(window => {
    
    
    window.webContents.send('fromMain', 'response content')
  })
})

ここに画像の説明を挿入します

Electron とノードスクリプト間の通信

たとえば、ノード スクリプトを使用して画像をダウンロードしたい場合、electron がノード スクリプトにメッセージを送信して、ダウンロードした画像の名前を知らせる必要があります。ノード スクリプトがイメージをダウンロードした後、イメージのダウンロードが完了したことを Electron に伝える必要がありますか?

ここではモジュールが必要ですchild_process。このモジュールには、child_process子プロセスを作成するためのいくつかのメソッドが用意されていますexec:spawnおよびforkこれらの方法は次の点で異なります。

  1. execメソッド:execメソッドはコマンドを実行し、その出力を取得するために使用されます。シェルを作成し、そのシェル内で指定されたコマンドを実行します。コマンドの実行が完了すると、コマンドの出力を取得するコールバック関数が提供されます。この方法は、単純なコマンドを実行してその出力を取得する必要がある状況に適しています。

  2. spawnメソッド:spawnメソッドは、新しいプロセスを作成し、ストリームを通じてプロセスと通信するために使用されます。複雑なコマンドを実行でき、標準入力、標準出力、および標準エラー ストリームのリアルタイム データ送信を提供します。この方法は、子プロセスとのリアルタイムの対話が必要な状況に適しています。

  3. forkメソッド:forkメソッドは、spawn新しい Node.js プロセスを作成するために使用される特別な形式のメソッドです。子プロセスで Node.js モジュールを実行し、IPC (プロセス間通信) チャネルを通じて親プロセスと通信できます。この方法は、タスクを並列処理するために独立した Node.js プロセスを作成する必要がある状況に適しています。

結論は:

  • exec単純なコマンドを実行し、その出力結果を取得するために使用されます。
  • spawn子プロセスを作成し、ストリーム経由でリアルタイムで通信するために使用されます。
  • fork独立した Node.js プロセスを作成し、IPC を通じて親プロセスと通信するために使用されます。

最初の 2 つはあまり使われていないので、あまり調べていませんが、興味があれば Baidu を使ってみてください。ここでは主に 3 について説明します。fork

電子側

const {
    
     fork } = require('child_process');

// 创建子进程
const child = fork('child.js');
// 向子进程发送消息
child.send('Hello from main');

// 这是创建的窗口界面的对象
const mainWindow = new BrowserWindow({
    
    
    width: 800,
    height: 600,
    webPreferences: {
    
    
      nodeIntegration: true // 允许在渲染进程中使用 Node.js API
    }
 });


// 监听子进程的消息
child.on('message', (msg) => {
    
    
   mainWindow.webContents.send('message-from-child', msg); // 向渲染进程发送消息
});

補充:

1. 子プロセスを作成するプロセスでは、同時にノード スクリプトが実行されます
2. 子プロセスの作成時にパラメータを渡すことができます。

// 创建子进程,并指定命令行参数和环境变量
const child = fork('child.js', ['arg1', 'arg2'], {
    
     env: {
    
     NODE_ENV: 'production' } });

サブプロセス (スクリプト)

const {
    
     ipcMain } = require('electron');

// 监听主进程发送的消息
ipcMain.on('message-from-renderer', (event, msg) => {
    
    
  console.log('Received message from renderer:', msg);
});

// 向主进程发送消息,也可以发送对象
process.send('Hello from child');

補充:

サブプロセスは、process.argvサブプロセスの開始時に属性を通じて渡されるコマンド ライン パラメータを取得できます。process.argvNode.js プロセスの開始時に渡されるすべてのコマンド ライン パラメーターを含む配列です。

console.log(process.argv); // 打印所有命令行参数
console.log(process.argv[0]); // 打印 Node.js 可执行文件路径
console.log(process.argv[1]); // 打印被执行的 JavaScript 文件路径
console.log(process.argv.slice(2)); // 打印用户传递的命令行参数

vueとノードスクリプト間の通信

上で紹介した通信はいずれも中継局に相当するメインプロセスを使用する必要があります。それでは、vue コンポーネント内のノード スクリプトと直接通信することは可能でしょうか? たとえば、次の助けを借りて確認することが可能です。spawn

const {
    
     spawn } = require('child_process');import {
    
     spawn } from 'child_process';

ただし、この方法を使用することはお勧めしませんので、詳しく調べるつもりはありません。

メインプロセスを介して通信すると、すべての通信がメインプロセスで検出され、問題を簡単に調査できます。パラメータを渡すことで、さまざまなスクリプトを実行するようにパブリック通信を設定できます。

ただし、vue コンポーネントがノード スクリプトと直接通信できる場合は、コンポーネントの数が少なくても問題ありません。コンポーネントが多すぎたり、一緒に開発する人が多すぎると、さまざまな問題が発生しやすくなります。たとえば、私は写真をダウンロードするためのメッセージ a を定義し、別の人は写真をダウンロードするためのメッセージ b を定義し、場合によっては c、d などを定義します。これにより、プロジェクトがますます悪化する可能性があります。

メッセージの種類

以下はgptと組み合わせて自分で適用したものですが、正確ではないかもしれませんので、間違いがあればご指摘ください。

  • メイン プロセスとレンダリング プロセスの間の通信では、メッセージ タイプをカスタマイズできますが、両者が一貫していることを確認してください。

メインプロセス

import {
    
     app, BrowserWindow, shell, ipcMain } from 'electron'

// 监听toMain事件
ipcMain.on('toMain', (event, message) => {
    
    
  console.log("toMain事件:", event, message)
  // 获取所有打开的窗口
  const windows = BrowserWindow.getAllWindows()
  const date = new Date().toLocaleDateString()
  // 向所有窗口广播消息
  windows.forEach(window => {
    
    
    window.webContents.send('fromMain', date)
  })
})

レンダリングプロセス

const {
    
     ipcRenderer } = window.require('electron')

// 监听从Electron主进程接收到的消息
ipcRenderer.on('fromMain', (event, message) => {
    
    
    console.log("fromMain", event, message)
    date.value = message
})

// 向Electron主进程发送消息
ipcRenderer.send('toMain', 'message content')
  • メインプロセスは子プロセス(ノードスクリプト)と通信します

メインプロセス

const {
    
     fork } = require('child_process');

// 创建子进程,filePath是脚本路径
const child = fork(filePath,['screenshot_0.png']);
// 监听子进程的消息
child.on('message', (data) => {
    
    
    console.log("success:",data)
})

messageこれはchild_processモジュール内の固定イベント名であり、子プロセスによって送信されたメッセージを受信するために使用されます。これは、子プロセスによって送信されるあらゆる種類のメッセージをリッスンする組み込みイベントです。子プロセスはオブジェクトを送信でき、メインプロセスはオブジェクトの属性値に基づいてメッセージの種類を識別します。

脚本

const message = {
    
    
    type: "download",
    status: "success",
    path: path.join(
      process.env.DIST_ELECTRON,
      `../puppeteer-download/${
    
    process.argv[2]}`
    ),
  };
  process.send(message);

スクリプトを実行する

コードはここには載せませんが、レンダリングは次のとおりです:
画像の説明を追加してください
パッケージ化中にいくつかの問題が発生しました。

質問 1: 以下に示すように、その理由は、Nullish Coalescing Assignment (??=) が ECMAScript 2021 で導入され、それをサポートするには Node.js 15.0.0 以降が必要であるためです。Node.js のバージョンが 15.0.0 以降であることを確認する必要があります
ここに画像の説明を挿入します
質問 2: 理由は以下の通り、github からファイルをダウンロードするときにエラーが発生するためです。中国のgithub。
ここに画像の説明を挿入します
このファイルに加えて、他にもいくつかのファイルがあり、ダウンロード アドレスをブラウザにコピーすることでダウンロードできます。
ここで合計 3 つのファイルをダウンロードしました: 、 。winCodeSign-2.6.0.7zこれらnsis-3.0.4.1.7z3nsis-resources-3.4.1.7zつのファイルは、それぞれ対応するファイル ディレクトリに解凍する必要があります (パスは同じではない場合がありますが、基本的には C ドライブです。フォルダーを見つけてくださいelectron-builder)
。 :
ここに画像の説明を挿入しますここに画像の説明を挿入します

再度パッケージングを実行すると、パッケージ化が成功すると次のようになります。
ここに画像の説明を挿入します
ここに画像の説明を挿入します

パッケージ化に必要な構成ファイルは、プロジェクト デモのダウンロード アドレスからダウンロードされています:
リンク: https://pan.baidu.com/s/12EnVdQNB7bwqDACLISEUcw
抽出コード: 1234

おすすめ

転載: blog.csdn.net/weixin_41897680/article/details/133012022