把所有爬虫要实现的功能集成到了一个类里,需要使用的时候,只用新建一个对象,再调用相应的方法即可。
下面就分享一天写的这个爬虫类是如何工作的。
1 public: 2 CCrawler(void); 3 ~CCrawler(void); 4 CString GetSubsitesFromPage(CString pageStr);//从页面当中提取出所有的子页面 5 CString GetPageStr(CString url); //得到完整的页面数据,这里就要使用网络连接,为了简便,不把更细的细节分开写 6 CString GenerateUrl(CString indexUrl, CString site);//页面中得到的连接,需要和主页一起,生成可以访问的完整连接 7 CString CheckContent(CString strContent, CString keywords);//检查内容,看是否包含需要检索的关键字 8 CString PurifyContent(CString strContent);//为了减少对比过程中的复杂度,先将内容简化,去除无用的标签 9 10 protected: 11 int PureTextIndex(CString &strResult, CString str, int offset); //递归方法,净化主页面,得到网址 12 int PureTextContent(CString & strResult, CString str, int offset);//同上,净化内容页面,得到纯文本 13
很多人以为爬虫很关键的地方在于如何爬不同深度的网页,网上也找了很多讲爬虫理论的,可能是我悟性比较低吧,只写了一个可以爬二级页面内容的程序。要是让我写把互联网所有内容全爬过来的程序,可以设想一下,不过实现起来就很难了。
言归正传,网络连接部分网上很多,而且每一种开发语言都会提供比较成熟的接口,因而我不想在这方面多花心思去研究HTTP报文,协议什么的,直接用了网上的一个做好的DLL程序,直接把所有网页返回的数据得到了。
1 /************************************************************************/ 2 /* 根据url提供的地址,访问网络,返回从网络得到的全部字符*/ 3 /************************************************************************/ 4 CString CCrawler::GetPageStr(CString url) 5 { 6 CHttpSocket *pHttp = new CHttpSocket(); 7 CString strServer, strObject, strPage; 8 unsigned short port; 9 DWORD dwServerType; 10 long nLength; 11 const char *pRequestHeader = NULL; 12 13 // pretreat of sending 14 AfxParseURL(url,dwServerType, strServer, strObject, port); 15 pRequestHeader = pHttp->FormatRequestHeader((LPTSTR)(LPCTSTR)strServer,(LPTSTR)(LPCTSTR)strObject, nLength); 16 pHttp->Socket(); // begin to send request 17 pHttp->Connect((LPTSTR)(LPCTSTR)strServer); 18 pHttp->SendRequest(); 19 pHttp->SetTimeout(10000,0); 20 21 // retrieve page data 22 char pageSize[30]; 23 pHttp->GetField("Content-Length", pageSize, 30); 24 int nServerState = pHttp->GetServerState(); 25 int nPageSize = atoi(pageSize); 26 27 char pData[1024]; 28 int nRecSize=0, nComplSize=0; 29 while(nComplSize < nPageSize) 30 { 31 nRecSize = pHttp->Receive(pData,1024); 32 if (nRecSize==0) 33 { 34 AfxMessageBox("Connect closed"); 35 break; 36 } 37 if(nRecSize==-1) 38 { 39 AfxMessageBox("over time"); 40 break; 41 } 42 // ConvertUTF8ToANSI(pData,ch); //此处可能存在内存问题 43 //strPage += ch; 44 strPage += pData; 45 nComplSize += nRecSize; 46 } 47 pHttp->CloseSocket(); 48 /***************************调试用的*********************************************/ 49 CStdioFile file; 50 file.Open("c:/newpage.html",CFile::modeCreate|CFile::modeWrite); 51 file.WriteString(strPage); 52 file.Close(); 53 /************************************************************************/ 54 return strPage; 55 }
这时出现了一个很多人都遇到的问题:乱码。因为工程使用的编码和从网页上返回的编码不一致,导致中文无法显示,工程里面可以选,一般是UTF-8,网页上返回的是GBK编码,所以需要转换一下编码。就在上处标注的地方。
其他方法就不多说了,后面会把工程上传,因为写得还不成熟,效率可能不会很高,毕竟不是大型项目,在自己电脑上运行着玩儿的,大家可以参考一下。