文章详情
C++使用chromedriver完成浏览器自动化操作测试
Posted on 2024-10-03 06:03:16 by 主打一个C++
bb: 因项目需求,要获取某音直播间的实时数据,一堆坑🕳,总算爬出来~~~
大致看了一下chromedriver的功能还是非常庞大的,能实现的不能实现的都实现了。。。我只取一瓢~~~~
测试结果
测试环境:
windows操作系统 + C++ + curl.lib
资源:
1.chromedriver.exe 下载地址: https://sites.google.com/chromium.org/driver/downloads (尽量与浏览器版本对应)
2.谷歌的Chrome for Testing: https://googlechromelabs.github.io/chrome-for-testing/
我试用的130.0.6723.58版本 : https://storage.googleapis.com/chrome-for-testing-public/130.0.6723.58/win64/chrome-win64.zip
3.相关指令: https://chromium.googlesource.com/chromium/src/+/master/docs/chromedriver_status.md
初始化配置:CCurl.h (bb: 代码仅供测试)
为了方便,直接封装了两个函数,一个头文件调用方便随时扩展,Curl7.几版本以下貌似非线程安全,so
#pragma once
#ifndef CCURL_H
#define CCURL_H
#include <curl.h>
#pragma comment(lib, "libcurl")
class CCurl
{
CCurl() {
curl_global_init(CURL_GLOBAL_DEFAULT);
m_curl = curl_easy_init();
if (m_curl == nullptr) {
printf("Curl init failed!\n");
}
};
~CCurl() {
if (m_curl) {
curl_easy_cleanup(m_curl);
curl_global_cleanup();
}
};
public:
static CCurl* This() {
static CCurl instance;
return &instance;
}
int Excute(const char* _url,const char* _command) {
curl_easy_setopt(m_curl, CURLOPT_URL, _url);
curl_easy_setopt(m_curl, CURLOPT_CUSTOMREQUEST, _command);
CURLcode res = curl_easy_perform(m_curl);
if (res != CURLE_OK) {
std::cerr << "Excute failed: " << curl_easy_strerror(res) << std::endl;
return 3;
}
return 0;
}
int Post(const char* _url, const char* _postData, std::string* _readBuffer) {
_readBuffer->clear();
curl_easy_setopt(m_curl, CURLOPT_URL, _url);
curl_easy_setopt(m_curl, CURLOPT_POSTFIELDS, _postData);
// 设置回调函数以处理返回的数据
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, CCurl::WriteCallback);
// 将缓冲区传递给回调函数
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, _readBuffer);
// 设置请求头
//struct curl_slist* headers = NULL;
//headers = curl_slist_append(headers, "Accept: */*");
//curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, headers);
// 设置 Cookie
//curl_easy_setopt(m_curl, CURLOPT_COOKIE, "");
CURLcode res = curl_easy_perform(m_curl);
if (res != CURLE_OK) {
std::cerr << "Post failed: " << curl_easy_strerror(res) << std::endl;
return 5;
}
return 0;
}
private:
static size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* userp) {
size_t totalSize = size * nmemb;
userp->append((char*)contents, totalSize);
return totalSize;
}
private:
CURL* m_curl = nullptr;
};
#endif // !CCURL_H
启动配置:main.cpp
#include <iostream>
#include "CJson.h"
//#include "dy_tcp.h"
#include "CCurl.h"
//启动,默认为附加自身
int StartChromeProcess() {
printf("%s\n", __FUNCTION__);
std::string _cmdLine = DY_CHROME_FULL_PATH;
_cmdLine += " --port=";
_cmdLine += DY_CHROME_PORT;
bool _isHidden = false;
// 创建一个 STARTUPINFO 结构体实例
STARTUPINFOA si{ (DWORD)sizeof(si) };
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
ZeroMemory(&pi, sizeof(pi));
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOW;
if (_isHidden) {
si.wShowWindow = SW_HIDE;
}
// 启动cmd.exe
if (::CreateProcessA(
NULL,
(LPSTR)_cmdLine.c_str(), //参数
NULL, // 进程句柄不可继承
NULL, // 线程句柄不可继承
FALSE, // 不继承句柄
0, // 创建标志CREATE_NEW_CONSOLE
NULL, // 使用默认的环境变量
NULL, // 使用默认的当前目录
&si, // STARTUPINFO 结构体
&pi) // PROCESS_INFORMATION 结构体
) {
// 等待进程结束
//WaitForSingleObject(pi.hProcess, INFINITE);
// 关闭进程和线程句柄
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
else {
std::cerr << "Failed to start Chrome process: "<< GetLastError() << std::endl;
}
return 0;
}
//结束进程
bool TerminateProcessByName(DWORD _processId) {
printf("%s\n", __FUNCTION__);
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, _processId);
if (hProcess != NULL) {
// 强制结束进程
if (TerminateProcess(hProcess, 0)) {
return true;
}
CloseHandle(hProcess);
}
return false;
}
//打开一个网页
void openUrl(const std::string& session_id, const std::string& url, std::string* readBuffer) {
CURLcode res;
// 打开指定的 URL
std::string openUrl = DY_CHROME_HOST;
openUrl += ":";
openUrl += DY_CHROME_PORT;
openUrl += "/session/";
openUrl += session_id;
openUrl += "/url";
std::string postFields = "{"url": "" + url + ""}";
if (CCurl::This()->Post(openUrl.c_str(), postFields.c_str(), readBuffer) != 0) {
}
else {
std::cerr << "Response data: " << readBuffer << std::endl;
}
}
//执行js代码
void executeJs(const std::string& session_id, const std::string& jsCode, std::string* readBuffer) {
CURLcode res;
// 执行 JavaScript 代码
std::string executeJsUrl = DY_CHROME_HOST;
executeJsUrl += ":";
executeJsUrl += DY_CHROME_PORT;
executeJsUrl += "/session/";
executeJsUrl += session_id;
executeJsUrl += "/execute/sync";
std::string jsPostFields = "{"script":"" + jsCode + "","args":[]}";
if (CCurl::This()->Post(executeJsUrl.c_str(), jsPostFields.c_str(), readBuffer) != 0) {
}
else {
std::cerr << "Response data: " << readBuffer << std::endl;
}
}
//关闭浏览器窗口
void closeChromeDriver(const std::string& session_id) {
printf("%s\n",__FUNCTION__);
std::string closeWindowUrl = DY_CHROME_HOST;
closeWindowUrl += ":";
closeWindowUrl += DY_CHROME_PORT;
closeWindowUrl += "/session/";
closeWindowUrl += session_id;
CCurl::This()->Excute(closeWindowUrl.c_str(), "DELETE");
}
//启动chromeDirver
std::string StartChromeDriver() {
printf("%s\n", __FUNCTION__);
std::string session_id = "";
std::string readBuffer = ""; // 用于存储返回数据
// "--headless",
const char* postFields = R"({
"desiredCapabilities": {
"browserName": "chrome",
"goog:chromeOptions": {
"excludeSwitches": ["enable-automation"],
"args": [
"--window-size=1024,768",
"--disable-extensions",
"--disable-dev-shm-usage",
"--no-sandbox",
"--disable-setuid-sandbox",
"--disable-popup-blocking",
"--disable-notifications",
"--disable-print-preview",
"--disable-prompt-on-repost",
"--disable-desktop-notifications",
"--disable-device-discovery-notifications",
"--disable-features=site-per-process",
"--disable-sync",
"--disable-translate",
"--disable-save-password-bubble",
"--disable-single-click-autofill",
"--disable-infobars",
"--disable-background-timer-throttle",
"--disable-backgrounding-occluded-windows",
"--useAutomationExtension=false"
]
}
}
})";
std::string url = DY_CHROME_HOST;//"http://localhost:1900/session";
url += ":";
url += DY_CHROME_PORT;
url += "/session";
if (CCurl::This()->Post(url.c_str(), postFields, &readBuffer) != 0) {
}
else {
std::cerr << "Response data: " << readBuffer << std::endl; // 输出返回的数据
CJson json(&readBuffer);
session_id = json.getValue("sessionId").toString();
printf("sessionId=[%s]\n", session_id.c_str());
}
return session_id;
}
//启动浏览器
int main(int argc, char* argv[]) {
if (StartChromeProcess() == 0) {
std::string session_id = StartChromeDriver(); // 启动 `chromedriver`
if (session_id.empty()) {
std::cerr << "Failed to start ChromeDriver" << std::endl;
return 2;
}
std::string readBuffer = "";
openUrl(session_id, "https://live.douyin.com/963259834694", &readBuffer);
SetWindowTextA(GetConsoleWindow(), "Press Ctrl+Space to quit.");
//Sleep(3000);
//closeChromeDriver(session_id + "/window/");
}
printf("quit.\n");
return 0;
}
//至此完成!
*转载请注明出处:原文链接:https://cpp.vin/page/60.html