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

9bfwbjaz  于 2023-08-09  发布在  其他
关注(0)|答案(8)|浏览(208)
  1. int main(void)
  2. {
  3. CURL *curl;
  4. CURLcode res;
  5. curl = curl_easy_init();
  6. if(curl) {
  7. curl_easy_setopt(curl, CURLOPT_URL, "http://www.google.com");
  8. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
  9. curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
  10. res = curl_easy_perform(curl);
  11. curl_easy_cleanup(curl);
  12. }
  13. _getch();
  14. return 0;
  15. }
  16. string contents = "";

字符串
我想将curl html内容的结果保存为字符串,该如何操作?这是一个愚蠢的问题,但不幸的是,我在C++的cURL示例中找不到任何地方,谢谢!

7uhlpewt

7uhlpewt1#

您必须使用CURLOPT_WRITEFUNCTION来设置写入回调。我现在还不能测试编译这个函数,但是这个函数看起来应该很接近;

  1. static std::string readBuffer;
  2. static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
  3. {
  4. size_t realsize = size * nmemb;
  5. readBuffer.append(contents, realsize);
  6. return realsize;
  7. }

字符串
然后通过做来调用它;

  1. readBuffer.clear();
  2. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
  3. // ...other curl options
  4. res = curl_easy_perform(curl);


调用后,readBuffer应该有您的内容。
编辑:您可以使用CURLOPT_WRITEDATA来传递缓冲区字符串,而不是使其成为静态的。在本例中,为了简单起见,我将其设置为静态。here是一个很好的页面(除了上面的链接示例),它解释了这些选项。
Edit 2:按照要求,这里有一个没有静态字符串缓冲区的完整工作示例;

  1. #include <iostream>
  2. #include <string>
  3. #include <curl/curl.h>
  4. static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
  5. {
  6. ((std::string*)userp)->append((char*)contents, size * nmemb);
  7. return size * nmemb;
  8. }
  9. int main(void)
  10. {
  11. CURL *curl;
  12. CURLcode res;
  13. std::string readBuffer;
  14. curl = curl_easy_init();
  15. if(curl) {
  16. curl_easy_setopt(curl, CURLOPT_URL, "http://www.google.com");
  17. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
  18. curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
  19. res = curl_easy_perform(curl);
  20. curl_easy_cleanup(curl);
  21. std::cout << readBuffer << std::endl;
  22. }
  23. return 0;
  24. }

展开查看全部
s8vozzvw

s8vozzvw2#

在我的博客上,我有一个简单的 Package 器类published来执行这个任务。
使用示例:

  1. #include "HTTPDownloader.hpp"
  2. int main(int argc, char** argv) {
  3. HTTPDownloader downloader;
  4. std::string content = downloader.download("https://stackoverflow.com");
  5. std::cout << content << std::endl;
  6. }

字符串
下面是头文件:

  1. /**
  2. * HTTPDownloader.hpp
  3. *
  4. * A simple C++ wrapper for the libcurl easy API.
  5. *
  6. * Written by Uli Köhler (techoverflow.net)
  7. * Published under CC0 1.0 Universal (public domain)
  8. */
  9. #ifndef HTTPDOWNLOADER_HPP
  10. #define HTTPDOWNLOADER_HPP
  11. #include <string>
  12. /**
  13. * A non-threadsafe simple libcURL-easy based HTTP downloader
  14. */
  15. class HTTPDownloader {
  16. public:
  17. HTTPDownloader();
  18. ~HTTPDownloader();
  19. /**
  20. * Download a file using HTTP GET and store in in a std::string
  21. * @param url The URL to download
  22. * @return The download result
  23. */
  24. std::string download(const std::string& url);
  25. private:
  26. void* curl;
  27. };
  28. #endif /* HTTPDOWNLOADER_HPP */


下面是源代码:

  1. /**
  2. * HTTPDownloader.cpp
  3. *
  4. * A simple C++ wrapper for the libcurl easy API.
  5. *
  6. * Written by Uli Köhler (techoverflow.net)
  7. * Published under CC0 1.0 Universal (public domain)
  8. */
  9. #include "HTTPDownloader.hpp"
  10. #include <curl/curl.h>
  11. #include <curl/easy.h>
  12. #include <curl/curlbuild.h>
  13. #include <sstream>
  14. #include <iostream>
  15. using namespace std;
  16. size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream) {
  17. string data((const char*) ptr, (size_t) size * nmemb);
  18. *((stringstream*) stream) << data;
  19. return size * nmemb;
  20. }
  21. HTTPDownloader::HTTPDownloader() {
  22. curl = curl_easy_init();
  23. }
  24. HTTPDownloader::~HTTPDownloader() {
  25. curl_easy_cleanup(curl);
  26. }
  27. string HTTPDownloader::download(const std::string& url) {
  28. curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
  29. /* example.com is redirected, so we tell libcurl to follow redirection */
  30. curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
  31. curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); //Prevent "longjmp causes uninitialized stack frame" bug
  32. curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "deflate");
  33. std::stringstream out;
  34. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
  35. curl_easy_setopt(curl, CURLOPT_WRITEDATA, &out);
  36. /* Perform the request, res will get the return code */
  37. CURLcode res = curl_easy_perform(curl);
  38. /* Check for errors */
  39. if (res != CURLE_OK) {
  40. fprintf(stderr, "curl_easy_perform() failed: %s\n",
  41. curl_easy_strerror(res));
  42. }
  43. return out.str();
  44. }

展开查看全部
polkgigr

polkgigr3#

使用“新”的C++11 lambda功能,这可以在几行代码中完成。

  1. #ifndef WIN32 #define __stdcall "" #endif //For compatibility with both Linux and Windows
  2. std::string resultBody { };
  3. curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resultBody);
  4. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, static_cast<size_t (__stdcall *)(char*, size_t, size_t, void*)>(
  5. [](char* ptr, size_t size, size_t nmemb, void* resultBody){
  6. *(static_cast<std::string*>(resultBody)) += std::string {ptr, size * nmemb};
  7. return size * nmemb;
  8. }
  9. ));
  10. CURLcode curlResult = curl_easy_perform(curl);
  11. std::cout << "RESULT BODY:\n" << resultBody << std::endl;
  12. // Cleanup etc

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

展开查看全部
lmyy7pcs

lmyy7pcs4#

这可能不会立即起作用,但应该给予你一个想法:

  1. #include <string>
  2. #include <curl.h>
  3. #include <stdio.h>
  4. size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) {
  5. size_t written;
  6. written = fwrite(ptr, size, nmemb, stream);
  7. return written;
  8. }
  9. int main() {
  10. std::string tempname = "temp";
  11. CURL *curl;
  12. CURLcode res;
  13. curl = curl_easy_init();
  14. if(curl) {
  15. FILE *fp = fopen(tempname.c_str(),"wb");
  16. curl_easy_setopt(curl, CURLOPT_URL, "http://www.google.com");
  17. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
  18. curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
  19. res = curl_easy_perform(curl);
  20. curl_easy_cleanup(curl);
  21. fclose(fp);
  22. fp = fopen(tempname.c_str(),"rb");
  23. fseek (fp , 0 , SEEK_END);
  24. long lSize = ftell (fp);
  25. rewind(fp);
  26. char *buffer = new char[lSize+1];
  27. fread (buffer, 1, lSize, fp);
  28. buffer[lSize] = 0;
  29. fclose(fp);
  30. std::string content(buffer);
  31. delete [] buffer;
  32. }
  33. }

字符串

展开查看全部
t0ybt7op

t0ybt7op5#

给出了一个有用但简单的解决方案,它重载了std::ostream::operator<<

  1. #include <ostream>
  2. #include <curl/curl.h>
  3. size_t curlCbToStream (
  4. char * buffer,
  5. size_t nitems,
  6. size_t size,
  7. std::ostream * sout
  8. )
  9. {
  10. *sout << buffer;
  11. return nitems * size;
  12. }
  13. std::ostream & operator<< (
  14. std::ostream & sout,
  15. CURL * request
  16. )
  17. {
  18. ::curl_easy_setopt(request, CURLOPT_WRITEDATA, & sout);
  19. ::curl_easy_setopt(request, CURLOPT_WRITEFUNCTION, curlCbToStream);
  20. ::curl_easy_perform(request);
  21. return sout;
  22. }

字符串
所采用方法的可能缺点可能是:

  1. typedef void CURL;


这意味着它涵盖了所有已知的指针类型。

展开查看全部
nhaq1z21

nhaq1z216#

基于@JoachimIsaksson的回答,这里是一个更详细的输出,它处理内存不足,并对curl的最大输出有限制(因为CURLOPT_MAXFILESIZE仅基于头信息而不是传输的实际大小)。

  1. #DEFINE MAX_FILE_SIZE = 10485760 //10 MiB
  2. size_t curl_to_string(void *ptr, size_t size, size_t count, void *stream)
  3. {
  4. if(((string*)stream)->size() + (size * count) > MAX_FILE_SIZE)
  5. {
  6. cerr<<endl<<"Could not allocate curl to string, output size (current_size:"<<((string*)stream)->size()<<"bytes + buffer:"<<(size * count) << "bytes) would exceed the MAX_FILE_SIZE ("<<MAX_FILE_SIZE<<"bytes)";
  7. return 0;
  8. }
  9. int retry=0;
  10. while(true)
  11. {
  12. try{
  13. ((string*)stream)->append((char*)ptr, 0, size*count);
  14. break;// successful
  15. }catch (const std::bad_alloc&) {
  16. retry++;
  17. if(retry>100)
  18. {
  19. cerr<<endl<<"Could not allocate curl to string, probably not enough memory, aborting after : "<<retry<<" tries at 10s apart";
  20. return 0;
  21. }
  22. cerr<<endl<<"Could not allocate curl to string, probably not enough memory, sleeping 10s, try:"<<retry;
  23. sleep(10);
  24. }
  25. }
  26. return size*count;
  27. }

字符串

展开查看全部
hjzp0vay

hjzp0vay7#

我将Joachim Isaksson的答案与CURLOPT_WRITEFUNCTION的现代C++适配一起使用。
没有C风格强制转换的编译器的唠叨。

  1. static auto WriteCallback(char* ptr, size_t size, size_t nmemb, void* userdata) -> size_t {
  2. static_cast<string*>(userdata)->append(ptr, size * nmemb);
  3. return size * nmemb;
  4. }

字符串

o2gm4chl

o2gm4chl8#

这里有一个完整的例子,如何使用curl将网站的内容放入C++中的std::string。
编译时不要忘记标志-lcurl。

  1. /**
  2. *
  3. */
  4. ////////////////////////////////////////////////////////////////////////////////
  5. // Includes - default libraries - C++
  6. ////////////////////////////////////////////////////////////////////////////////
  7. #include <iostream>
  8. #include <string>
  9. #include <sstream> // for ostringstream
  10. #include <memory>
  11. ////////////////////////////////////////////////////////////////////////////////
  12. // Includes - others libraries - C++
  13. ////////////////////////////////////////////////////////////////////////////////
  14. #include <curl/curl.h>
  15. ////////////////////////////////////////////////////////////////////////////////
  16. // show function
  17. ////////////////////////////////////////////////////////////////////////////////
  18. std::string
  19. args_to_str(const std::ostringstream& os)
  20. {
  21. return os.str();
  22. }
  23. template<typename T, typename ... Args>
  24. std::string
  25. args_to_str(std::ostringstream& os, const T val, const Args ... args)
  26. {
  27. os << val;
  28. return args_to_str(os, args ...);
  29. }
  30. template<typename ... Args>
  31. void
  32. show(const Args ... args)
  33. {
  34. std::ostringstream os;
  35. std::cout << args_to_str(os, args ...);
  36. }
  37. ////////////////////////////////////////////////////////////////////////////////
  38. // headers
  39. ////////////////////////////////////////////////////////////////////////////////
  40. template<typename ... Args>
  41. void error(const Args ... args);
  42. size_t curl_to_string(void *ptr, size_t size, size_t nmemb, void *data);
  43. std::string get_content_from_website(CURL* curl, const std::string& url);
  44. void curl_free(CURL *curl);
  45. ////////////////////////////////////////////////////////////////////////////////
  46. // main
  47. ////////////////////////////////////////////////////////////////////////////////
  48. int
  49. main()
  50. {
  51. ////////////////////////////////////////////////////////////////////////////////
  52. // init libcurl
  53. ////////////////////////////////////////////////////////////////////////////////
  54. std::shared_ptr<CURL> curl (curl_easy_init(), curl_free);
  55. if(!curl.get()) error("cannot initialize CURL.");
  56. curl_easy_setopt(curl.get(), CURLOPT_VERBOSE, 1L);
  57. ////////////////////////////////////////////////////////////////////////////////
  58. // site that will be fetched
  59. ////////////////////////////////////////////////////////////////////////////////
  60. const std::string url = "https://www.fundsexplorer.com.br/funds/knsc11"; // put your website here
  61. ////////////////////////////////////////////////////////////////////////////////
  62. // fetch the content of the site
  63. ////////////////////////////////////////////////////////////////////////////////
  64. const std::string site = get_content_from_website(curl.get(), url);
  65. ////////////////////////////////////////////////////////////////////////////////
  66. // print the result
  67. ////////////////////////////////////////////////////////////////////////////////
  68. show(site);
  69. return 0;
  70. }
  71. ////////////////////////////////////////////////////////////////////////////////
  72. // functions
  73. ////////////////////////////////////////////////////////////////////////////////
  74. template<typename ... Args>
  75. void
  76. error(const Args ... args)
  77. {
  78. show(args ...);
  79. abort();
  80. }
  81. std::string
  82. get_content_from_website(CURL* curl, const std::string& url)
  83. {
  84. CURLcode res;
  85. res = curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
  86. if(res != CURLE_OK) error("Cannot set curl url.\n");
  87. res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_to_string);
  88. if(res != CURLE_OK) error("Cannot copy the C_STR to C++ string.\n");
  89. std::string result;
  90. res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, &result);
  91. if(res != CURLE_OK) error("Cannot set the curl write data.\n");
  92. res = curl_easy_perform(curl);
  93. if(res != CURLE_OK) error("Cannot perform curl.\n");
  94. return result;
  95. }
  96. size_t curl_to_string(void *ptr, size_t size, size_t nmemb, void *data)
  97. {
  98. std::string* str = static_cast<std::string*>(data);
  99. char* sptr = static_cast<char*>(ptr);
  100. size_t total = size * nmemb;
  101. const auto str_old_size = (*str).size();
  102. (*str).resize(str_old_size + total);
  103. for(size_t x = 0; x < total; ++x)
  104. {
  105. (*str)[str_old_size + x] = sptr[x];
  106. }
  107. return total;
  108. }
  109. void
  110. curl_free(CURL *curl)
  111. {
  112. curl_easy_cleanup(curl);
  113. curl = NULL;
  114. curl_global_cleanup();
  115. }

字符串

展开查看全部

相关问题