如何使用 libcurl 进行网页抓取

在这里插入图片描述

网页抓取是一种从网站提取数据的强大技术,它可以自动化诸如收集定价信息、监控内容更新或收集大型数据集等任务。libcurl 是 C++ 中最流行的网页抓取库之一,它是一个免费且开源的客户端 URL 传输库。它支持多种协议,如 HTTP、HTTPS、FTP 等,使其成为检索网络内容的理想选择。

libcurl 简介

libcurl 是一个强大的 C 库,用于发出 HTTP 请求,支持多种协议,如 HTTP、HTTPS、FTP 等等。它是一个灵活的工具,广泛应用于 C++ 应用程序中执行网络请求。

特性:

  • 多协议支持: HTTP、HTTPS、FTP、FTPS、SMTP 等。
  • 异步支持: 通过 CURLM 一次管理多个请求。
  • 错误处理: 提供详细的错误消息和状态代码。
  • 身份验证: 支持基本、摘要、NTLM、协商等。
  • Cookie 和会话: 可以轻松管理 Cookie 和会话信息。

先决条件

在使用 libcurl 之前,您必须:

  • 在您的系统上安装 libcurl
  • 在您的 C++ 代码中包含 curl/curl.h 头文件。

您可以在 Linux 上使用以下命令安装 libcurl:

sudo apt-get install libcurl4-openssl-dev

基本示例:发出 GET 请求

以下是如何使用 C++ 中的 libcurl 执行简单的 GET 请求:

#include <iostream>
#include <curl/curl.h>

static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp)
{
    ((std::string*)userp)->append((char*)contents, size * nmemb);
    return size * nmemb;
}

int main() {
    CURL* curl;
    CURLcode res;
    std::string readBuffer;

    curl_global_init(CURL_GLOBAL_DEFAULT);
    curl = curl_easy_init();
    
    if(curl) {
        curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/get");
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);

        res = curl_easy_perform(curl);
        if(res != CURLE_OK) {
            std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
        } else {
            std::cout << "Response: " << readBuffer << std::endl;
        }

        curl_easy_cleanup(curl);
    }
    curl_global_cleanup();
    
    return 0;
}

网页抓取示例:从 API 获取 JSON 数据

以下是一个从 API 获取数据并打印结果的示例:

#include <iostream>
#include <curl/curl.h>

static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp)
{
    ((std::string*)userp)->append((char*)contents, size * nmemb);
    return size * nmemb;
}

int main() {
    CURL* curl;
    CURLcode res;
    std::string readBuffer;

    curl_global_init(CURL_GLOBAL_DEFAULT);
    curl = curl_easy_init();

    if(curl) {
        curl_easy_setopt(curl, CURLOPT_URL, "https://jsonplaceholder.typicode.com/posts");
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);

        res = curl_easy_perform(curl);
        if(res != CURLE_OK) {
            std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
        } else {
            std::cout << "Response: " << readBuffer << std::endl;
        }

        curl_easy_cleanup(curl);
    }
    curl_global_cleanup();
    
    return 0;
}

使用 libcurl 处理代理

要通过 libcurl 将您的请求路由到代理服务器:

#include <iostream>
#include <curl/curl.h>

static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp)
{
    ((std::string*)userp)->append((char*)contents, size * nmemb);
    return size * nmemb;
}

int main() {
    CURL* curl;
    CURLcode res;
    std::string readBuffer;

    curl_global_init(CURL_GLOBAL_DEFAULT);
    curl = curl_easy_init();

    if(curl) {
        curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/ip");
        curl_easy_setopt(curl, CURLOPT_PROXY, "http://proxyserver:8080");
        curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, "username:password");
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);

        res = curl_easy_perform(curl);
        if(res != CURLE_OK) {
            std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
        } else {
            std::cout << "Response: " << readBuffer << std::endl;
        }

        curl_easy_cleanup(curl);
    }
    curl_global_cleanup();
    
    return 0;
}

使用 libcurl 处理 Cookie

libcurl 可以通过启用 COOKIEFILE 选项来管理 Cookie:

#include <iostream>
#include <curl/curl.h>

static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp)
{
    ((std::string*)userp)->append((char*)contents, size * nmemb);
    return size * nmemb;
}

int main() {
    CURL* curl;
    CURLcode res;
    std::string readBuffer;

    curl_global_init(CURL_GLOBAL_DEFAULT);
    curl = curl_easy_init();

    if(curl) {
        curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/cookies/set?name=value");
        curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "");
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);

        res = curl_easy_perform(curl);
        if(res != CURLE_OK) {
            std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
        } else {
            std::cout << "Response: " << readBuffer << std::endl;
        }

        curl_easy_cleanup(curl);
    }
    curl_global_cleanup();
    
    return 0;
}

高级用法:自定义标头和 POST 请求

要发送自定义标头或执行 libcurl 的 POST 请求:

#include <iostream>
#include <curl/curl.h>

static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp)
{
    ((std::string*)userp)->append((char*)contents, size * nmemb);
    return size * nmemb;
}

int main() {
    CURL* curl;
    CURLcode res;
    std::string readBuffer;
    
    curl_global_init(CURL_GLOBAL_DEFAULT);
    curl = curl_easy_init();

    if(curl) {
        struct curl_slist* headers = nullptr;
        headers = curl_slist_append(headers, "User-Agent: Mozilla/5.0");
        headers = curl_slist_append(headers, "Accept-Language: en-US,en;q=0.5");

        curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/post");
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "username=testuser&password=testpass");
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);

        res = curl_easy_perform(curl);
        if(res != CURLE_OK) {
            std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
        } else {
            std::cout << "Response: " << readBuffer << std::endl;
        }

        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
    }
    curl_global_cleanup();

    return 0;
}

示例:使用 CapSolver 和 libcurl (C++) 解决 ReCaptcha V3

在本示例中,我们将演示如何使用 C++ 中的 CapSolver: 和 libcurl 库解决 ReCaptcha V3。CapSolver API 允许轻松与 ReCaptcha 任务进行交互并检索解决方案。

在开始之前,确保您具备以下先决条件:

  • 在您的系统上安装 libcurl(在 Linux 上通过 sudo apt-get install libcurl4-openssl-dev 安装它)。
  • CapSolver API 密钥(将代码中的 "YourKey" 替换为您的实际密钥)。

以下是使用 CapSolver 解决 ReCaptcha V3 的分步指南:

第 1 步:创建任务

第一步是向 CapSolver 的 API 发送请求以创建解决 ReCaptcha 的任务。该任务包含网站 URL、网站密钥(来自目标页面)和特定页面操作等详细信息。

#include <iostream>
#include <string>
#include <curl/curl.h>
#include <json/json.h>

const std::string CAPSOLVER_KEY = "YourKey";
const std::string PAGE_URL = "https://antcpt.com/score_detector";
const std::string PAGE_KEY = "6LcR_okUAAAAAPYrPe-HK_0RULO1aZM15ENyM-Mf";
const std::string PAGE_ACTION = "homepage";

static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) {
    ((std::string*)userp)->append((char*)contents, size * nmemb);
    return size * nmemb;
}

std::string createTask(const std::string& url, const std::string& key, const std::string& action) {
    CURL* curl;
    CURLcode res;
    std::string readBuffer;

    curl = curl_easy_init();
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, "https://api.capsolver.com/createTask");
        curl_easy_setopt(curl, CURLOPT_POST, 1L);

        // JSON 负载用于任务创建
        Json::Value payload;
        payload["clientKey"] = CAPSOLVER_KEY;
        payload["task"]["type"] = "ReCaptchaV3TaskProxyLess";
        payload["task"]["websiteURL"] = url;
        payload["task"]["websiteKey"] = key;
        payload["task"]["pageAction"] = action;

        Json::StreamWriterBuilder writer;
        std::string requestData = Json::writeString(writer, payload);

        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, requestData.c_str());

        struct curl_slist* headers = nullptr;
        headers = curl_slist_append(headers, "Content-Type: application/json");
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);

        res = curl_easy_perform(curl);
        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
    }
    return readBuffer;
}

此函数向 CapSolver API 发送一个 POST 请求,其中包含必要的任务详细信息,并返回响应,其中将包含一个 taskId

第 2 步:检索 CAPTCHA 解决方案

创建任务后,您需要查询 CapSolver 的 API 以获取任务的结果,其中包含用于绕过 ReCaptcha 挑战的令牌。

std::string getTaskResult(const std::string& taskId) {
    CURL* curl;
    CURLcode res;
    std::string readBuffer;

    curl = curl_easy_init();
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, "https://api.capsolver.com/getTaskResult");
        curl_easy_setopt(curl, CURLOPT_POST, 1L);

        // JSON 负载用于获取任务结果
        Json::Value payload;
        payload["clientKey"] = CAPSOLVER_KEY;
        payload["taskId"] = taskId;

        Json::StreamWriterBuilder writer;
        std::string requestData = Json::writeString(writer, payload);

        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, requestData.c_str());

        struct curl_slist* headers = nullptr;
        headers = curl_slist_append(headers, "Content-Type: application/json");
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);

        do {
            readBuffer.clear();
            res = curl_easy_perform(curl);
            std::this_thread::sleep_for(std::chrono::seconds(5));
        } while (readBuffer.find("\"status\":\"ready\"") == std::string::npos);

        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
    }
    return readBuffer;
}

此函数会重复检查任务状态,直到任务准备就绪,然后返回 ReCaptcha 解决方案。

第 3 步:整合在一起

最后,以下是如何将这两个函数整合到您的主代码中:

int main() {
    std::cout << "Creating CAPTCHA task..." << std::endl;
    std::string taskResponse = createTask(PAGE_URL, PAGE_KEY, PAGE_ACTION);

    Json::CharReaderBuilder reader;
    Json::Value jsonResponse;
    std::string errors;
    std::istringstream taskStream(taskResponse);
    std::string taskId;

    if (Json::parseFromStream(reader, taskStream, &jsonResponse, &errors)) {
        taskId = jsonResponse["taskId"].asString();
        std::cout << "Task ID: " << taskId << std::endl;

        std::cout << "Retrieving CAPTCHA result..." << std::endl;
        std::string resultResponse = getTaskResult(taskId);

        Json::Value resultJson;
        std::istringstream resultStream(resultResponse);
        Json::parseFromStream(reader, resultStream, &resultJson, &errors);

        std::string token = resultJson["solution"]["gRecaptchaResponse"].asString();
        std::cout << "Token Solution: " << token << std::endl;
    } else {
        std::cerr << "Error parsing task response: " << errors << std::endl;
    }

    return 0;
}

这段代码将:

  1. 通过 CapSolver 创建一个 ReCaptcha 任务。
  2. 等待任务完成。
  3. 检索 ReCaptcha 令牌解决方案并将其打印出来。

附加代码

CapSolver: 上获取顶级验证码解决方案的 附加代码scrape。兑换后,每次充值后,您将获得额外的 5% 奖励,无限次。

在这里插入图片描述

结论

借助 libcurl,您可以在 C++ 应用程序中轻松处理 HTTP 请求。通过将其与 CapSolver 集成,您可以解决诸如 ReCaptcha V3 之类的验证码,并在您的请求中使用结果。


CapsolverCN官 方代理交流扣 群:497493756


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值