当前位置: 首页 > 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;面对众多复杂的操作功能…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中&#xff0c;iftop是网络管理的得力助手&#xff0c;能实时监控网络流量、连接情况等&#xff0c;帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

JavaScript基础-API 和 Web API

在学习JavaScript的过程中&#xff0c;理解API&#xff08;应用程序接口&#xff09;和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能&#xff0c;使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发&#xff0c;后来由Pivotal Software Inc.&#xff08;现为VMware子公司&#xff09;接管。RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写。广泛应用于各种分布…...

【Linux】Linux 系统默认的目录及作用说明

博主介绍&#xff1a;✌全网粉丝23W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋

随着工业以太网的发展&#xff0c;其高效、便捷、协议开放、易于冗余等诸多优点&#xff0c;被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口&#xff0c;具有实时性、开放性&#xff0c;使用TCP/IP和IT标准&#xff0c;符合基于工业以太网的…...

VSCode 没有添加Windows右键菜单

关键字&#xff1a;VSCode&#xff1b;Windows右键菜单&#xff1b;注册表。 文章目录 前言一、工程环境二、配置流程1.右键文件打开2.右键文件夹打开3.右键空白处打开文件夹 三、测试总结 前言 安装 VSCode 时没有注意&#xff0c;实际使用的时候发现 VSCode 在 Windows 菜单栏…...