- 爬虫步骤:
- 获取目标网站 http.get
- 分析网站内容 cheerio,可以使用jQuery选择器
- 获取有效信息
一. 下面是一个数据分片传输的小例子,仅供热身:
const http=require('https');
let url = 'https://www.jd.com/'
http.get(url,(res)=>{
// 数据分段,只要接受数据就会触发data事件,chunk就是每次接受的数据片段
res.on('data',(chunk)=>{
console.log('数据传输');
})
// end表示数据流传输完毕
res.on('end',()=>{
console.log('数据传输完毕');
})
}).on('error',()=>{
console.log('请求错误');
})
数据量比较大的话会分片传输
二. 下面就把京东的首页给扒下来,存到jd.html文件中:
const http=require('https');
const fs=require('fs');
let url = 'https://www.jd.com/'
http.get(url,(res)=>{
let rawDate='';
// 数据分段,流式传输,只要接受数据就会触发data事件,chunk就是每次接受的数据片段
res.on('data',(chunk)=>{
console.log('数据传输');
rawDate += chunk.toString('utf8');
})
// end表示数据流传输完毕
res.on('end',()=>{
console.log('数据传输完毕');
// 将请求的数据保存到本地
fs.writeFileSync('./jd.html',rawDate);
})
}).on('error',()=>{
console.log('请求错误');
})
三. 进一步加上判断:
const http=require('https');
const fs=require('fs');
let url = 'https://www.jd.com/'
http.get(url,(res)=>{
//-----------------新加的判断,不是我想要的就终止爬取----------------------------
// 安全判断
const { statusCode } = res; // es6赋值方法,同'statusCode=res.statusCode',表示状态码
const contentType = res.headers['content-type']; // 判断文件类型
console.log(statusCode,contentType);
let err=null;
if(statusCode!==200){
err=new Error('请求状态错误')
}else if(!/^text\/html/.test(contentType)){ // 用正则表达式来判断是不是我们想要的类型
err=new Error('请求类型错误')
}
if(err){
console.log(err);
res.resume(); // 重置缓存
return false;
}
//---------------------------------------------------------------------------
let rawDate='';
// 数据分段,流式传输,只要接受数据就会触发data事件,chunk就是每次接受的数据片段
res.on('data',(chunk)=>{
console.log('数据传输');
rawDate += chunk.toString('utf8');
})
// end表示数据流传输完毕
res.on('end',()=>{
console.log('数据传输完毕');
// 将请求的数据保存到本地
fs.writeFileSync('./jd.html',rawDate);
})
}).on('error',()=>{
console.log('请求错误');
})
四. cheerio
cheerio是jquery核心功能的一个快速灵活而又简洁的实现,主要是为了用在服务器端需要对DOM进行操作的地方
安装cheerio
npm install cheerio --save
去npm的官网查询对应的文档:
https://www.npmjs.com/
https://www.npmjs.com/package/cheerio
cheerio的简单使用实例:
const cheerio = require('cheerio');
let $ = cheerio.load('<div><p>你好</p><img src="http://img0.imgtn.bdimg.com/it/u=1734221205,4211923994&fm=214&gp=0.jpg"></div>')
console.log($('img').attr('src'));
console.log($('p').text());
就是用jQuery的语法,要是有多个img标签,可以这样写:
const cheerio = require('cheerio');
let $ = cheerio.load('<div><p>你好</p><img src="http://www.baidu.com"><img src="http://www.taobao.com"></div>')
$('img').each((index,el)=>{
console.log($(el).attr('src'));
})
五. 爬呀爬
完整代码如下,很多图片没爬到,爬到的都是html文件中的静态图片。
const http=require('https');
const fs=require('fs');
const cheerio=require('cheerio')
const request=require('request')
let url = 'https://www.jd.com/'
http.get(url,(res)=>{
// 安全判断
const { statusCode } = res; // es6赋值方法,同'statusCode=res.statusCode',表示状态码
const contentType = res.headers['content-type']; // 判断文件类型
console.log(statusCode,contentType);
let err=null;
if(statusCode!==200){
err=new Error('请求状态错误')
}else if(!/^text\/html/.test(contentType)){ // 用正则表达式来判断是不是我们想要的类型
err=new Error('请求类型错误')
}
if(err){
console.log(err);
res.resume(); // 重置缓存
return false;
}
let rawDate='';
// 数据分段,流式传输,只要接受数据就会触发data事件,chunk就是每次接受的数据片段
res.on('data',(chunk)=>{
console.log('数据传输');
rawDate += chunk.toString('utf8');
})
// end表示数据流传输完毕
res.on('end',()=>{
console.log('数据传输完毕');
// 通过cheerio进行分析
let $=cheerio.load(rawDate) // 将请求到的网页数据进行转化
$('img').each((index,el)=>{
// console.log($(el).attr('src'))
let imgurl=$(el).attr('src');
// 有的链接没有http头,给他加上
if(imgurl.indexOf('http')==-1){
imgurl="http:"+imgurl
}
// imgname=imgurl.match(/\{1}[0-9a-zA-Z]+/.png)
// console.log(imgname)
request.head(imgurl,function(err,res,body){
if(err){
console.log(err);
}
});
console.log(imgurl)
// 将图片保存到本地
request(imgurl).pipe(fs.createWriteStream('./'+ index + ".png"));
})
// // 将请求的数据保存到本地
// fs.writeFileSync('./jd.html',rawDate);
})
}).on('error',()=>{
console.log('请求错误');
})
网友评论