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

 

感謝這三位博主的開源。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM