将cURL内容结果保存为C++中的字符串

Gre*_*ego 47 c++ curl

int main(void)
{
  CURL *curl;
  CURLcode res;

  curl = curl_easy_init();
  if(curl) {
    curl_easy_setopt(curl, CURLOPT_URL, "http://www.google.com");
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
    res = curl_easy_perform(curl);
    curl_easy_cleanup(curl);
  }
  _getch();
  return 0;
}

string contents = "";
Run Code Online (Sandbox Code Playgroud)

string contents ="";

我想将curl html内容的结果保存在字符串中,我该怎么做?这是一个愚蠢的问题,但不幸的是,我无法在CURL C++示例中找到任何地方感谢!

Joa*_*son 100

您将不得不使用CURLOPT_WRITEFUNCTION设置回写进行写入.我现在无法测试编译它,但函数应该看起来接近;

static std::string readBuffer;

static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
{ 
    size_t realsize = size * nmemb;
    readBuffer.append(contents, realsize);
    return realsize;
}
Run Code Online (Sandbox Code Playgroud)

然后通过这样做来调用它;

readBuffer.clear();
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
// ...other curl options
res = curl_easy_perform(curl);
Run Code Online (Sandbox Code Playgroud)

通话结束后,readBuffer应该有你的内容.

编辑:您可以使用CURLOPT_WRITEDATA传递缓冲区字符串而不是使其静态.在这种情况下,我只是为了简单而使其静态.一个好的页面(除了上面的链接示例)在这里是对选项的解释.

Edit2:根据要求,这是一个没有静态字符串缓冲区的完整工作示例;

#include <iostream>
#include <string>
#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(void)
{
  CURL *curl;
  CURLcode res;
  std::string readBuffer;

  curl = curl_easy_init();
  if(curl) {
    curl_easy_setopt(curl, CURLOPT_URL, "http://www.google.com");
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
    res = curl_easy_perform(curl);
    curl_easy_cleanup(curl);

    std::cout << readBuffer << std::endl;
  }
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 重要提示:如果您在应用程序的任何地方使用多个线程,则必须添加 curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L); 否则你会在没有解释的情况下得到段错误。 (2认同)

Uli*_*ler 5

在我的博客上,我发布了一个简单的包装类来执行此任务。

\n\n

使用示例:

\n\n
#include "HTTPDownloader.hpp"\n\nint main(int argc, char** argv) {\n    HTTPDownloader downloader;\n    std::string content = downloader.download("https://stackoverflow.com");\n    std::cout << content << std::endl;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是头文件:

\n\n
/**\n * HTTPDownloader.hpp\n *\n * A simple C++ wrapper for the libcurl easy API.\n *\n * Written by Uli K\xc3\xb6hler (techoverflow.net)\n * Published under CC0 1.0 Universal (public domain)\n */\n#ifndef HTTPDOWNLOADER_HPP\n#define HTTPDOWNLOADER_HPP\n\n#include <string>\n\n/**\n * A non-threadsafe simple libcURL-easy based HTTP downloader\n */\nclass HTTPDownloader {\npublic:\n    HTTPDownloader();\n    ~HTTPDownloader();\n    /**\n     * Download a file using HTTP GET and store in in a std::string\n     * @param url The URL to download\n     * @return The download result\n     */\n    std::string download(const std::string& url);\nprivate:\n    void* curl;\n};\n\n#endif  /* HTTPDOWNLOADER_HPP */\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是源代码:

\n\n
/**\n * HTTPDownloader.cpp\n *\n * A simple C++ wrapper for the libcurl easy API.\n *\n * Written by Uli K\xc3\xb6hler (techoverflow.net)\n * Published under CC0 1.0 Universal (public domain)\n */\n#include "HTTPDownloader.hpp"\n#include <curl/curl.h>\n#include <curl/easy.h>\n#include <curl/curlbuild.h>\n#include <sstream>\n#include <iostream>\nusing namespace std;\n\nsize_t write_data(void *ptr, size_t size, size_t nmemb, void *stream) {\n    string data((const char*) ptr, (size_t) size * nmemb);\n    *((stringstream*) stream) << data;\n    return size * nmemb;\n}\n\nHTTPDownloader::HTTPDownloader() {\n    curl = curl_easy_init();\n}\n\nHTTPDownloader::~HTTPDownloader() {\n    curl_easy_cleanup(curl);\n}\n\nstring HTTPDownloader::download(const std::string& url) {\n    curl_easy_setopt(curl, CURLOPT_URL, url.c_str());\n    /* example.com is redirected, so we tell libcurl to follow redirection */\n    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);\n    curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); //Prevent "longjmp causes uninitialized stack frame" bug\n    curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "deflate");\n    std::stringstream out;\n    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);\n    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &out);\n    /* Perform the request, res will get the return code */\n    CURLcode res = curl_easy_perform(curl);\n    /* Check for errors */\n    if (res != CURLE_OK) {\n        fprintf(stderr, "curl_easy_perform() failed: %s\\n",\n                curl_easy_strerror(res));\n    }\n    return out.str();\n}\n
Run Code Online (Sandbox Code Playgroud)\n


Mar*_*and 5

使用“新”C++11 lambda 功能,只需几行代码即可完成此操作。

#ifndef WIN32 #define __stdcall "" #endif //For compatibility with both Linux and Windows
std::string resultBody { };
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resultBody);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, static_cast<size_t (__stdcall *)(char*, size_t, size_t, void*)>(
    [](char* ptr, size_t size, size_t nmemb, void* resultBody){
        *(static_cast<std::string*>(resultBody)) += std::string {ptr, size * nmemb};
        return size * nmemb;
    }
));

CURLcode curlResult = curl_easy_perform(curl);
std::cout << "RESULT BODY:\n" << resultBody << std::endl;
// Cleanup etc
Run Code Online (Sandbox Code Playgroud)

请注意,需要 __stdcall 强制转换来遵守 C 调用约定(cURL 是一个 C 库)