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
感谢这三位博主的开源。