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

51 篇文章 4 订阅
17 篇文章 0 订阅

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


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


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


看看封装后类:

get_web_data_from_url.h:

#ifndef __GETPAGEBYURL_INCLUDE_H__
#define __GETPAGEBYURL_INCLUDE_H__


#include "curl.h"
#include "string"
#include "iostream"
using namespace std;


class GetWebDataFromUrl
{
public:
	GetWebDataFromUrl(void);
public:
	~GetWebDataFromUrl(void);
private:
	static string web_data_;
	static CURL *curl_;
private:
	static size_t WriteFunc(char *data, size_t size, size_t nmemb, string *writerData);
public:
	static bool Initialize(string curlopt_proxy_ip = "", string curlopt_proxy_port = "");
	static bool GetPage(const string& urlStr, string& page);
	static void Cleanup();
	static void GetPageContent(string page_link, string &page_content);
};


#endif // !__GETPAGEBYURL_INCLUDE_H__



get_web_data_from_url.cpp:

#include "StdAfx.h"
#include "get_web_data_from_url.h"


#define HAVE_LIBZ
#define HAVE_ZLIB_H


//static member variable define
string GetWebDataFromUrl::web_data_ = "";//当前保存的网页源码
CURL* GetWebDataFromUrl::curl_ = NULL;


GetWebDataFromUrl::GetWebDataFromUrl(void)
{
}


GetWebDataFromUrl::~GetWebDataFromUrl(void)
{
}


/************************************************************************/
/* 函数名:Initialize
/* 功	 能: 初始化libcurl库
/* 返回值:成功,返回true;失败,返回false
/************************************************************************/
bool GetWebDataFromUrl::Initialize(string curlopt_proxy_ip, string curlopt_proxy_port)
{
	curl_global_init(CURL_GLOBAL_ALL);  
	curl_ = curl_easy_init();
	struct curl_slist *chunk = NULL;
	if (curl_)
	{
		cout << curl_version() << endl;
		chunk = curl_slist_append(chunk, "Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
		chunk = curl_slist_append(chunk, "Accept-Charset:GBK,utf-8;q=0.7,*;q=0.3");
		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");
		chunk = curl_slist_append(chunk, "Connection:keep-alive");
		chunk = curl_slist_append(chunk, "Accept-Charset:GBK,utf-8;q=0.7,*;q=0.3");
		chunk = curl_slist_append(chunk, "Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
		chunk = curl_slist_append(chunk, "Accept-Encoding:gzip,deflate,sdch");
		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");
		chunk = curl_slist_append(chunk, "Expect:");
		
		if (!curlopt_proxy_ip.empty() && !curlopt_proxy_port.empty())
		{
			curl_easy_setopt(curl_, CURLOPT_PROXY, curlopt_proxy_ip.c_str());
			curl_easy_setopt(curl_, CURLOPT_PROXYPORT, std::atoi(curlopt_proxy_port.c_str()));
	//		curl_easy_setopt(m_curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); 
		}
		curl_easy_setopt(curl_, CURLOPT_FOLLOWLOCATION, 1L);
		curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, WriteFunc);
		curl_easy_setopt(curl_, CURLOPT_WRITEDATA, &web_data_);
		curl_easy_setopt(curl_, CURLOPT_ACCEPT_ENCODING, "gzip");
		curl_easy_setopt(curl_, CURLOPT_HTTPHEADER, chunk);
	}
	else
	{
		MessageBoxA(NULL,"GetPageByURL::Initialize Failed!", "GetPageByURL::Initialize", MB_ICONERROR);
		return false;
	}
	return true;
}


/************************************************************************/
/* 函数名:WriteFunc
/* 功  能: libcurl会调用这个标准的函数,
/*				 size_t function( void *ptr, size_t size, size_t nmemb, void *userdata);
/*				 以提供格式化网页数据的机会
/*				 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteFunc); 
/* 返回值:返回buffer的大小
/************************************************************************/
size_t GetWebDataFromUrl::WriteFunc(char *data, size_t size, size_t nmemb, string *writerData)
{
	if (writerData == NULL)
		return 0;
	size_t len = size*nmemb;
	writerData->append(data, len);

	return len;
}


/************************************************************************/
/* 函数名:GetPage
/* 功  能: 根据url,抓取对应的网页源码;使用了libcurl库
/* 返回值:成功,返回包含网页源码的字符串;失败,返回空字符串
/************************************************************************/
bool GetWebDataFromUrl::GetPage(const string& urlStr, //url字符串
								string& page			  //输出参数,返回对应页面源码
								)
{
	_ASSERT("" != urlStr);
	if(!curl_)
	{
		MessageBoxA(NULL,"You must initialize curl first!", "GetPageByURL", MB_ICONERROR);
		return false;
	}

	web_data_.clear();
	curl_easy_setopt(curl_, CURLOPT_URL, urlStr.c_str());
	CURLcode res = curl_easy_perform(curl_);
	if(res != CURLE_OK)
	{
		MessageBoxA(NULL,"curl call false!", "GetWebDataFromUrl::GetPage2", MB_ICONERROR);
		return false;
	}
	else
	{
		page = web_data_;
		return true;
	}
}


/************************************************************************/
/* 函数名:Cleanup
/* 功  能: 清理内存
/* 返回值:无
/************************************************************************/
void GetWebDataFromUrl::Cleanup()
{
	if(curl_)
	{
		/* always cleanup */
		curl_easy_cleanup(curl_);
		curl_ = NULL;
	}
}


void GetWebDataFromUrl::GetPageContent(string page_link, string &page_content)
{
	page_content = "";
	GetWebDataFromUrl::GetPage(page_link, page_content);
}




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

curl_easy_setopt(curl_, CURLOPT_ACCEPT_ENCODING, "gzip");

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



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




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




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

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





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



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

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


  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值