首页 > 代码库 > MFC抓取网页代码。
MFC抓取网页代码。
本人是初学MFC,这几天都要弄怎么抓取网页代码,一开始是一头雾水,不过最后多亏网上的丰富资源,让我有所收获,我也帮助新手们,下面是我自己参考网上资料所得的。
1 #pragma once 2 3 4 //抓取网页代码封装类 5 6 #include <afxinet.h> //所需要的函数的头文件。 7 8 9 class CGetInternet10 {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 else146 {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 try177 {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 else187 {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 try318 {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=http://www.mamicode.com/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
感谢这三位博主的开源。