使用libcurl获取经过gzip压缩的网页文件

转自:http://blog.csdn.net/zengraoli/article/details/13623237

有些网页是经过gzip压缩的,如果直接从web获取网页的源代码后,得到的是一些乱码,比如“http://www.fenzhi.com/”这个网站的


你就是保存到本地,得到的数据,也是一个乱码的,当然用cout输出的也会是乱码;


下面我们封装一下libcurl(参考了网上的代码,加入了自己的一些属性)


看看封装后类:

get_web_data_from_url.h:

  1. #ifndef __GETPAGEBYURL_INCLUDE_H__  
  2. #define __GETPAGEBYURL_INCLUDE_H__  
  3.   
  4.   
  5. #include "curl.h"  
  6. #include "string"  
  7. #include "iostream"  
  8. using namespace std;  
  9.   
  10.   
  11. class GetWebDataFromUrl  
  12. {  
  13. public:  
  14.     GetWebDataFromUrl(void);  
  15. public:  
  16.     ~GetWebDataFromUrl(void);  
  17. private:  
  18.     static string web_data_;  
  19.     static CURL *curl_;  
  20. private:  
  21.     static size_t WriteFunc(char *data, size_t size, size_t nmemb, string *writerData);  
  22. public:  
  23.     static bool Initialize(string curlopt_proxy_ip = "", string curlopt_proxy_port = "");  
  24.     static bool GetPage(const string& urlStr, string& page);  
  25.     static void Cleanup();  
  26.     static void GetPageContent(string page_link, string &page_content);  
  27. };  
  28.   
  29.   
  30. #endif // !__GETPAGEBYURL_INCLUDE_H__  



get_web_data_from_url.cpp:

  1. #include "StdAfx.h"  
  2. #include "get_web_data_from_url.h"  
  3.   
  4.   
  5. #define HAVE_LIBZ  
  6. #define HAVE_ZLIB_H  
  7.   
  8.   
  9. //static member variable define  
  10. string GetWebDataFromUrl::web_data_ = "";//当前保存的网页源码  
  11. CURL* GetWebDataFromUrl::curl_ = NULL;  
  12.   
  13.   
  14. GetWebDataFromUrl::GetWebDataFromUrl(void)  
  15. {  
  16. }  
  17.   
  18.   
  19. GetWebDataFromUrl::~GetWebDataFromUrl(void)  
  20. {  
  21. }  
  22.   
  23.   
  24. /************************************************************************/  
  25. /* 函数名:Initialize 
  26. /* 功     能: 初始化libcurl库 
  27. /* 返回值:成功,返回true;失败,返回false 
  28. /************************************************************************/  
  29. bool GetWebDataFromUrl::Initialize(string curlopt_proxy_ip, string curlopt_proxy_port)  
  30. {  
  31.     curl_global_init(CURL_GLOBAL_ALL);    
  32.     curl_ = curl_easy_init();  
  33.     struct curl_slist *chunk = NULL;  
  34.     if (curl_)  
  35.     {  
  36.         cout << curl_version() << endl;  
  37.         chunk = curl_slist_append(chunk, "Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");  
  38.         chunk = curl_slist_append(chunk, "Accept-Charset:GBK,utf-8;q=0.7,*;q=0.3");  
  39.         chunk = curl_slist_append(chunk, "Accept-Language:zh-TW,zh;q=0.8,en-US;q=0.6,en;q=0.4,zh-CN;q=0.2");  
  40.         chunk = curl_slist_append(chunk, "Connection:keep-alive");  
  41.         chunk = curl_slist_append(chunk, "Accept-Charset:GBK,utf-8;q=0.7,*;q=0.3");  
  42.         chunk = curl_slist_append(chunk, "Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");  
  43.         chunk = curl_slist_append(chunk, "Accept-Encoding:gzip,deflate,sdch");  
  44.         chunk = curl_slist_append(chunk, "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31");  
  45.         chunk = curl_slist_append(chunk, "Expect:");  
  46.           
  47.         if (!curlopt_proxy_ip.empty() && !curlopt_proxy_port.empty())  
  48.         {  
  49.             curl_easy_setopt(curl_, CURLOPT_PROXY, curlopt_proxy_ip.c_str());  
  50.             curl_easy_setopt(curl_, CURLOPT_PROXYPORT, std::atoi(curlopt_proxy_port.c_str()));  
  51.     //      curl_easy_setopt(m_curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);   
  52.         }  
  53.         curl_easy_setopt(curl_, CURLOPT_FOLLOWLOCATION, 1L);  
  54.         curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, WriteFunc);  
  55.         curl_easy_setopt(curl_, CURLOPT_WRITEDATA, &web_data_);  
  56.         curl_easy_setopt(curl_, CURLOPT_ACCEPT_ENCODING, "gzip");  
  57.         curl_easy_setopt(curl_, CURLOPT_HTTPHEADER, chunk);  
  58.     }  
  59.     else  
  60.     {  
  61.         MessageBoxA(NULL,"GetPageByURL::Initialize Failed!""GetPageByURL::Initialize", MB_ICONERROR);  
  62.         return false;  
  63.     }  
  64.     return true;  
  65. }  
  66.   
  67.   
  68. /************************************************************************/  
  69. /* 函数名:WriteFunc 
  70. /* 功  能: libcurl会调用这个标准的函数, 
  71. /*               size_t function( void *ptr, size_t size, size_t nmemb, void *userdata); 
  72. /*               以提供格式化网页数据的机会 
  73. /*               curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteFunc);  
  74. /* 返回值:返回buffer的大小 
  75. /************************************************************************/  
  76. size_t GetWebDataFromUrl::WriteFunc(char *data, size_t size, size_t nmemb, string *writerData)  
  77. {  
  78.     if (writerData == NULL)  
  79.         return 0;  
  80.     size_t len = size*nmemb;  
  81.     writerData->append(data, len);  
  82.   
  83.     return len;  
  84. }  
  85.   
  86.   
  87. /************************************************************************/  
  88. /* 函数名:GetPage 
  89. /* 功  能: 根据url,抓取对应的网页源码;使用了libcurl库 
  90. /* 返回值:成功,返回包含网页源码的字符串;失败,返回空字符串 
  91. /************************************************************************/  
  92. bool GetWebDataFromUrl::GetPage(const string& urlStr, //url字符串  
  93.                                 string& page              //输出参数,返回对应页面源码  
  94.                                 )  
  95. {  
  96.     _ASSERT("" != urlStr);  
  97.     if(!curl_)  
  98.     {  
  99.         MessageBoxA(NULL,"You must initialize curl first!""GetPageByURL", MB_ICONERROR);  
  100.         return false;  
  101.     }  
  102.   
  103.     web_data_.clear();  
  104.     curl_easy_setopt(curl_, CURLOPT_URL, urlStr.c_str());  
  105.     CURLcode res = curl_easy_perform(curl_);  
  106.     if(res != CURLE_OK)  
  107.     {  
  108.         MessageBoxA(NULL,"curl call false!""GetWebDataFromUrl::GetPage2", MB_ICONERROR);  
  109.         return false;  
  110.     }  
  111.     else  
  112.     {  
  113.         page = web_data_;  
  114.         return true;  
  115.     }  
  116. }  
  117.   
  118.   
  119. /************************************************************************/  
  120. /* 函数名:Cleanup 
  121. /* 功  能: 清理内存 
  122. /* 返回值:无 
  123. /************************************************************************/  
  124. void GetWebDataFromUrl::Cleanup()  
  125. {  
  126.     if(curl_)  
  127.     {  
  128.         /* always cleanup */  
  129.         curl_easy_cleanup(curl_);  
  130.         curl_ = NULL;  
  131.     }  
  132. }  
  133.   
  134.   
  135. void GetWebDataFromUrl::GetPageContent(string page_link, string &page_content)  
  136. {  
  137.     page_content = "";  
  138.     GetWebDataFromUrl::GetPage(page_link, page_content);  
  139. }  




这样,对于像“http://www.fenzhi.com/”那样的网站(始终进行gzip压缩),都能够正确获取到源代码了,其实主要是在初始化curl的时候,给了一个标志

curl_easy_setopt(curl_, CURLOPT_ACCEPT_ENCODING, "gzip");

这个标志,需要在编译curl的时候,假如zlib。要不然找不到这个标志



但是在cout到屏幕的时候,看到的还是乱码,那是因为cout使用的对汉字编码格式不同的缘故:




但是我们看到的输出到文件的部分已经是正确的了:




为了对比,把其中一行代码去掉,可以看到原始效果:

  1. // curl_easy_setopt(m_curl, CURLOPT_ACCEPT_ENCODING, "gzip");  





忘了,最好说一下我的对应版本:



目前的这一部分工程已经上传到我的资源中,对应的下载地址如下:

http://download.csdn.net/download/zengraoli/6474927


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值