【转】如何在Windows+VS2005使用最新静态libcurl 7.35.0获取网页数据,支持HTTPS

地址: http://blog.csdn.net/hujkay
作者:Jekkay Hu([email protected])
关键词:Windows,curl,ssl,  visual c++ 2005, libcurl, https,网页抓取
时间: 2014/2/18

1. 概述

由于Curl提供强大的网络功能,支持HTTP,HTTPS, DICT, FILE, FTP, FTPS, Gopher, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMTP, SMTPS, Telnet ,TFTP等,已成为应用最为广泛的轻量级网络库之一。libCurl支持Windows,但如果在Win 平台使用VC开发的话,则需要下载msvc的版本,其下载地址是:http://curl.haxx.se/download/,如:libcurl-7.19.3-win32-ssl-msvc.zip。

目前Curl的的最新版本已经是7.35.0,但是官网提供的msvc的版本仍然是2009年2月发布的7.19.3版本,而且还没有含静态openssl的lib,这就意味写个小exe程序的话,还得打包好几个Openssl DLL进去,挺麻烦的,所以我就重新编译了一个含Openssl静态库,这个库算是我编译的最大的库了,达到25M,下载地址:

[plain] view plain copy

print?

  1. 已编译好含SSL的静态libcurl 7.35.0[VC2005].zip
  2. http://download.csdn.net/detail/hujkay/6931345

2. 使用

我以MFC Dialog based工程为例,介绍如何在Windons+VC2005上使用libcurl 7.35.0静态库。

2.1. 创建工程

打开Visual studio 2005,直接创建一个MFC工程,工程类型选择基于对话框[Dialog based]的就行,编码方式取消Unicode,这样就可以使用ANSI编码.

2.2  配置工程属性

右键工程属性,设置Curl的头文件目录路径,如下图:

配置库的链接方式和编码方式,如下图:

配置Runtime library,Debug模式为/MTD,Rlease模式为/MT

然后在Preprocesser里面添加预订义宏CURL_STATICLIB,如下图:

Debug模式和Release模式,配置的内容是一样的。

然后在stdafx.h文件最后面,添加如下代码:

[cpp] view plain copy

print?

  1. //// 添加CURL库
  2. #include <curl/curl.h>
  3. //// 带SSL的静态链接库
  4. #ifdef _DEBUG
  5. #pragma message("======编译======[DEBUG] CURL库=====")
  6. #pragma comment(lib,"libcurld.lib")
  7. #else
  8. #pragma message("======编译======[Release] CURL库=====")
  9. #pragma comment(lib,"libcurl.lib")
  10. #endif
  11. #pragma comment(lib,"wldap32.lib")
  12. #pragma comment(lib,"ws2_32.lib")

2.3  封装Curl库访问

为了使得Curl访问更加方便,我简单封装了一下Curl的访问类,代码如下:

VVCurl.h的源码如下:

[cpp] view plain copy

print?

  1. #pragma once
  2. #include <string>
  3. enum CURL_TYPE {CURL_GET=1,CURL_POST=2};
  4. class CVVCurl
  5. {
  6. public:
  7. CVVCurl(void);
  8. ~CVVCurl(void);
  9. BOOL            Init(CString strProxyAddr=_T(""),INT nPort=80) ;
  10. // 释放资源
  11. void            Release();
  12. // 打开指定的网页
  13. BOOL            OpenURL(std::string strURL,CURL_TYPE ntype = CURL_GET);
  14. BOOL            OpenURL(std::string strURL,std::string strPostData,CURL_TYPE ntype = CURL_POST);
  15. // 获取网页内容
  16. const char *    GetHeadContent() { return m_headcontent.c_str() ;} ;
  17. size_t          GetHeadContentLength() { return m_headcontent.size() ;} ;
  18. const char *    GetBodyContent() { return m_bodycontent.c_str() ;} ;
  19. size_t          GetBodyContentLength() { return m_bodycontent.size() ;} ;
  20. protected:
  21. BOOL            InitCurlHandle() ;
  22. BOOL            ReleaseCurlHandle() ;
  23. BOOL            DeleteCookieFile() ;
  24. BOOL            SetCurlHandleOpt() ;
  25. protected:
  26. // 句柄
  27. CURL *              m_pcurl;
  28. // 获取的内容
  29. std::string         m_headcontent ;
  30. std::string         m_bodycontent ;
  31. std::string         m_debugcontent ;
  32. // agent
  33. std::string         m_agent ;
  34. // cookie
  35. std::string         m_cookiepath ;
  36. // proxy
  37. std::string         m_strProxyServer ;
  38. // port
  39. int                 m_nPort ;
  40. };

VVCurl.cpp的源码如下:

[cpp] view plain copy

print?

  1. #include "StdAfx.h"
  2. #include "VVCurl.h"
  3. //#include "../include/Util.h"
  4. /*
  5. ptr是指向存储数据的指针,
  6. size是每个块的大小,
  7. nmemb是指块的数目,
  8. stream是用户参数。
  9. 所以根据以上这些参数的信息可以知道,ptr中的数据的总长度是size*nmemb
  10. */
  11. static size_t call_wirte_func(const char *ptr, size_t size, size_t nmemb, std::string *stream)
  12. {
  13. size_t len  = size * nmemb;
  14. stream->append(ptr, len);
  15. return len;
  16. }
  17. // 返回http header回调函数
  18. static size_t header_callback(const char  *ptr, size_t size, size_t nmemb, std::string *stream)
  19. {
  20. size_t len  = size * nmemb;
  21. stream->append(ptr, len);
  22. return len;
  23. }
  24. static int debug_callback (CURL * pcurl, curl_infotype ntype, char * ptr, size_t size, std::string  * stream)
  25. {
  26. int len  = (int)size;
  27. stream->append(ptr, len);
  28. return len;
  29. }
  30. CVVCurl::CVVCurl(void)
  31. {
  32. m_pcurl = NULL ;
  33. m_agent = _T("Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.66 Safari/537.36 LBBROWSER") ;
  34. m_cookiepath = _T("cookie.txt") ; //CUtil::GetRandTempPath(_T("_cookie.txt"));
  35. }
  36. CVVCurl::~CVVCurl(void)
  37. {
  38. Release() ;
  39. }
  40. BOOL CVVCurl::Init(CString strProxyAddr,INT nPort)
  41. {
  42. m_nPort = nPort ;
  43. m_strProxyServer = strProxyAddr ;
  44. return InitCurlHandle() ;
  45. }
  46. void CVVCurl::Release()
  47. {
  48. ReleaseCurlHandle() ;
  49. DeleteCookieFile() ;
  50. }
  51. BOOL CVVCurl::InitCurlHandle()
  52. {
  53. if( NULL == m_pcurl)
  54. {
  55. m_pcurl = curl_easy_init() ;
  56. }
  57. if( NULL == m_pcurl ){
  58. ASSERT(FALSE) ;
  59. return FALSE ;
  60. }
  61. SetCurlHandleOpt() ;
  62. return TRUE ;
  63. }
  64. BOOL CVVCurl::SetCurlHandleOpt()
  65. {
  66. if( NULL == m_pcurl )
  67. return FALSE ;
  68. // 设置Agent
  69. curl_easy_setopt(m_pcurl, CURLOPT_USERAGENT, m_agent.c_str());
  70. // 官方下载的DLL并不支持GZIP,Accept-Encoding:deflate, gzip
  71. curl_easy_setopt(m_pcurl, CURLOPT_ENCODING, "");
  72. //跳过服务器SSL验证,不使用CA证书
  73. curl_easy_setopt(m_pcurl, CURLOPT_SSL_VERIFYPEER, 0L);
  74. //如果不跳过SSL验证,则可指定一个CA证书目录
  75. //curl_easy_setopt(curl, CURLOPT_CAPATH, "this is ca ceat");
  76. //验证服务器端发送的证书,默认是 2(高),1(中),0(禁用)
  77. curl_easy_setopt(m_pcurl, CURLOPT_SSL_VERIFYHOST, 0L);
  78. /* 与服务器通信交互cookie,默认在内存中,可以是不存在磁盘中的文件或留空 */
  79. curl_easy_setopt(m_pcurl, CURLOPT_COOKIEFILE, m_cookiepath.c_str());
  80. /* 与多个CURL或浏览器交互cookie,会在释放内存后写入磁盘文件 */
  81. curl_easy_setopt(m_pcurl, CURLOPT_COOKIEJAR, m_cookiepath.c_str()) ;
  82. //设置重定向的最大次数
  83. curl_easy_setopt(m_pcurl, CURLOPT_MAXREDIRS, 5);
  84. // 设置自动设置refer字段
  85. curl_easy_setopt ( m_pcurl, CURLOPT_AUTOREFERER, 1 );
  86. //设置301、302跳转跟随location
  87. curl_easy_setopt(m_pcurl, CURLOPT_FOLLOWLOCATION, 1);
  88. //抓取内容后,回调函数
  89. curl_easy_setopt(m_pcurl, CURLOPT_WRITEFUNCTION, call_wirte_func);
  90. curl_easy_setopt(m_pcurl, CURLOPT_WRITEDATA, &m_bodycontent );
  91. //抓取头信息,回调函数
  92. curl_easy_setopt(m_pcurl, CURLOPT_HEADERFUNCTION, header_callback );
  93. curl_easy_setopt(m_pcurl, CURLOPT_HEADERDATA, &m_headcontent);
  94. // 设置超时时间
  95. curl_easy_setopt(m_pcurl, CURLOPT_TIMEOUT, 10);
  96. // 禁用掉alarm这种超时
  97. curl_easy_setopt(m_pcurl, CURLOPT_NOSIGNAL, 1L);
  98. // 禁止重用TCP连接
  99. curl_easy_setopt(m_pcurl, CURLOPT_FORBID_REUSE, 1);
  100. // 打开调试
  101. curl_easy_setopt(m_pcurl, CURLOPT_VERBOSE, 1);
  102. curl_easy_setopt(m_pcurl, CURLOPT_DEBUGFUNCTION, debug_callback);
  103. curl_easy_setopt(m_pcurl, CURLOPT_DEBUGDATA, &m_debugcontent);
  104. // 判断是否是需要代理
  105. if( m_strProxyServer.size() > 0 && m_nPort > 0)
  106. {
  107. // 打开,允许重用TCP连接
  108. curl_easy_setopt(m_pcurl, CURLOPT_FORBID_REUSE, 0);
  109. // 第一种方法
  110. curl_easy_setopt(m_pcurl,CURLOPT_PROXY,m_strProxyServer.c_str());
  111. curl_easy_setopt(m_pcurl, CURLOPT_PROXYPORT, m_nPort);
  112. curl_easy_setopt(m_pcurl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
  113. curl_easy_setopt(m_pcurl, CURLOPT_HTTPPROXYTUNNEL, 1L);
  114. }
  115. return TRUE ;
  116. }
  117. BOOL CVVCurl::ReleaseCurlHandle()
  118. {
  119. if( NULL != m_pcurl)
  120. {
  121. curl_easy_cleanup(m_pcurl);
  122. }
  123. m_pcurl = NULL ;
  124. return TRUE ;
  125. }
  126. BOOL CVVCurl::DeleteCookieFile()
  127. {
  128. ::DeleteFile(m_cookiepath.c_str());
  129. return TRUE ;
  130. }
  131. BOOL CVVCurl::OpenURL(std::string strURL,CURL_TYPE ntype)
  132. {
  133. return OpenURL(strURL,_T(""),ntype) ;
  134. }
  135. BOOL CVVCurl::OpenURL(std::string strURL,std::string strPostData,CURL_TYPE ntype)
  136. {
  137. m_headcontent = m_bodycontent = m_debugcontent = _T("");
  138. if( NULL == m_pcurl )
  139. {
  140. ASSERT(FALSE) ;
  141. return FALSE ;
  142. }
  143. if( ntype == CURL_POST || strPostData.size() > 0)
  144. {
  145. //curl_easy_setopt(m_pcurl,CURLOPT_HTTPGET,0);
  146. /* POST 数据 */
  147. curl_easy_setopt(m_pcurl,CURLOPT_POST,1);
  148. if(strPostData.size() > 0)
  149. {
  150. curl_easy_setopt(m_pcurl, CURLOPT_POSTFIELDS, strPostData.c_str());
  151. curl_easy_setopt(m_pcurl, CURLOPT_POSTFIELDSIZE, strPostData.size());
  152. }
  153. else
  154. {
  155. curl_easy_setopt(m_pcurl, CURLOPT_POSTFIELDS, NULL);
  156. curl_easy_setopt(m_pcurl, CURLOPT_POSTFIELDSIZE, 0);
  157. }
  158. //SetCurlHandleOpt() ;
  159. }else
  160. {
  161. // 禁用POST,直接GET请求
  162. //curl_easy_setopt(m_pcurl,CURLOPT_POST,0);
  163. //curl_easy_setopt(m_pcurl, CURLOPT_POSTFIELDS, NULL);
  164. curl_easy_setopt(m_pcurl,CURLOPT_HTTPGET,1);
  165. //SetCurlHandleOpt() ;
  166. }
  167. try
  168. {
  169. // 远程URL,支持 http, https, ftp
  170. curl_easy_setopt(m_pcurl, CURLOPT_URL, strURL.c_str());
  171. CURLcode nRet =  curl_easy_perform(m_pcurl);
  172. return CURLE_OK == nRet ;
  173. }
  174. catch (...)
  175. {
  176. }
  177. return FALSE ;
  178. }

2.4 编写代码

在使用CVVCurl封装类之前必须先调用函数cur_global_init进行全局初始化,再关闭时在调用函数curl_global_cleanup扫尾。我们可以在函数CTestlibCurlApp::InitInstance()中,添加这个两个函数,如下图:

然后就可以在程序的任何地方调用了CVVCurl类来访问网页了,比如我在一个函数响应出使用如下代码获取网页数据:

[cpp] view plain copy

print?

  1. void CTestlibCurlDlg::OnBnClickedVisitButton()
  2. {
  3. UpdateData(TRUE);
  4. m_Url = m_Url.Trim();
  5. if( m_Url.GetLength() <= 0)
  6. return ;
  7. CVVCurl vvcurl ;
  8. vvcurl.Init() ;
  9. if( vvcurl.OpenURL(m_Url.GetBuffer()))
  10. {
  11. m_ContentEdit.Clear() ;
  12. m_ContentEdit.SetSel(0,-1,FALSE);
  13. m_ContentEdit.ReplaceSel(vvcurl.GetBodyContent(),FALSE) ;
  14. }
  15. }

2.5 调试

编译程序,可能会有许多没有调试符号警告,这个是无所谓的。

[plain] view plain copy

print?

  1. Linking...
  2. libcurld.lib(asyn-thread.obj) : warning LNK4204: ‘c:\resource\vccode\testlibcurl\testlibcurl\debug\vc80.pdb‘ is missing debugging information for referencing module; linking object as if no debug info
  3. libcurld.lib(base64.obj) : warning LNK4204: ‘c:\resource\vccode\testlibcurl\testlibcurl\debug\vc80.pdb‘ is missing debugging information for referencing module; linking object as if no debug info
  4. libcurld.lib(bundles.obj) : warning LNK4204: ‘c:\resource\vccode\testlibcurl\testlibcurl\debug\vc80.pdb‘ is missing debugging information for referencing module; linking object as if no debug info
  5. libcurld.lib(conncache.obj) : warning LNK4204: ‘c:\resource\vccode\testlibcurl\testlibcurl\debug\vc80.pdb‘ is missing debugging information for referencing module; linking object as if no debug info
  6. libcurld.lib(connect.obj) : warning LNK4204: ‘c:\resource\vccode\testlibcurl\testlibcurl\debug\vc80.pdb‘ is missing debugging information for referencing module; linking object as if no debug info
  7. libcurld.lib(cookie.obj) : warning LNK4204: ‘c:\resource\vccode\testlibcurl\testlibcurl\debug\vc80.pdb‘ is missing debugging information for referencing module; linking object as if no debug info
  8. libcurld.lib(curl_addrinfo.obj) : warning LNK4204: ‘c:\resource\vccode\testlibcurl\testlibcurl\debug\vc80.pdb‘ is missing debugging information for referencing module; linking object as if no debug info

执行程序结果如下,测试HTTP访问和HTTPS访问:

3. 总结

我封装的CVVCurl访问类是可以支持HTTPS POST的,具体的请看下访问接口就可以了,此外还可以指定Cookie文件 ,是线程安全的封装类。如果需要支持多个账号同时登陆Web,那么只需要为每个不同的账号指定不同的Cookie文件就可以了。

对于抓取的网页内容,如果用的UTF8编码的网页内容可能需要进行编码转换一下,才能正确显示中文,工程中含有代码转换的类CStringConvert,已经加到工程代码中,可直接使用,如果还不懂的话,就请打发一杯咖啡钱给我,让老衲细细道来。【点此打发咖啡】[https://me.alipay.com/jekkay]

以上的测试工程代码,可以在下面网址中下载:

    1. :   VC2005使用含SSL的静态libcurl库代码工程
    2. :  http://download.csdn.net/detail/hujkay/6932541
时间: 2024-10-13 10:06:22

【转】如何在Windows+VS2005使用最新静态libcurl 7.35.0获取网页数据,支持HTTPS的相关文章

在Windows下使用MinGW静态编译Assimp

使用MinGW静态编译Assimp 到了5月份了,没有写一篇日志,于是自己从知识库里面拿出一篇文章充数吧.这次将要讲解如何在Windows下使用MinGW静态编译Assimp. Assimp是目前比较全的3D格式解析库了,熟悉3D游戏开发的同行都知道,3D的格式非常混乱,各种3D格式在不同场合都有他们特定的应用,游戏引擎只能够解析少部分3D格式,更多实用的格式来自游戏公司自定义的格式.而在开源领域,Assimp算是比较全的3D格式导入库了.它对3D格式理解深入,很适合整合至3D图形引擎中,让你们

如何在Windows上安装FFmpeg程序

如何在Windows上安装FFmpeg程序 由 Yutao 编辑 2 方法:下载FFmpeg在命令行中开启FFmpeg FFmpeg程序进行各种媒体格式的转换,从而它们可以在不同设备上播放.该程序只有命令行模式,因此将它安装到计算机中看上去有些令人生畏,但是只要根据本指南的方法,你只需要几分钟就可以将FFmpeg安装成功! 广告 方法 1: 下载FFmpeg 1 下载FFmpeg.访问下载页面时,你将看到很多不同下载选项.你可以根据自己的操作系统选择下载最新的32位或64位静态程序版本.广告 2

如何在Windows平台使用VS搭建C++/Lua的开发环境

转自:http://ju.outofmemory.cn/entry/95358 本文主要介绍如何在Windows平台利用VS搭建C++/Lua开发环境.这里的“C++/Lua开发环境”主要指的是C++调用Lua,以及Lua调用C++.Mac平台相对会比较方便,但是VS也不是很麻烦就是了.Mac上利用XCode搭建的教程可以参考子龙山人的教程,当然也可以利用其他IDE,比如Eclipse+CDT+LDT来搭建,这都没有问题. 另外,本文不谈及Lua/C++的交互,相关内容可以参考<Lua程序设计>

Windows 上静态编译 Libevent 2.0.10 并实现一个简单 HTTP 服务器(无数截图)

[文章作者:张宴 本文版本:v1.0 最后修改:2011.03.30 转载请注明原文链接:http://blog.s135.com/libevent_windows/] 本文介绍了如何在 Windows 操作系统中,利用微软 Visual Studio 2005 编译生成 Libevent 2.0.10 静态链接库,并利用 Libevent 静态链接库,实现一个简单的 HTTP Web服务器程序:httpd.exe. 假设 Visual Studio 2005 的安装路径为“D:\Program

Windows 上静态编译 Libevent 2.0.10 并实现一个简单 HTTP 服务器(图文并茂,还有实例下载)

[文章作者:张宴 本文版本:v1.0 最后修改:2011.03.30 转载请注明原文链接:http://blog.s135.com/libevent_windows/] 本文介绍了如何在 Windows 操作系统中,利用微软 Visual Studio 2005 编译生成 Libevent 2.0.10 静态链接库,并利用 Libevent 静态链接库,实现一个简单的 HTTP Web服务器程序:httpd.exe. 假设 Visual Studio 2005 的安装路径为“D:\Program

Windows技巧|如何在Windows 10在锁屏状态下打开某种应用程序?

本文标签:    电脑技巧 Windows技巧 Win10的锁屏界面 互联网杂谈 在Win10的锁屏界面,右下角有三个图标,中间有个像时钟的图标就是所谓的"轻松使用"按钮,里面有讲述人.放大镜.屏幕键盘等功能,这些功能我们可以修改成我们常用的应用程序,这样将大大的方便我们的操作,那么该如何修改呢? 默认情况下在锁屏界面点击右下角中间的图标会弹出"轻松使用"菜单 具体方法如下: 1.在Cortana搜索栏输入regedit,按回车键进入注册表编辑器; 2.定位到:HK

《Go语言入门》如何在Windows下安装Go语言编程环境

概述 本文为Go语言学习入门第一篇,<Go语言入门>如何在Windows下安装Go语言编程环境 . 主要讲Go语言编译环境的安装以及基于Notepad++(Go语言插件.语法高亮)的开发环境配置. 下载安装包 安装包下载地址:https://golang.org/dl/ 这里选择下载Windows版本,点击链接打开的页面可能不会开始下载:地址栏里会显示完整的下载地址,如:https://golang.org/doc/install?download=go1.5.1.windows-amd64.

如何在Windows中打开多个Windows Media Player

博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:如何在Windows中打开多个Windows Media Player. 如何在Windows中打开多个Windows Media Player

Windows 上静态编译 Libevent 2.0.10 并实现一个简单 HTTP 服务器

Windows 上静态编译 Libevent 2.0.10 并实现一个简单 HTTP 服务器  大 | 中 | 小  [ 2011-3-30 08:40 | by 张宴 ] [文章作者:张宴 本文版本:v1.0 最后修改:2011.03.30 转载请注明原文链接:http://blog.zyan.cc/libevent_windows/] 本文介绍了如何在 Windows 操作系统中,利用微软 Visual Studio 2005 编译生成 Libevent 2.0.10 静态链接库,并利用 L