C++ WebDriver扩展
概述
WebDriver协议基于HTTP,使用JSON进行数据传输,定义了client与driver之间的通信标准。无论client的实现语言(如Java或C#),都能通过协议中的endpoints准确指示driver执行各种操作,覆盖了Selenium的所有功能。这些endpoints详细列出了所有可用的功能点。
目标

msedgedriver下载
启动
msedgedriver.exe --port=8080 --remote-allow-origins=* - --verbose -allow-insecure-localhost --allowed-origins=* --allowed-ips=["127.0.0.1"] --headless --disable-gpu
示例
#include "webdriver.h"int main() {WebDriver m_driver;m_driver.NavigateTo("https://www.hao123.com/");qDebug() << m_driver.getPageSource();
}
效果

webdriver.h
#ifndef WEBDRIVER_H
#define WEBDRIVER_H#include <QNetworkAccessManager>
#include <QNetworkReply>class WebDriver : public QObject
{Q_OBJECT
public:WebDriver();~WebDriver();void getStatus();void getTimeout();void setTimeOut(int implicit, long long pageLoad, long long script);void NavigateTo(const QString& url);QString getCurrentUrl();void historyBack();void historyForward();void refresh();QString getTitle();QString showWindow();void closeWindow();void getWindowHandles();void createWindow();QString getPageSource();signals:void response(const QByteArray& bytes);private:void connectToServer(const QUrl& url);private:void post(const QByteArray& bytes);void get();void deleteRes();private:void waitFinish();private:QString m_host;QNetworkAccessManager m_networkManger;QNetworkRequest m_client;std::string m_sessionID;std::string m_elementID;QByteArray m_responseCache;
};#endif // WEBDRIVER_H
webdriver.cpp
#include "webdriver.h"
#include <QElapsedTimer>
#include <QApplication>
#include <QJsonDocument>
#include <QJsonObject>
#include "webDriverResponseJson.h"
#include "webDriverRequestJson.h"WebDriver::WebDriver() : m_host("http://127.0.0.1:8080"){connectToServer(QUrl(m_host + "/session"));
}WebDriver::~WebDriver() {if (m_sessionID.empty())return;m_client.setUrl(QUrl(m_host + QString("/session/") + QString::fromStdString(m_sessionID)));deleteRes();waitFinish();
}void WebDriver::connectToServer(const QUrl& url) {m_client.setUrl(url);m_client.setHeader(QNetworkRequest::ContentTypeHeader, "application/json; charset=utf-8");m_client.setHeader(QNetworkRequest::UserAgentHeader, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Edg/128.0.0.0");m_client.setRawHeader("Cache-Control", "no-cache");REQ::Options options;options.capabilities.browserName = "edge";std::string json = JS::serializeStruct(options, JS::SerializerOptions(JS::SerializerOptions::Compact));post(QString::fromStdString(json).toLocal8Bit());waitFinish();// 反序列RES::MSEdgeRoot response;JS::ParseContext parseContext(m_responseCache.data());auto error = parseContext.parseTo(response);if (JS::Error::NoError != error) {std::string errorStr = parseContext.makeErrorString();fprintf(stderr, "Error parsing struct %s\n", errorStr.c_str());}m_sessionID = response.value.sessionId;
}void WebDriver::NavigateTo(const QString& url) {m_client.setUrl(QUrl(m_host + QString("/session/") + QString::fromStdString(m_sessionID) + "/url"));REQ::NavigateTo nav;nav.url = url.toStdString();std::string json = JS::serializeStruct(nav, JS::SerializerOptions(JS::SerializerOptions::Compact));post(QString::fromStdString(json).toLocal8Bit());waitFinish();QJsonParseError jsonError;QJsonDocument doucment = QJsonDocument::fromJson(m_responseCache, &jsonError); // 转化为 JSON 文档if (!doucment.isNull() && (jsonError.error == QJsonParseError::NoError)) { // 解析未发生错误if (doucment.isObject()) { // JSON 文档为对象QJsonObject object = doucment.object(); // 转化为对象if (object.contains("value")) { // 包含指定的 keyQJsonValue value = object.value("value"); // 获取指定 key 对应的 valueqDebug() << "NavigateTo " << (value.isNull() ? "Success" : "Fail");}}}
}QString WebDriver::getPageSource() {m_client.setUrl(QUrl(m_host + QString("/session/") + QString::fromStdString(m_sessionID) + "/source"));get();waitFinish();QJsonParseError jsonError;QJsonDocument doucment = QJsonDocument::fromJson(m_responseCache, &jsonError); // 转化为 JSON 文档if (!doucment.isNull() && (jsonError.error == QJsonParseError::NoError)) { // 解析未发生错误if (doucment.isObject()) { // JSON 文档为对象QJsonObject object = doucment.object(); // 转化为对象if (object.contains("value")) { // 包含指定的 keyQJsonValue value = object.value("value"); // 获取指定 key 对应的 valueif (value.isString())return value.toString();}}}return QString::fromStdString(m_responseCache.toStdString());
}void WebDriver::waitFinish() {QEventLoop loop;connect(this, &WebDriver::response, &loop, &QEventLoop::quit);loop.exec();
}void WebDriver::post(const QByteArray& bytes) {auto reply = m_networkManger.post(m_client, bytes);connect(reply, &QNetworkReply::finished, [this, reply]() {m_responseCache = reply->readAll();qDebug() << "finish:" << m_responseCache;emit response(m_responseCache);});
}void WebDriver::get() {auto reply = m_networkManger.get(m_client);connect(reply, &QNetworkReply::finished, [this, reply]() {m_responseCache = reply->readAll();qDebug() << "finish:" << m_responseCache;emit response(m_responseCache);});
}void WebDriver::deleteRes() {auto reply = m_networkManger.deleteResource(m_client);connect(reply, &QNetworkReply::finished, [this, reply]() {emit response(m_responseCache);});
}
example.py
import requests
import json
session_url = 'http://localhost:8080/session'
session_pars ={"capabilities": {"browserName": "edge"}}
r_session = requests.post(session_url,json=session_pars)
print(json.dumps(r_session.json(),indent=2))
参考
使用 WebDriver 自动执行 Microsoft Edge - Microsoft Edge Developer documentation | Microsoft Learn WebDriver
selenium ,webdriver 运行原理与机制-腾讯云开发者社区-腾讯云
C/C++ JSON ORM 之 structs 数据结构相互嵌套定义-CSDN博客
创作不易,小小的支持一下吧!


相关文章:
C++ WebDriver扩展
概述 WebDriver协议基于HTTP,使用JSON进行数据传输,定义了client与driver之间的通信标准。无论client的实现语言(如Java或C#),都能通过协议中的endpoints准确指示driver执行各种操作,覆盖了Selenium的所有功…...
WeChat_DevTools 断点调试方法总结
新建工程,以小程序 login 调试为例,代码如下: // 登录wx.login({success: res > {// 发送 res.code 到后台换取 openId, sessionKey, unionIddebugger;resThis this;wx.showModal({title: 登录成功,content: res.code res.code,comple…...
水波荡漾效果+渲染顺序+简单UI绘制
创建场景及布置 创建新场景Main,在Main场景中创建一个plane物体,命名为WaterWavePla,具体数值及层级面板排布如下: 编写脚本 创建一个文件夹,用于存放脚本,命名Scripts,创建一个子文件夹Effect,存放特效相关脚本,创建…...
深度学习中的结构化概率模型 - 使用图来描述模型结构篇
序言 在深度学习的探索之路上,结构化概率模型以其独特的视角和强大的表达能力,成为了研究复杂数据关系的重要工具。这一模型的核心在于其巧妙地利用图来描述模型结构,将随机变量间的复杂交互关系可视化、结构化。图的引入,不仅为…...
C语言中的栈帧
------------------------ | 局部变量区 | | (根据变量声明而变化) | ------------------------ | 参数区 | | (根据函数原型而变化) | ------------------------ | (可选) 保存寄存器区 | | (编译器/架构特定) | -…...
vue数组根据某些条件进行二次切割
原本的一个一维数组首先 1.根据depnm和bed的不同会分成不同的数组 2.在条件1的基础上分割出来的数组如果存在里面有isBgn1的会进行二次分割 比如原数组是[{depnm:1,bed:2,isBgn:0},{}……] 根据条件一会组成一个二维数组得到 [ [①depnm值一致的一个一维数组], [②bed值一…...
Yolov8改进轻量级网络Ghostnetv2
1,理论部分 轻量级卷积神经网络 (CNN) 专为移动设备上的应用程序而设计,具有更快的推理速度。卷积运算只能捕获窗口区域中的局部信息,这会阻止性能进一步提高。将自我注意引入卷积可以很好地捕获全局信息,但会在很大程度上阻碍实际速度。在本文中,我们提出了一种硬件友好…...
【Spring】@RequestMapping、@RestController和Postman
文章目录 1.RequestMapping 注解介绍2. RequestMapping 使用3. RequestMapping 是 GET 还是 POST 请求?GET 请求POST 请求指定 GET/POST 方法类型 2. Postman 介绍1. 创建请求2. 传参介绍1. 普通传参2. form-data3. x-www-form-urlencoded form 表单,对应…...
【深度学习基础模型】回声状态网络(Echo State Networks, ESN)详细理解并附实现代码。
【深度学习基础模型】回声状态网络(Echo State Networks, ESN)详细理解并附实现代码。 【深度学习基础模型】回声状态网络(Echo State Networks, ESN)详细理解并附实现代码。 文章目录 【深度学习基础模型】回声状态网络…...
Redis的基础认识与在ubuntu上的安装教程
来自Redis的自我介绍 我是Redis,一个中间件,职责是把数据存储在内存上,因此可以作为数据库、缓存、消息队列等场景使用。由于可以把数据存储在内存上,因此江湖人称快枪手 1.redis的功能特性 (1)数据在内存…...
鸿蒙harmonyos next flutter混合开发之ohos工程引用 har 文件
创建鸿蒙原生工程MyApplication。创建flutter module,生成har文件,并且将flutter module中.ohos文件entryability/EntryAbility.ets、pages/Index.ets分别替换MyApplication中的。 # 1. 创建 flutter子模块工程 flutter create -t module my_flutter_…...
react-问卷星项目(5)
实战 路由 路由设计,网址和页面的关系,就是从业务上分析需要哪些页面哪些页面内容可以抽离,业务流程要有入有出增加页面和Layout模版,模版就是抽离页面公共部分,比如都有顶部或者左侧导航,直接上代码&…...
08.useInterval
在 React 应用中,实现定时器功能通常需要使用 setInterval() 和 clearInterval(),这可能会导致代码复杂和难以维护。useInterval 钩子提供了一种声明式的方法来实现定时器功能,使得定时器的管理更加简单和直观。这个自定义钩子不仅简化了定时器的使用,还解决了一些常见的定…...
【Android 源码分析】Activity生命周期之onDestroy
忽然有一天,我想要做一件事:去代码中去验证那些曾经被“灌输”的理论。 – 服装…...
增强现实中的物体识别与跟踪
增强现实(AR)中的物体识别与跟踪是实现虚拟内容与现实世界无缝融合的关键技术。以下是该领域的主要技术和方法概述: 1. 物体识别 1.1 特征提取 SIFT、SURF、ORB:传统的特征提取算法用于识别图像中的关键点并生成描述符…...
移动端实现下拉刷新和上拉加载(内含案例)
在前端开发中,上拉加载和下拉刷新常用于实现内容的动态加载,尤其在移动端的应用中。下面我将提供一个简单的示例和逻辑说明。 1. 逻辑说明: 下拉刷新: 用户向下拖动页面顶部,触发一个事件,刷新当前内容。需…...
Opencv第十一章——视频处理
1. 读取并显示摄像头视频 1.1 VideoCapture类 VideoCapture类提供了构造方法VideoCapture(),用于完成摄像头的初始化工作,其语法格式如下: capture cv2.VideoCapture(index) 参数说明: capture:要打开的摄像头视频。 index:摄像头设备索引。…...
Flutter 3.24 AAPT: error: resource android:attr/lStar not found.
在Android build,gradle下面,添加右边红框的代码: subprojects {afterEvaluate { project ->if (project.plugins.hasPlugin("com.android.application") ||project.plugins.hasPlugin("com.android.library")) {project.androi…...
C++——输入一个2*3的矩阵, 将这个矩阵向左旋转90度后输出。(要求:使用指针完成。)
没注释的源代码 #include <iostream> using namespace std; int main() { int a[2][3]; cout<<"请输入一个2*3的矩阵:"<<endl; for(int i0;i<2;i) { for(int j0;j<3;j) { cin>>a[i][j…...
AI芯片WT2605C赋能厨房家电,在线对话操控,引领智能烹饪新体验:尽享高效便捷生活
在智能家居的蓬勃发展中,智能厨电作为连接科技与生活的桥梁,正逐步渗透到每一个现代家庭的厨房中。蒸烤箱作为智能厨电的代表,以其丰富的功能和高效的性能,满足了人们对美食的多样化追求。然而,面对众多复杂的操作功能…...
Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
Caliper 负载(Workload)详细解析
Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...
