【实现一个网络爬虫】三、爬虫是如何工作的

把所有爬虫要实现的功能集成到了一个类里,需要使用的时候,只用新建一个对象,再调用相应的方法即可。

下面就分享一天写的这个爬虫类是如何工作的。

 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编码,所以需要转换一下编码。就在上处标注的地方。

其他方法就不多说了,后面会把工程上传,因为写得还不成熟,效率可能不会很高,毕竟不是大型项目,在自己电脑上运行着玩儿的,大家可以参考一下。

posted @ 2012-10-30 14:48  byan  阅读(2058)  评论(0编辑  收藏  举报