MFC抓取网页代码。

本人是初学MFC,这几天都要弄怎么抓取网页代码,一开始是一头雾水,不过最后多亏网上的丰富资源,让我有所收获,我也帮助新手们,下面是我自己参考网上资料所得的。

 1 #pragma once
 2 
 3 
 4 //抓取网页代码封装类
 5 
 6 #include <afxinet.h> //所需要的函数的头文件。
 7 
 8 
 9 class CGetInternet
10 {
11 public:
12     CGetInternet();
13     virtual ~CGetInternet();
14 
15     //添加变量
16 protected:
17     CString        m_strError;  //接受错误信息
18     CString        m_HttpCode;  //接受抓取的网页代码
19     UINT           PageCode;   //CP_UTF8:65001 CP_ACP:0  转换代码用  
20 
21     //添加自定义函数
22 public:
23     BOOL OnInitSession(CInternetSession &session);//判断链接是否成功。可以不要
24     
25     CString GetHttpCode(CString &url); //主要接口,输入网址,获取代码
26     
27     int OnProcessError(int dwRetcode, CInternetSession &session,
28                 CHttpConnection *pServer, CHttpFile *pFile);//链接错误函数
29 
30 
31 };
  1 #include "stdafx.h"
  2 #include "GetInternet.h"
  3 
  4 //验证的字符串
  5 const TCHAR szHeaders[] = _T("Accept: _T/*\r\nUser-Agent: LCD's Infobay Http Client\r\n");
  6 
  7 //构造函数
  8 CGetInternet::CGetInternet()
  9 {
 10     PageCode = 65001; //因为我们的网址是UTF8格式,所以用65001;
 11     m_HttpCode = _T("");
 12 }
 13 
 14 //析构函数
 15 CGetInternet::~CGetInternet()
 16 {
 17     m_strError.ReleaseBuffer();
 18 }
 19 
 20 //主要接口,输入网址,获取代码
 21 CString CGetInternet::GetHttpCode(CString &url)
 22 {
 23     //获取网页的初始化工作
 24     CInternetSession session(NULL, 0); 
 25     CHttpFile *htmlFile = NULL;
 26     TCHAR sRecv[1024];  //接受缓存代码。
 27 
 28     //错误判断初始化
 29     DWORD dwServiceType = 0;
 30     DWORD  dwHttpRequestFlags = INTERNET_FLAG_EXISTING_CONNECT | INTERNET_FLAG_NO_AUTO_REDIRECT;
 31     CString strServerName = _T("");
 32     CString strObject = _T("");
 33     INTERNET_PORT nPort = 0;
 34     CString StrContent = _T("");
 35     DWORD dwRetcode = -1;
 36 
 37     CHttpConnection *pServer = NULL;
 38 
 39     try
 40     {
 41         if (!OnInitSession(session)) //判断链接是否成功;可以不要
 42         {
 43             return NULL;
 44         }
 45         if (!AfxParseURL(url, dwServiceType, strServerName, strObject, nPort) || dwServiceType != INTERNET_SERVICE_HTTP)
 46         {
 47             m_strError = _T("非法的URL");
 48             return NULL;
 49         }
 50 
 51         pServer = session.GetHttpConnection(strServerName, nPort);
 52 
 53 
 54         if (pServer == NULL)
 55         {
 56             m_strError = _T("无法与服务器建立连接");
 57             return NULL;
 58         }
 59         //下面第一个可以为1  打开http链接
 60         htmlFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_GET, strObject,
 61             NULL, 1, NULL, NULL, dwHttpRequestFlags);
 62 
 63         if (htmlFile == NULL)
 64         {
 65             m_strError = _T("无法与服务器建立连接");
 66             return NULL;
 67         }
 68 
 69         /////////////////////////////////////////////////
 70         try
 71         { //调用此成员函数添加一个或多个HTTP请求标头到HTTP请求处理。AddRequestHeaders
 72             //
 73             if (!htmlFile->AddRequestHeaders(szHeaders) || !htmlFile->SendRequest())
 74             {
 75                 m_strError = _T("网络错误-无法发送请求报头");
 76                 return NULL;
 77             }
 78         }
 79         catch (CInternetException *ex)
 80         {
 81             StrContent.Empty();
 82             m_strError = _T("无法发送http报头,可能网络状况有问题");
 83             ex->Delete();
 84             return NULL;
 85         }
 86         //////////////////////////////////////////////////////////////////////////
 87 
 88         if (!htmlFile->QueryInfoStatusCode(dwRetcode))
 89         {
 90             m_strError = _T("网络错误-无法查询反馈代码");
 91             return NULL;
 92         }
 93 
 94         if (dwRetcode >= 200 && dwRetcode < 300)
 95         {
 96             try
 97             {
 98                 //htmlFile = (CHttpFile*)session.OpenURL(url);//打开链接
 99 
100                 while (htmlFile->ReadString(sRecv, 1024))
101                 {
102                     // 编码转换,可解决中文乱码问题  
103                     //gb2312转为unicode,则用CP_ACP  
104                     //gbk转为unicode,也用CP_ACP  
105                     //utf-8转为unicode,则用CP_UTF8  
106                     int nBufferSize = MultiByteToWideChar(PageCode, 0, (LPCSTR)sRecv, -1, NULL, 0);
107 
108                     wchar_t *pBuffer = new wchar_t[nBufferSize + 1];
109                     memset(pBuffer, 0, (nBufferSize + 1) *sizeof(wchar_t));
110 
111                     //gb2312转为unicode,则用CP_ACP  
112                     //gbk转为unicode,也用CP_ACP  
113                     //utf-8转为unicode,则用CP_UTF8  
114                     MultiByteToWideChar(PageCode, 0, (LPCSTR)sRecv, -1, pBuffer, nBufferSize *sizeof(wchar_t));
115 
116                     m_HttpCode += pBuffer;
117                     m_HttpCode += "\r\n";
118                     delete pBuffer;
119                 }
120 
121                 htmlFile->Close();
122                 session.Close();
123                 delete htmlFile;
124                 
125                 //多余。
126                 CFile file;
127                 file.Open(_T("test2.txt"), CFile::modeCreate | CFile::modeNoTruncate | CFile::modeReadWrite);
128                 file.Write(m_HttpCode, m_HttpCode.GetLength());
129                 file.Close();
130                 
131                 return m_HttpCode;
132 
133             }
134             catch (CInternetException* pEx)
135             {
136                 m_strError = _T("接收数据错误");
137                 pEx->Delete();
138 
139                 //因为是CString,所以返回NULL,而不是0;
140                 return NULL;
141             }
142             return StrContent;
143 
144         }
145         else
146         {
147             //读取失败,将buffer清空。
148             StrContent.Empty();
149 
150             //发送错误。
151             OnProcessError(dwRetcode, session, pServer, htmlFile);
152 
153             return NULL;
154         }
155 
156     }
157     catch (CInternetException* pEx)
158     {
159         m_strError = _T("网络错误");
160 
161         pEx->Delete();
162         return NULL;
163     }
164 
165     return NULL;
166 }
167 
168 
169 //判断链接是否成功。可以不要
170 BOOL CGetInternet::OnInitSession(CInternetSession &session)
171 {
172     //超时设置很重要!如果设置太小回引起服务器超时,如果设置太大则回引起线程挂起。
173     //在重试连接之间的等待的延时值在毫秒级。
174     //网络连接请求时间超时值在数毫秒级。如果连接请求时间超过这个超时值,请求将被取消。缺省的超时值是无限的。
175     //在网络连接请求时的重试次数。如果一个连接企图在指定的重试次数后仍失败,则请求被取消。缺省值为5。
176     try
177     {
178         if (!session.SetOption(INTERNET_OPTION_CONNECT_TIMEOUT, 10000) ||  //超时
179             !session.SetOption(INTERNET_OPTION_CONNECT_BACKOFF, 1000) ||    //延迟
180             !session.SetOption(INTERNET_OPTION_CONNECT_RETRIES, 3) ||       //重试
181             !session.SetOption(INTERNET_OPTION_RECEIVE_TIMEOUT, 60000) ||       //最大超时
182             !session.EnableStatusCallback(TRUE))            //建立一个状态回调例程。异步操作需要
183         {
184             return FALSE;
185         }
186         else
187         {
188             return TRUE;
189         }
190     }
191     catch (CInternetException* pEx)
192     {
193         pEx->GetErrorMessage(m_strError.GetBuffer(0), 1023);
194         pEx->Delete();
195 
196         return FALSE;
197     }
198 
199 }
200 
201 //链接错误函数
202 int CGetInternet::OnProcessError(int dwRetcode, CInternetSession &session,
203     CHttpConnection *pServer, CHttpFile *pFile)
204 {
205     switch (dwRetcode)
206     {
207     case 100:
208         m_strError = _T("客户方错误-继续 [Continue]");
209         break;
210         //
211     case 101:
212         m_strError = _T("客户方错误-交换协议 [witching Protocols]");
213         break;
214         //
215     case 204:
216         m_strError = _T("网页内容为空 [No Content]");
217         break;
218         //------------------------------------------------------------
219     case 400:
220         m_strError = _T("错误请求 [Bad Request]");
221         break;
222         //
223     case 401:
224         m_strError = _T("网页需要验证信息 [Unauthorized]");
225         break;
226         //
227     case 402:
228         m_strError = _T("网页需要付费 [Payment Required]");
229         break;
230         //
231     case 403:
232         m_strError = _T("禁止访问 [Forbidden]");
233         break;
234         //
235     case 404://
236         m_strError = _T("没有找到网页 [Not Found]");
237         break;
238         //
239     case 405:
240         m_strError = _T("不允许Http访问该文件 [Method Not Allowed]");
241         break;
242         //
243     case 406:
244         m_strError = _T("该文件不允许访问 [Not Acceptable]");
245         break;
246         //
247     case 407:
248         m_strError = _T("该文件需要代理认证 [Proxy Authentication Required]");
249         break;
250         //
251     case 408:
252         m_strError = _T("对该文件请求超时 [Request Time-out]");
253         break;
254         //
255     case 409:
256         m_strError = _T("对该文件访问冲突 [Conflict]");
257         break;
258         //
259     case 410:
260         m_strError = _T("对该文件访问失败 [Gone]");
261         break;
262         //
263     case 411:
264         m_strError = _T("该文件需要长度信息 [Length Required]");
265         break;
266         //
267     case 412:
268         m_strError = _T("请求条件失败 [Precondition Failed]");
269         break;
270         //
271     case 413:
272         m_strError = _T("请求文件实体太大 [Request Entity Too Large]");
273         break;
274         //
275     case 414:
276         m_strError = _T("请求的URI太长 [Request-URI Too Large]");
277         break;
278         //
279     case 415:
280         m_strError = _T("不支持媒体类型 [Unsupported Media Type]");
281         break;
282         //
283     case 416:
284         m_strError = _T("队列请求失败 [Requested range not satisfiable]");
285         break;
286         //
287     case 417:
288         m_strError = _T("预期失败 [Expectation Failed]");
289         break;
290         //--------------------------------------------------------------
291     case 500:
292         m_strError = _T("服务器内部错误 [Internal Server Error]");
293         break;
294         //
295     case 501:
296         m_strError = _T("未实现请求 [Not Implemented]");
297         break;
298         //
299     case 502:
300         m_strError = _T("网关失败 [Bad Gateway]");
301         break;
302         //
303     case 503:
304         m_strError = _T("没有找到服务器 [Service Unavailable]");
305         break;
306         //
307     case 504:
308         m_strError = _T("网关超时 [Gateway Time-out]");
309         break;
310         //
311     case 505:
312         m_strError = _T("服务器不支持系统使用的HTTP版本 [HTTP Version not supported]");
313         break;
314         //
315     }
316 
317     try
318     {
319         if (pFile != NULL) SafeDelete(pFile);
320         if (pServer != NULL) SafeDelete(pServer);
321 
322         session.Close();
323 
324         return 0;
325     }
326     catch (CInternetException *pEx)
327     {
328         pEx->GetErrorMessage(m_strError.GetBuffer(0), 1024);
329         pEx->Delete();
330 
331         return 0;
332     }
333 }

 

 


//多余。
CFile file;
file.Open(_T("test2.txt"), CFile::modeCreate | CFile::modeNoTruncate | CFile::modeReadWrite);
file.Write(m_HttpCode, m_HttpCode.GetLength());
file.Close();

 

这个是用来查看抓取的代码。

 

PS:

 

需要在stdafx.h加入这个

//删除指针
#define SafeDelete(pData) { try { delete pData; } catch (...) { ASSERT(FALSE); } pData=NULL; }

 

1,创建一个MFC的基本对话框,

2.创建一个c++类,将上面代码加入,

3.在OnInitDialog函数中调用:

// TODO: 在此添加额外的初始化代码

CGetInternet get1;
CString url = _T("http://www.tqyb.com.cn/index.html");
get1.GetHttpCode(url);

 

以上。

 

感谢:

http://code.it168.com/v/yigecongwangyetaglimianfenxiurlheurlbiaotideleivcyuandaima/GetWeb.cpp

http://blog.chinaunix.net/uid-27213819-id-3781188.html

http://www.gymsaga.com/project/728.html

 

感谢这三位博主的开源。

 

posted @ 2014-08-13 12:06  学需持  阅读(2674)  评论(1编辑  收藏  举报