electron获取元素xpath、pc端网页展示获取到的xpath、websocket给两端传值

目录

  • 需求点:
  • 思路:
    • 思路:
      • 一、electron获取xpath
        • 1、创建主窗口
        • 2、创建子窗口并且setBrowserView到主窗口,子窗口默认加载error.html
        • 3、如果获取到了url,就加载url
        • 4、获取xpath并传递
      • 二、electron通过websocket传递消息
      • 三、vue监听websocket
      • 四、electron注册和多次打开问题
        • 1、electron端注册
        • 2、pc端打开
        • 3、electron端检测是第一次打开,还是重复打开

需求点:

1、打开任意网站,点击元素,获取元素xpath(这个在pc端就很难实现了,会涉及到跨域问题,所以用的electron)
2、获取的xpath需要回显到PC端网站,通过接口保存

思路:

1、electron实现获取xpath这一操作
2、pc端需要有 调起electron app 和 拿到 electron app 返回值的操作
3、传值
在传值上先后试过 mqtt、url+localstorage,mqtt因为延时,导致获取以后不能马上看到赋值,pass,url+localstorage就是electron app 通过打开一个新链接的方式跳转到pc,这样会每次打开一个新链接,并且涉及到要一直判断什么时候该保存,什么时候该清空,体验不太好,所以最后选择websocket

思路:

仅用于描述思路,代码不完整,不能直接使用

一、electron获取xpath

建2个窗口,主窗口通过 process.argv 获取 打开app时候的 参数,如果参数中包含url,则认为是pc端启动的app,这时候子窗口加载url地址,否则认为是单独启动app,这时候子窗口加载错误页面,提示需要pc端打开。
获取xpath用插件 (get-xpath)

1、创建主窗口
win = new BrowserWindow({width: 1500,height: 1200,webPreferences: {webSecurity: true,webviewTag: true, // 开启webviewnodeIntegration: true, // 启用 Node.js 集成preload: path.join(__dirname, "/static/js/preload.js"),},});
win.loadFile("./index.html");
2、创建子窗口并且setBrowserView到主窗口,子窗口默认加载error.html
view = new BrowserView({webPreferences: {webSecurity: true,webviewTag: true, // 开启webviewnodeIntegration: true, // 启用 Node.js 集成preload: path.join(__dirname, "./static/js/capturePage.js"),},});view.setBounds({x: 0,y: 0,width: 1500,height: 1200,horizontal: true,vertical: true,});winWebContents = win.webContents;viewWebContents = view.webContents;win.setBrowserView(view);viewWebContents.loadFile("./error.html");
3、如果获取到了url,就加载url
if (par && par.href && par.orderId && par.targetHref) {viewWebContents.loadURL(par.href);
}
4、获取xpath并传递

上方代码有个(preload: path.join(__dirname, “./static/js/capturePage.js”) 在这里新建一个capturePage.js文件,文件里的功能需要实现:a.引入插件; b.拦截加载页面的原生点击事件;c.给点击事件加效果;d.传递获取到的xpath给主进程

const { ipcRenderer } = require("electron");
const getXPath = require("get-xpath");// 高亮的样式
const cla = "clickClass";
const style = "background:#ffeded;outline:2px dashed #ff5050;";
// box-sizing:border-box!important;
// 清空并初始化元素
function initDom(cla) {const body = document.querySelector("html");const allChoosedDom = body.querySelectorAll(`.${cla}`);allChoosedDom &&allChoosedDom.forEach((item) => {item.style.cssText = "";item.classList.remove(cla);});
}document.addEventListener("DOMContentLoaded", (event) => {const errBox = document?.querySelector("#errBox");// console.log(errBox, "errBox");if (errBox) return;// mouseover、mouseout共用方法function changeDomStyle(env) {document.addEventListener(env, function (event) {event.preventDefault();let element = event.target;const inlineStyle = element.style.cssText;let all = inlineStyle;const hoverStyle = "background:#9eddc3;outline:2px solid #41b584;";const initStyle = "background:none; outline:none;";// box-sizing:border-box!important;if (env === "mouseover") {all += hoverStyle;element.style.cssText = all;}if (env === "mouseout") {if (element.classList.contains(cla)) {all += style;element.style.cssText = all;} else {all += initStyle;element.style.cssText = all;}}});}changeDomStyle("mouseover");changeDomStyle("mouseout");// 点击获取元素document.addEventListener("click", function (event) {event.preventDefault();initDom(cla);var element = event.target;element.classList.add(cla);element.style.cssText = style;ipcRenderer.send("submit-xpath", getXPath(element));});
});

至此,electron获取xpath交互差不多完成

二、electron通过websocket传递消息

此处需关注,初始化ws和发送消息是异步的,链接一次即可,发送消息可以多次,每次xpath获取到了就发送一次

// 初始化
const WebSocket = require("ws");
let wss, wslocal;
wss = new WebSocket.Server({ port: 66666});
wss.on("connection", (ws) => {wslocal = ws;ws.on("message", (message) => {console.log(`Received message: ${message}`);});ws.on("error", (error) => {console.log(error, "error");});
});
wss.on("error", (error) => {console.log("WebSocket-error:", error);
});
// 触发
// 子窗口给渲染进程-xpath
ipcMain.on("submit-xpath", (event, xpath) => {//给客户端发消息wslocal.send(`${decodeURIComponent(par.targetHref)}?orderId=${par.orderId}&xpath=${xpath}`);// 通过打开新窗口的方法传值-此方法体验不好,已废弃/* shell.openExternal(`${decodeURIComponent(par.targetHref)}?orderId=${par.orderId}&xpath=${xpath}`); */
});

三、vue监听websocket

这里需要实现1、判断用户是否安装app(这里是根据ws链接情况判断的,10s没有连接到,就默认没有安装)2、获取值

const loading = ref(false)const websocket = ref(null)const retryCount = ref(0)const maxRetries = ref(5)const retryDelay = ref(2000) // 2秒const timeoutId = ref(null)const createWeb = () => {if (!timeoutId.value) {loading.value = truetimeoutId.value = setTimeout(() => {gp.$baseMessage('连接超时,请先下载APP','error',false,'vab-hey-message-error')loading.value = false}, 10000)}websocket.value = new WebSocket('ws://localhost:66666')websocket.value.onopen = (event) => {console.log('WebSocket连接已建立', event)loading.value = false}websocket.value.onmessage = (event) => {clearTimeout(timeoutId.value) // 清除超时定时器const { data } = event}websocket.value.onclose = (event) => {if (event.code === 1006 && retryCount.value < maxRetries.value) {// 如果是网络问题导致的连接关闭,则重试连接retryCount.value++setTimeout(createWeb(), retryDelay.value) // 2秒后再次尝试连接} else {console.log(event, '其他原因导致的连接关闭')}}websocket.value.onerror = (error) => {console.log(error, 'error')}}

四、electron注册和多次打开问题

1、electron端注册
// 注册app,用于PC端唤醒
setDefaultProtocol: (scheme) => {//判断系统if (process.platform === "win32") {let args = [];if (!app.isPackaged) {//开发阶段调试阶段需要将运行程序的绝对路径加入启动参数args.push(path.resolve(process.argv[1]));}//添加--防御自定义协议漏洞,忽略后面追加参数args.push("--");//判断是否已经注册if (!app.isDefaultProtocolClient(scheme, process.execPath, args)) {app.setAsDefaultProtocolClient(scheme, process.execPath, args);}} else {//判断是否已经注册if (!app.isDefaultProtocolClient(scheme)) {app.setAsDefaultProtocolClient(scheme);}}
}
2、pc端打开
// myApp是我随便取的,换成自己的就可以了
const allHref = `myApp://?orderId=${orderId}&href=${href}&targetHref=${targetHref}`
window.location.href = allHref
3、electron端检测是第一次打开,还是重复打开

(因为我的需求设计是,pc端每次想要获取的时候,都可以唤醒electron app,所以需要这个,如果没有这部分的需求,这段就没必要加了)

// 获取单实例锁
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {app.quit();
} else {app.on("second-instance", (event, argv) => {ipcMain.removeAllListeners();// 处理收到的参数protocol = mainSupplement.handleArgv(argv, "myApp");par = mainSupplement.handleURL(protocol);// 唤起已打开的窗口if (win) {if (win.isMinimized()) win.restore();win.focus();// 加载需要抓取的页面if (par && par.href && par.orderId && par.targetHref) {viewWebContents.loadURL(par.href);// 子窗口给渲染进程-xpathipcMain.on("submit-xpath", (event, xpath) => {//给客户端发消息wslocal.send(`${decodeURIComponent(par.targetHref)}?orderId=${par.orderId}&xpath=${xpath}`);});}}});//冷启动主进程代码执行直接在这里获取启动协议// 处理收到的参数protocol = mainSupplement.handleArgv(process.argv, "myApp");par = mainSupplement.handleURL(protocol);
}

因为启动分为第一次启动和第二次启动,这个部分在electron文档可以看到,不多说,就是需要根据两种情境配置2份代码,app.on(“second-instance”) 和 app.whenReady() 代码非常相似

app.whenReady().then(async () => {await createWindow();// 加载需要抓取的页面if (par && par.href && par.orderId && par.targetHref) {viewWebContents.loadURL(par.href);// 子窗口给渲染进程-xpathipcMain.removeAllListeners();ipcMain.on("submit-xpath", (event, xpath) => {//给客户端发消息wslocal.send(`${decodeURIComponent(par.targetHref)}?orderId=${par.orderId}&xpath=${xpath}`);});}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/669616.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度学习缝模块怎么描述创新点?(附写作模板+涨点论文)

深度学习缝了别的模块怎么描述创新点、怎么讲故事写成一篇优质论文&#xff1f; 简单框架&#xff1a;描述自己这个领域&#xff0c;该领域出现了什么问题&#xff0c;你用了什么方法解决&#xff0c;你的方法有了多大的性能提升。 其中&#xff0c;重点讲清楚这两点&#xf…

开源计算机视觉库OpenCV详细介绍

开源计算机视觉库OpenCV详细介绍 1. OpenCV简介 OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个开源的计算机视觉和机器学习软件库。它最初由Intel开发&#xff0c;现在由一个庞大的社区维护和更新。OpenCV旨在提供一个通用、跨平台的计算机…

QtAV学习:(一)Windows下编译QtAV

QtAV 主页&#xff1a; QtAV by wang-bin 作者的编译构建说明文档&#xff1a; Build QtAV wang-bin/QtAV Wiki GitHub 我的编译环境&#xff1a; 编译环境&#xff1a;win10/msvc2015/Qt5.6.3 第一步&#xff1a;GitHub拉取代码,执行子模块初始化 地址&#xff1a; …

2024-01-07-AI 大模型全栈工程师 - 做自己的产品经理

摘要 2024-01-07 周日 杭州 阴 本节内容: a. 如何做好独立开发设计&#xff0c;实现财富自由&#xff1b; 课程内容 1. 独立开发者 英文 indie hacker&#xff0c;是指独立开发软件产品的人&#xff1b;一人承担一个项目产品的所有工作&#xff1b; 2. 创业机会 云计算设…

JavaScript 设计模式之原型模式

原型模式 一般模式 所谓原型&#xff0c;一般就类似将数据放置到原型上&#xff0c;通过原型继承模式来实现一个基类&#xff0c;然后用子类继承方式来实现 // 汽车基类 const Car function (car,sale) {this.car car;this.sale sale;this.getName function () {}this.g…

C++ 内存模型

C内存模型 - MrYun - 博客园 (cnblogs.com) 内存区域 C内存分为5个区域&#xff1a;堆 heap &#xff1a; 由new分配的内存块&#xff0c;其释放编译器不去管&#xff0c;由我们程序自己控制&#xff08;一个new对应一个delete&#xff09;。如果程序员没有释放掉&#xff0c…

abap - 发送邮件,邮件正文带表格和excel附件

发送内容 的数据获取&#xff1a; 正文部分使用cl_document_bcs>create_document静态方法实现 传入参数为html内表结构 CLEAR lo_document .lo_document cl_document_bcs>create_document(i_type HTMi_text lt_htmli_length conlengthsi_subject lv_subje…

【漏洞复现】EPON上行A8-C政企网关信息泄露漏洞

Nx01 产品简介 EPON上行A8-C政企网关是一款终端产品&#xff0c;提供企业网络解决方案。 Nx02 漏洞描述 EPON上行A8-C政企网关敏感信息泄露漏洞&#xff0c;攻击者通过敏感信息泄露获取管理员密码。 Nx03 产品主页 fofa-query: "ZXECS" && title"Web…

网络安全红队基础建设与介绍

1.ATT&CK相关背景 ATT&CK在各种日常环境中都很有价值。开展任何防御活动时&#xff0c;可以应用ATT&CK防御法&#xff0c;参考攻击者及其行为。ATT&CK不仅对网络防御者提供通用技术库&#xff0c;还为渗透测试和红队提供了基础。提到对抗行为时&#xff0c;这为…

【机器学习】机器学习简单入门

&#x1f388;个人主页&#xff1a;甜美的江 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;matplotlib &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进…

谷歌免费开放模糊测试框架OSS-Fuzz(物联网、车联网、供应链安全、C/C++)

目录 模糊测试的智能化和自动化 模糊测试不能代替安全设计原则 AI驱动的漏洞修补

<.Net>使用visual Studio 2022在VB.net中新添自定义画图函数(优化版)

前言 这是基于我之前的一篇博文&#xff1a; 使用visual Studio 2019在VB.net中新添自定义画图函数 在此基础上&#xff0c;我优化了一下&#xff0c;改进了UI&#xff0c;添加了示例功能&#xff0c;即以画圆函数为基础&#xff0c;添加了走马灯功能。 先看一下最终效果&#…

Google Chrome Close AutoUpdate

DOMException: play() failed because the user didn‘t interact with the document first.-CSDN博客 html5 audio video-CSDN博客 Google Chrome Close AutoUpdate 关闭google浏览器自动更新 1&#xff1a;检查是否已安装google浏览器&#xff0c;并卸载&#xff1a; 2&…

router路由跳转的两种模板

<router-link><router-link/> <router-view><router-view/> link &#xff1a;链接&#xff0c;联系 view&#xff1a;指看见展现在人们面前的、可以稳定地进行详细审视的事物 将语境拉回到router里&#xff0c;抽象概括一下 router-link就是一个…

docker compose安装minio

要使docker-compose管理的容器&#xff08;如MinIO&#xff09;在系统启动时自动启动&#xff0c;你需要使用Docker的重启策略。在你的docker-compose.yml文件中为MinIO服务添加restart策略即可实现这一目标。restart: always指令确保了在容器退出时总是重新启动容器&#xff0…

55. 右旋字符串(卡码网KamaCoder)

文章目录 55. 右旋字符串题目描述暴力优化&#xff1a;不能申请额外空间&#xff0c;只能在本串上操作思路代码 55. 右旋字符串 题目描述 字符串的右旋转操作是把字符串尾部的若干个字符转移到字符串的前面。给定一个字符串 s 和一个正整数 k&#xff0c;请编写一个函数&…

Spark SQL调优实战

1、新添参数说明 // Driver和Executor内存和CPU资源相关配置 --是否开启executor动态分配&#xff0c;开启时spark.executor.instances不生效 spark.dynamicAllocation.enabledfalse --配置Driver内存 spark.dirver.memory5g --driver最大结果大小&#xff0c;设置为0代…

SQLserver2008 r2 下载安装配置、使用、新建登录用户及通过Navicat远程连接

目录 一、下载 二、安装配置 1.安装 2.许可条款 3.安装程序支持文件 4.功能选择 5.实例配置 6.服务器配置 7.数据库引擎配置 8.Reporting Services 配置 9.安装进度 ​编辑 10.完成 三、使用 四、新建登录用户 1.新建登录名 2.常规 3.服务器角色 4. 用户映…

08 - python操作mysql

认识pymysql 借助pymysql模块&#xff0c;这是一个python编写的MYSQL驱动程序&#xff0c;借助它来操作数据库。 操作数据库的流程和java 使用原生的JDBC操作数据的流程步骤差不多。 安装pymysql pip install pymysql 操作步骤 导入pymysql模块 import pymysql创建数据库…

基于CNN+LSTM深度学习网络的时间序列预测matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 卷积神经网络&#xff08;CNN&#xff09; 4.2 长短时记忆网络&#xff08;LSTM&#xff09; 4.3 CNNLSTM网络结构 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 MA…