Electron 结合 Selenium + chromedriver 驱动服务实现浏览器多开
背景
在调研浏览器多开的过程中,electron 有自带的 browserview,webview,但是上面两个受制于 electron 内核版本限制,升级不够灵活,对新版的网页支持可能不及时,甚至不兼容,必须通过发布新的客户端版本才能解决,此外,这两个组件本身也不稳定,经常内存溢出,如果能改为 chrome 自己开发的浏览器内核来运行,则以上问题解决起来都不会特别吃力,所以才有了对 Electorn 控制浏览器多开的技术调研。
思路
-
在开发爬虫时,我了解导 selenium 和 chromedriver,其中 selenium 有个 node.js 调用库(还有 php,python,java 等包),其中 selenium 是一个 webdriver 协议,webdriver 是什么?和 chromedriver 有什么区别?这个后续再说。selenium 基于 webdriver 协议并且封装了 webdriver 协议,用以操控浏览器,而 chromedriver 负责桥接 selenium 和 chrome 浏览器,这样就实现了浏览器多开。
-
在研究爬虫时,还发现 puppeteer 库,这个库就比较特殊,它不依赖 chromedriver,那就意味着 puppeteer 自己实现了一套 chromedriver 用来管理 chrome,同时自己还实现了 selenium 的封装,如果将 puppeteer 打包到 electron 包中,那就要解决 chrome 执行路径的问题。
实现
-
puppeteer 这个还没跑通,这个也没有现成的案例,github 有个库,但是只支持 node.js 18,而我用的 electron 依赖 node.js 16,此外还需要 puppeteer 的版本和 electron 的版本对应,这个处理起来比较复杂,也没有人给予一个完整可运行的 demo 包,因为暂时放弃这方面的探索。
electron 官网中讲了 selenium 和 chromedriver
这是一个比较古老的文档,electron 更新频率过快,很多库都懒得跟进 electron,选择 electron 本身就是个大坑,要面对的问题很多,要求掌握的知识也很多,还解决不了这些基础的 C++问题
Selenium 和 WebDriver | Electron
webdriver vs chromedriver 的区别
WebDriver
WebDriver 是一种定义了如何通过代码来操作浏览器的接口。它是一个规范(或者说协议),由 W3C 制定,旨在通过统一的接口与各种浏览器进行交互。WebDriver 允许开发人员编写代码来控制浏览器执行各种操作,如打开网页、点击按钮、输入文本等。
ChromeDriver
ChromeDriver 是 WebDriver 的一个具体实现,它专门用于与 Google Chrome 浏览器进行交互。ChromeDriver 充当一个独立的服务,用于接收 WebDriver 的命令并将这些命令转发给 Chrome 浏览器,从而控制浏览器的行为。它是由开发 Chromium 和 WebDriver 的团队维护的。
electron 文档讲的乱乱的
-
看上面的 electron 你会很懵逼,对方讲了很多套路和方法,但由于一些东西缺失具体的演示,你根本不知道干嘛的
electron 文档核心点解析
-
开头
配置 Spectron
没啥用,你可以直接忽略,看起来这个库都被放弃了 -
紧接着 Electron 给了两种 webdriver 实现协议,一种是
WebDriverJs
,一种是WebdriverIO
,我一开始还以为这两者是顺序关系呢,其实是互斥的关系,是两种独立实现方式,第一种比较像 selenium,库名字也有 selenium,npm install selenium-webdriver
, 第二种,ChatGPT-4o 说是一种简化写法,类似于 js 和 jquery 的关系,但其实第一种就够用了。 -
其中讲到的
npm install electron-chromedriver
也是一种误导,其实就是 chromedriver,你装这个还会搞不清楚 chromedriver 和 chrome 两者之间的版本问题,但这里的 electron-chromedriver 应该是可以驱动 electron 自带的 chrome 浏览器的,但本文并不想探讨这个问题。
如何找到 chromedriver 以及对应的 chrome
开发爬虫最麻烦的点,就在于 chromedriver 和 chrome 的版本对应关系,这会让新手搔头抓耳,不过早有一批人整理了这些东西,我分享在这里
https://googlechromelabs.github.io/chrome-for-testing/latest-versions-per-milestone-with-downloads.json
非常 nice,这个 json 查看谷歌扩展是哪个?
GitHub - tulios/json-viewer: It is a Chrome extension for printing JSON and JSONP.
还有很多风格可以选择,推荐给大家,用这个查看在线 json 事半功倍
chromedriver 是可以直接启动的
下载好之后,找到路径,在地址栏输入 cmd,按回车,即可打开控制台
默认开启 9515 端口,至于启动那个 chrome,这是 selenium 那边控制的,chromedriver 会根据你给的 chrome.exe 去找到 chrome,来执行命令
我们将 119 版本的 chrome 下载下来放到 D 盘
在 Electron 主进程中编写一个启动函数
在 ready 事件中调用
function openChrome(){const webdriver = require('selenium-webdriver')const driver = new webdriver.Builder()// "9515" 是ChromeDriver使用的端口.usingServer('http://localhost:9515').withCapabilities({'goog:chromeOptions': {// 这里填您的Electron二进制文件路径。binary: "D:\\chrome-win64\\chrome.exe",args: ['--no-sandbox', '--enable-chrome-browser-cloud-management']},}).forBrowser('chrome').build()driver.get('https://www.google.com')driver.findElement(webdriver.By.name('q')).sendKeys('webdriver')driver.executeScript(`setTimeout(function() {var inputElement = document.querySelector('input[name="btnK"]');if (inputElement) {inputElement.click();} else {console.error('元素未找到');}}, 3000);`);
}
app.on('ready', openChrome)
运行脚本 npm run dev
就可以拉起浏览器了,通过给于不同的用户目录,就可以打开多个独立的浏览器同时运行,如果你将目录更换为最新用户自带的 chrome 浏览器地址也可以,不过这样
相关文章:

Electron 结合 Selenium + chromedriver 驱动服务实现浏览器多开
背景 在调研浏览器多开的过程中,electron 有自带的 browserview,webview,但是上面两个受制于 electron 内核版本限制,升级不够灵活,对新版的网页支持可能不及时,甚至不兼容,必须通过发布新的客…...

手持式气象检测设备:便携科技,气象探测
一、手持式气象检测设备:小巧身躯,大能量 手持式气象检测设备,顾名思义,是一种可以手持操作的气象监测工具。它集成了温度、湿度、气压、风速风向等多种传感器,能够实时获取气象数据,并通过显示屏或手机APP…...
shell 发送邮件脚本(免密)
#!/bin/bash ENV$1 TARGET_VERSION$2 TO$3 # SMTP服务器设置 SMTP_SERVER"邮箱服务地址" SMTP_PORT"25"# 邮件信息 FROM"jenkinsy.com" SUBJECT"Deployment Status Notification" BODY$ENV"发布完成,版本 :…...

Web动画(lottie篇)
一、Lottie简介 Lottie是一个库,可以解析使用AE制作的动画(需要用bodymovin导出为json格式),支持web、ios、android和react native。在web侧,lottie-web库可以解析导出的动画json文件,并将其以svg或者canva…...

昇思25天学习打卡营第20天|CV-ResNet50图像分类
打卡 目录 打卡 图像分类 ResNet网络介绍 数据集准备与加载 可视化部分数据集 残差网络构建 Building Block 结构 代码实现 Bottleneck结构 代码实现 构建ResNet50网络 代码定义 模型训练与评估 可视化模型预测 重点:通过网络层数加深,感知…...
grep: /etc/mysql/my.cnf: 没有那个文件或目录
当你收到 "grep: /etc/mysql/my.cnf: 没有那个文件或目录" 的错误信息时,这意味着你的系统上可能没有默认的 MySQL/MariaDB 配置文件 /etc/mysql/my.cnf。MariaDB 和 MySQL 可能会使用不同的配置文件路径。下面是一些步骤来帮助你找到正确的配置文件&…...

养猫好物|宠物空气净化器是不是智商税?靠谱猫毛空气净化器推荐
宠物空气净化器是不是智商税?宠物空气净化器是否真有其效,是许多由于要不要买空气净化器养宠人心中的疑惑。作为呼吸科医生,我深知良好空气质量对呼吸道健康的重要性,因此建议所有家庭,尤其是养有猫狗等宠物的家庭&…...

【CPS出版】2024年智能计算与数据分析国际学术会议(ICDA 2024,9月6日-8)
为探讨数据科学和计算智能领域的关键问题,促进相关交流,2024年智能计算与数据分析国际学术会议(ICDA 2024)将于2024年9月6日-8日在中国青岛召开。 本届会议拟邀请数据分析和计算智能领域的顶级专家、学者和产业界优秀人才,围绕当前…...

AutoGen框架革新:解锁新闻稿写作的新境界
前言 今天带来的仍然是AutoGen基于AssistantAgent和UserProxyAgent的例子,以帮助大家一起消化目前最前卫的AI应用框架。这是一个AIGC最擅长,因为生成新闻稿嘛,同时又需要利用Agent的一个常规Demo。了解LangChain的同学,会通过对比…...

数据结构之队列详解
1.队列的概念以及结构 队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFo(Frist in Frist out)的特性 入队列:进行插入才操作的一端称为队尾 出队列:进行删除操作的一…...

[渗透测试] 反序列化漏洞
反序列化漏洞 序列化:将对象的状态信息转换为可以传输或存储的形式的过程。简单的来说,就是将一个抽象的对象转换成可以传输的字符串 ,以特定的形式在进行之间实现跨平台的传输。 序列化大多以字节流、字符串、json串的形式来传输。将对…...
C++ 类型转换 包括C风格的转换、static_cast、const_cast、reinterpret_cast、dynamic_cast、模板特化等
C 类型转换 包括C风格的转换、static_cast、const_cast、reinterpret_cast、dynamic_cast、模板特化等 flyfish 0. 隐式转换(Implicit Conversions) 隐式转换是编译器自动进行的类型转换,通常在需要将一个类型转换为另一个类型以匹配函数参…...
等保通过标准
等保测评,即信息系统安全等级保护测评,是国家对信息系统安全等级保护的一种评估活动。它涉及到安全管理、安全技术、安全运维等多个方面,旨在评定信息系统是否达到了国家设定的安全等级保护标准。等保测评的通过标准通常会根据信息系统的安全…...
reduceByKey 函数详解
reduceByKey 函数详解 实现原理 reduceByKey 函数主要用于处理分布式数据集。它接收两个操作符作为参数: keySelector:这是一个映射函数,用于从输入元素中提取键。 valueReducer:这是另一个函数,用于将具有相同键的…...

CSI-RS在信道中传输的过程
简单介绍CSI-RS信号生成,在信道中传输和接收的过程 1.载波配置 首先需要配置载波相关的参数 系统带宽和子载波间隔 5G NR中,系统带宽和子载波间隔是两个关键参数,共同决定无线资源的分配和使用 系统带宽 5G NR支持广泛的系统带宽&…...
建造者模式(Builder Pattern)工作原理
文章目录 [toc]建造者模式(Builder Pattern)工作原理一、基本概念二、主要角色三、工作流程(一)定义产品(二)定义抽象建造者(三)定义具体建造者(四)定义指挥者…...
Ubuntu22.04安装Go语言的几种方式
在 Ubuntu 22.04 上安装 Go 语言可以通过几种不同的方法,以下是两种常见的安装方法: 方法1:使用 go 官方安装脚本 打开终端。 下载 Go 语言的安装脚本: curl -O https://go.dev/dl/go1.22.5.linux-amd64.tar.gz请检查 Go 官方网…...

Typora笔记上传到CSDN
1.Typora 安装 Typora链接:百度网盘 提取码:b6d1 旧版本是不需要破解的 后来的版本比如1.5.9把放在typora的根目录下就可以了 2.上传到CSDN 步骤 csdn 写文章-使用MD编辑器-导入本地md文件即可 问题 图片没法显示 原因 图片的链接是本地的 当然没法…...

Modbus转BACnet/IP网关BA100-配硬件说明
在现代自动化系统中,不同设备和系统之间的通信至关重要,Modbus和BACnet/IP协议虽然各有优势,但它们之间的直接通信存在障碍。钡铼Modbus转BACnet/IP网关作为连接这两种协议的桥梁,允许不同系统之间的无缝数据交换。 一、Modbus转…...

DjangoRF实战-2-apps-users
1、用户模块 创建一个用户模块子应用,用来管理用户,和认证和授权。 1.1根目录创建apps, 为了使用方便,还需要再pycharm中设置一下资源路径,就可以自动提示 1.2注册子应用 1.3添加应用根目录到环境变量path python导…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...

深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...

HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...