【转】网络爬虫获取网站图片

  转自:http://blog.csdn.net/huangxy10/article/details/8120106

  备注:把项目属性中的字符集改成多字节集合?  

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

【转】网络爬虫获取网站图片的相关文章

如何通过网络爬虫获取网站数据

我们知道,网络爬虫是一种按照一定的规则,自动地抓取网站信息的程序或者脚本.那么,我们怎么通过网络爬虫获取所需要的网站信息呢?不同的网站有不同的规则,爬虫工程师根据这些规则设计不同的网络爬虫,以此来顺利获取所需要的信息.一.开放API的网站一个网如果开放了API,那么就可以直接GET到它的json数据.有三种方法可以判断一个网站是否开放了API.1.在站内寻找API入口:2.用搜索引擎搜索"某网站API":3.抓包,有的网站虽然用到了ajax,但是通过抓包还是能够获取XHR里的json数

Java 网络爬虫获取网页源代码原理及实现

Java 网络爬虫获取网页源代码原理及实现 1.网络爬虫是一个自动提取网页的程序,它为搜索引擎从万维网上下载网页,是搜索引擎的重要组成.传统爬虫从一个或若干初始网页的URL开始,获得初始网页上的URL,在抓取网页的过程中,不断从当前页面上抽取新的URL放入队列,直到满足系统的一定停止条件. 2.那么程序获取网页的原理到底是怎么回事呢?看下面的图:客服端首先向服务器端发出Http请求,之后服务器端返回相应的结果或者请求超时客户端自己报错. 服务器端发出的Http请求,实际上说是对服务器的文件的请求

通过网络路径获取的图片 btye 图片流互转

楼主有一个需要用户用的网站要上传图片,图片不保存到网站,而是要专门存放到一个图片服务器上面,于是需要通过byte的形式来传输 之前写的一个本地图片流转于byte互转 后来发现通过网络路径获取的图片这个方法就用不了 后来百度了 换了一个新的写法 图片流转成byte数组 1 public byte[] SaveImage(Image image) 2 { 3 MemoryStream ms = new MemoryStream(); 4 BinaryFormatter bf = new Binary

关于app生成商品图片,取代网络远程获取商品图片的设想

当我在使用各种电子商务或者O2O等app时,app在不断的从远程服务器处获取各种商品图片.是否可以取消这种方式?仅仅通过app生成. app生成图片,服务器提供商品描述指令.比如,app需要显示一个苹果图片时,服务器提供一个简单的商品描述指令:apple.当app获取到apple这个指令时,就自动绘制出苹果图片.这样,在app与服务器之间的数据传输将只有简单的描述指令等一些简单的信息. 那么关键问题转移到了图片生成上.

安卓 获取网站图片

public static Bitmap getBitmapFromServer(String imagePath) { HttpGet get = new HttpGet(imagePath); HttpClient client = new DefaultHttpClient(); Bitmap pic = null; try { HttpResponse response = client.execute(get); HttpEntity entity = response.getEnti

获取网站图片,下载

=== ===

Android实战——jsoup实现网络爬虫,糗事百科项目的起步

Android实战--jsoup实现网络爬虫,爬糗事百科主界面 本篇文章包括以下内容: 前言 jsoup的简介 jsoup的配置 jsoup的使用 结语 前言 对于Android初学者想要做项目时,最大的烦恼是什么?毫无疑问是数据源的缺乏,当然可以选择第三方接口提供数据,也可以使用网络爬虫获取数据,这样就不用第三方数据作为支持.本来是打算爬一些购物网站的数据,由于他们的反爬做得好,所以没办法爬到数据,只能爬取糗事百科的数据,或许聪明的你会想到可以高仿个糗事百科作为自己的练手项目,利用jsoup是

Python网络爬虫入门篇

1.  预备知识 学习者需要预先掌握Python的数字类型.字符串类型.分支.循环.函数.列表类型.字典类型.文件和第三方库使用等概念和编程方法. 2. Python爬虫基本流程 a. 发送请求 使用http库向目标站点发起请求,即发送一个Request,Request包含:请求头.请求体等. Request模块缺陷:不能执行JS 和CSS 代码. b. 获取响应内容 如果requests的内容存在于目标服务器上,那么服务器会返回请求内容. Response包含:html.Json字符串.图片,

[Search Engine] 搜索引擎技术之网络爬虫

随着互联网的大力发展,互联网称为信息的主要载体,而如何在互联网中搜集信息是互联网领域面临的一大挑战.网络爬虫技术是什么?其实网络爬虫技术就是指的网络数据的抓取,因为在网络中抓取数据是具有关联性的抓取,它就像是一只蜘蛛一样在互联网中爬来爬去,所以我们很形象地将其称为是网络爬虫技术.其中网络爬虫也被称为是网络机器人或者是网络追逐者. 网络爬虫技术是搜索引擎架构中最为根本的数据技术,通过网络爬虫技术,我们可以将互联网中数以百亿计的网页信息保存到本地,形成一个镜像文件,为整个搜索引擎提供数据支撑. 1.