当前位置: 首页 > news >正文

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&#xff0c;使用JSON进行数据传输&#xff0c;定义了client与driver之间的通信标准。无论client的实现语言&#xff08;如Java或C#&#xff09;&#xff0c;都能通过协议中的endpoints准确指示driver执行各种操作&#xff0c;覆盖了Selenium的所有功…...

WeChat_DevTools 断点调试方法总结

新建工程&#xff0c;以小程序 login 调试为例&#xff0c;代码如下&#xff1a; // 登录wx.login({success: res > {// 发送 res.code 到后台换取 openId, sessionKey, unionIddebugger;resThis this;wx.showModal({title: 登录成功,content: res.code res.code,comple…...

水波荡漾效果+渲染顺序+简单UI绘制

创建场景及布置 创建新场景Main,在Main场景中创建一个plane物体&#xff0c;命名为WaterWavePla,具体数值及层级面板排布如下&#xff1a; 编写脚本 创建一个文件夹&#xff0c;用于存放脚本&#xff0c;命名Scripts,创建一个子文件夹Effect,存放特效相关脚本&#xff0c;创建…...

深度学习中的结构化概率模型 - 使用图来描述模型结构篇

序言 在深度学习的探索之路上&#xff0c;结构化概率模型以其独特的视角和强大的表达能力&#xff0c;成为了研究复杂数据关系的重要工具。这一模型的核心在于其巧妙地利用图来描述模型结构&#xff0c;将随机变量间的复杂交互关系可视化、结构化。图的引入&#xff0c;不仅为…...

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 请求&#xff1f;GET 请求POST 请求指定 GET/POST 方法类型 2. Postman 介绍1. 创建请求2. 传参介绍1. 普通传参2. form-data3. x-www-form-urlencoded form 表单&#xff0c;对应…...

【深度学习基础模型】回声状态网络(Echo State Networks, ESN)详细理解并附实现代码。

【深度学习基础模型】回声状态网络&#xff08;Echo State Networks, ESN&#xff09;详细理解并附实现代码。 【深度学习基础模型】回声状态网络&#xff08;Echo State Networks, ESN&#xff09;详细理解并附实现代码。 文章目录 【深度学习基础模型】回声状态网络&#xf…...

Redis的基础认识与在ubuntu上的安装教程

来自Redis的自我介绍 我是Redis&#xff0c;一个中间件&#xff0c;职责是把数据存储在内存上&#xff0c;因此可以作为数据库、缓存、消息队列等场景使用。由于可以把数据存储在内存上&#xff0c;因此江湖人称快枪手 1.redis的功能特性 &#xff08;1&#xff09;数据在内存…...

鸿蒙harmonyos next flutter混合开发之ohos工程引用 har 文件

创建鸿蒙原生工程MyApplication。创建flutter module&#xff0c;生成har文件&#xff0c;并且将flutter module中.ohos文件entryability/EntryAbility.ets、pages/Index.ets分别替换MyApplication中的。 # 1. 创建 flutter子模块工程 flutter create -t module my_flutter_…...

react-问卷星项目(5)

实战 路由 路由设计&#xff0c;网址和页面的关系&#xff0c;就是从业务上分析需要哪些页面哪些页面内容可以抽离&#xff0c;业务流程要有入有出增加页面和Layout模版&#xff0c;模版就是抽离页面公共部分&#xff0c;比如都有顶部或者左侧导航&#xff0c;直接上代码&…...

08.useInterval

在 React 应用中,实现定时器功能通常需要使用 setInterval() 和 clearInterval(),这可能会导致代码复杂和难以维护。useInterval 钩子提供了一种声明式的方法来实现定时器功能,使得定时器的管理更加简单和直观。这个自定义钩子不仅简化了定时器的使用,还解决了一些常见的定…...

【Android 源码分析】Activity生命周期之onDestroy

忽然有一天&#xff0c;我想要做一件事&#xff1a;去代码中去验证那些曾经被“灌输”的理论。                                                                                  – 服装…...

增强现实中的物体识别与跟踪

增强现实&#xff08;AR&#xff09;中的物体识别与跟踪是实现虚拟内容与现实世界无缝融合的关键技术。以下是该领域的主要技术和方法概述&#xff1a; 1. 物体识别 1.1 特征提取 SIFT、SURF、ORB&#xff1a;传统的特征提取算法用于识别图像中的关键点并生成描述符&#xf…...

移动端实现下拉刷新和上拉加载(内含案例)

在前端开发中&#xff0c;上拉加载和下拉刷新常用于实现内容的动态加载&#xff0c;尤其在移动端的应用中。下面我将提供一个简单的示例和逻辑说明。 1. 逻辑说明&#xff1a; 下拉刷新&#xff1a; 用户向下拖动页面顶部&#xff0c;触发一个事件&#xff0c;刷新当前内容。需…...

Opencv第十一章——视频处理

1. 读取并显示摄像头视频 1.1 VideoCapture类 VideoCapture类提供了构造方法VideoCapture(),用于完成摄像头的初始化工作&#xff0c;其语法格式如下&#xff1a; capture cv2.VideoCapture(index) 参数说明&#xff1a; capture:要打开的摄像头视频。 index:摄像头设备索引。…...

Flutter 3.24 AAPT: error: resource android:attr/lStar not found.

在Android build,gradle下面&#xff0c;添加右边红框的代码&#xff1a; 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赋能厨房家电,在线对话操控,引领智能烹饪新体验:尽享高效便捷生活

在智能家居的蓬勃发展中&#xff0c;智能厨电作为连接科技与生活的桥梁&#xff0c;正逐步渗透到每一个现代家庭的厨房中。蒸烤箱作为智能厨电的代表&#xff0c;以其丰富的功能和高效的性能&#xff0c;满足了人们对美食的多样化追求。然而&#xff0c;面对众多复杂的操作功能…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)

说明&#xff1a; 想象一下&#xff0c;你正在用eNSP搭建一个虚拟的网络世界&#xff0c;里面有虚拟的路由器、交换机、电脑&#xff08;PC&#xff09;等等。这些设备都在你的电脑里面“运行”&#xff0c;它们之间可以互相通信&#xff0c;就像一个封闭的小王国。 但是&#…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

数据库分批入库

今天在工作中&#xff0c;遇到一个问题&#xff0c;就是分批查询的时候&#xff0c;由于批次过大导致出现了一些问题&#xff0c;一下是问题描述和解决方案&#xff1a; 示例&#xff1a; // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称&#xff1a;Apache Flink REST API 任意文件读取漏洞CVE编号&#xff1a;CVE-2020-17519CVSS评分&#xff1a;7.5影响版本&#xff1a;Apache Flink 1.11.0、1.11.1、1.11.2修复版本&#xff1a;≥ 1.11.3 或 ≥ 1.12.0漏洞类型&#xff1a;路径遍历&#x…...

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要&#xff1a; 近期&#xff0c;在使用较新版本的OpenSSH客户端连接老旧SSH服务器时&#xff0c;会遇到 "no matching key exchange method found"​, "n…...