网络爬虫C++

来源:互联网 发布:女性吸毒后性反应知乎 编辑:程序博客网 时间:2024/05/23 02:02

写了一个网络爬虫,可以抓取网上的图片。

需要给定初始网站即可。

在vs2010中编译通过。

编译后,运行即可,有惊喜哦!!!


[cpp] view plaincopyprint?
  1. //#include <Windows.h>   
  2. #include <string>   
  3. #include <iostream>   
  4. #include <fstream>   
  5. #include <vector>   
  6. #include "winsock2.h"   
  7. #include <time.h>   
  8. #include <queue>   
  9. #include <hash_set>   
  10.   
  11.   
  12. #pragma comment(lib, "ws2_32.lib")    
  13. using namespace std;  
  14.   
  15. #define DEFAULT_PAGE_BUF_SIZE 1048576  
  16.   
  17. queue<string> hrefUrl;  
  18. hash_set<string> visitedUrl;  
  19. hash_set<string> visitedImg;  
  20. int depth=0;  
  21. int g_ImgCnt=1;  
  22.   
  23. //解析URL,解析出主机名,资源名   
  24. bool ParseURL( const string & url, string & host, string & resource){  
  25.     const char * pos = strstr( url.c_str(), "http://" );  
  26.     if( pos==NULL ) pos = url.c_str();  
  27.     else pos += strlen("http://");  
  28.     if( strstr( pos, "/")==0 )  
  29.         return false;  
  30.     char pHost[100];  
  31.     char pResource[200];  
  32.     sscanf( pos, "%[^/]%s", pHost, pResource );  
  33.     host = pHost;  
  34.     resource = pResource;  
  35.     return true;  
  36. }  
  37.   
  38. //使用Get请求,得到响应   
  39. bool GetHttpResponse( const string & url, char * &response, int &bytesRead ){  
  40.     string host, resource;  
  41.     if(!ParseURL( url, host, resource )){  
  42.         cout << "Can not parse the url"<<endl;  
  43.         return false;  
  44.     }  
  45.       
  46.     //建立socket   
  47.     struct hostent * hp= gethostbyname( host.c_str() );  
  48.     if( hp==NULL ){  
  49.         cout<< "Can not find host address"<<endl;  
  50.         return false;  
  51.     }  
  52.   
  53.     SOCKET sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP);  
  54.     if( sock == -1 || sock == -2 ){  
  55.         cout << "Can not create sock."<<endl;  
  56.         return false;  
  57.     }  
  58.   
  59.     //建立服务器地址   
  60.     SOCKADDR_IN sa;  
  61.     sa.sin_family = AF_INET;  
  62.     sa.sin_port = htons( 80 );  
  63.     //char addr[5];   
  64.     //memcpy( addr, hp->h_addr, 4 );   
  65.     //sa.sin_addr.s_addr = inet_addr(hp->h_addr);  
  66.     memcpy( &sa.sin_addr, hp->h_addr, 4 );  
  67.   
  68.     //建立连接   
  69.     if( 0!= connect( sock, (SOCKADDR*)&sa, sizeof(sa) ) ){  
  70.         cout << "Can not connect: "<< url <<endl;  
  71.         closesocket(sock);  
  72.         return false;  
  73.     };  
  74.   
  75.     //准备发送数据   
  76.     string request = "GET " + resource + " HTTP/1.1\r\nHost:" + host + "\r\nConnection:Close\r\n\r\n";  
  77.   
  78.     //发送数据   
  79.     if( SOCKET_ERROR ==send( sock, request.c_str(), request.size(), 0 ) ){  
  80.         cout << "send error" <<endl;  
  81.         closesocket( sock );  
  82.         return false;  
  83.     }  
  84.   
  85.     //接收数据   
  86.     int m_nContentLength = DEFAULT_PAGE_BUF_SIZE;  
  87.     char *pageBuf = (char *)malloc(m_nContentLength);  
  88.     memset(pageBuf, 0, m_nContentLength);  
  89.   
  90.     bytesRead = 0;  
  91.     int ret = 1;  
  92.     cout <<"Read: ";  
  93.     while(ret > 0){  
  94.         ret = recv(sock, pageBuf + bytesRead, m_nContentLength - bytesRead, 0);  
  95.           
  96.         if(ret > 0)  
  97.         {  
  98.             bytesRead += ret;  
  99.         }  
  100.   
  101.         if( m_nContentLength - bytesRead<100){  
  102.             cout << "\nRealloc memorry"<<endl;  
  103.             m_nContentLength *=2;  
  104.             pageBuf = (char*)realloc( pageBuf, m_nContentLength);       //重新分配内存  
  105.         }  
  106.         cout << ret <<" ";  
  107.     }  
  108.     cout <<endl;  
  109.   
  110.     pageBuf[bytesRead] = '\0';  
  111.     response = pageBuf;  
  112.     closesocket( sock );  
  113.     return true;  
  114.     //cout<< response <<endl;   
  115. }  
  116. //提取所有的URL以及图片URL   
  117. void HTMLParse ( string & htmlResponse, vector<string> & imgurls, const string & host ){  
  118.     //找所有连接,加入queue中   
  119.     const char *p= htmlResponse.c_str();  
  120.     char *tag="href=\"";  
  121.     const char *pos = strstr( p, tag );  
  122.     ofstream ofile("url.txt", ios::app);  
  123.     while( pos ){  
  124.         pos +=strlen(tag);  
  125.         const char * nextQ = strstr( pos, "\"" );  
  126.         if( nextQ ){  
  127.             char * url = new char[ nextQ-pos+1 ];  
  128.             //char url[100]; //固定大小的会发生缓冲区溢出的危险  
  129.             sscanf( pos, "%[^\"]", url);  
  130.             string surl = url;  
  131.             if( visitedUrl.find( surl ) == visitedUrl.end() ){  
  132.                 visitedUrl.insert( surl );  
  133.                 ofile << surl<<endl;  
  134.                 hrefUrl.push( surl );  
  135.             }  
  136.             pos = strstr(pos, tag );  
  137.             delete [] url;  
  138.         }  
  139.     }  
  140.     ofile << endl << endl;  
  141.     ofile.close();  
  142.   
  143.     tag ="<img ";  
  144.     const char* att1= "src=\"";  
  145.     const char* att2="lazy-src=\"";  
  146.     const char *pos0 = strstr( p, tag );  
  147.     while( pos0 ){  
  148.         pos0 += strlen( tag );  
  149.         const char* pos2 = strstr( pos0, att2 );  
  150.         if( !pos2 || pos2 > strstr( pos0, ">") )  
  151.             pos = strstr( pos0, att1)+strlen(att1);  
  152.         else  
  153.             pos = pos2 + strlen(att2);  
  154.         const char * nextQ = strstr( pos, "\"");  
  155.         if( nextQ ){  
  156.             char * url = new char[nextQ-pos+1];  
  157.             sscanf( pos, "%[^\"]", url);  
  158.             cout << url<<endl;  
  159.             string imgUrl = url;  
  160.             if( visitedImg.find( imgUrl ) == visitedImg.end() ){  
  161.                 visitedImg.insert( imgUrl );  
  162.                 imgurls.push_back( imgUrl );  
  163.             }  
  164.             pos0 = strstr(pos0, tag );  
  165.             delete [] url;  
  166.         }  
  167.     }  
  168.     cout << "end of Parse this html"<<endl;  
  169. }  
  170.   
  171. //把URL转化为文件名   
  172. string ToFileName( const string &url ){  
  173.     string fileName;  
  174.     fileName.resize( url.size());  
  175.     int k=0;  
  176.     forint i=0; i<(int)url.size(); i++){  
  177.         char ch = url[i];  
  178.         if( ch!='\\'&&ch!='/'&&ch!=':'&&ch!='*'&&ch!='?'&&ch!='"'&&ch!='<'&&ch!='>'&&ch!='|')  
  179.             fileName[k++]=ch;  
  180.     }  
  181.     return fileName.substr(0,k) + ".txt";  
  182. }  
  183.   
  184. //下载图片到img文件夹   
  185. void DownLoadImg( vector<string> & imgurls, const string &url ){  
  186.   
  187.     //生成保存该url下图片的文件夹   
  188.     string foldname = ToFileName( url );  
  189.     foldname = "./img/"+foldname;  
  190.     if(!CreateDirectory( foldname.c_str(),NULL ))  
  191.         cout << "Can not create directory:"<< foldname<<endl;  
  192.     char *image;  
  193.     int byteRead;  
  194.     forint i=0; i<imgurls.size(); i++){  
  195.         //判断是否为图片,bmp,jgp,jpeg,gif   
  196.         string str = imgurls[i];  
  197.         int pos = str.find_last_of(".");  
  198.         if( pos == string::npos )  
  199.             continue;  
  200.         else{  
  201.             string ext = str.substr( pos+1, str.size()-pos-1 );  
  202.             if( ext!="bmp"&& ext!="jpg" && ext!="jpeg"&& ext!="gif"&&ext!="png")  
  203.                 continue;  
  204.         }  
  205.         //下载其中的内容   
  206.         if( GetHttpResponse(imgurls[i], image, byteRead)){  
  207.             const char *p=image;  
  208.             const char * pos = strstr(p,"\r\n\r\n")+strlen("\r\n\r\n");  
  209.             int index = imgurls[i].find_last_of("/");  
  210.             if( index!=string::npos ){  
  211.                 string imgname = imgurls[i].substr( index , imgurls[i].size() );  
  212.                 ofstream ofile( foldname+imgname, ios::binary );  
  213.                 if( !ofile.is_open() )  
  214.                     continue;  
  215.                 cout <<g_ImgCnt++<< foldname+imgname<<endl;  
  216.                 ofile.write( pos, byteRead- (pos-p) );  
  217.                 ofile.close();  
  218.             }  
  219.             free(image);  
  220.         }  
  221.     }  
  222. }  
  223.   
  224.   
  225.   
  226. //广度遍历   
  227. void BFS( const string & url ){  
  228.     char * response;  
  229.     int bytes;  
  230.     if( !GetHttpResponse( url, response, bytes ) ){  
  231.         cout << "The url is wrong! ignore." << endl;  
  232.         return;  
  233.     }  
  234.     string httpResponse=response;  
  235.     free( response );  
  236.     string filename = ToFileName( url );  
  237.     ofstream ofile( "./html/"+filename );  
  238.     if( ofile.is_open() ){  
  239.         ofile << httpResponse << endl;  
  240.         ofile.close();  
  241.     }  
  242.     vector<string> imgurls;  
  243.     HTMLParse( httpResponse,  imgurls, url );  
  244.       
  245.     //下载图片资源   
  246.     DownLoadImg( imgurls, url );  
  247. }  
  248. void main()  
  249. {  
  250.     WSADATA wsaData;  
  251.     if( WSAStartup(MAKEWORD(2,2), &wsaData) != 0 ){  
  252.         return;  
  253.     }  
  254.     CreateDirectory( "./img",0);  
  255.     CreateDirectory("./html",0);  
  256.     //string urlStart = "http://hao.360.cn/meinvdaohang.html";  
  257.     string urlStart = "http://hao.360.cn/meinvdaohang.html";  
  258.     BFS( urlStart );  
  259.     visitedUrl.insert( urlStart );  
  260.     while( hrefUrl.size()!=0 ){  
  261.         string url = hrefUrl.front();  
  262.         cout << url << endl;  
  263.         BFS( url );  
  264.         hrefUrl.pop();  
  265.     }  
  266.     WSACleanup();  
  267.     return;  
  268. }  
0 0