Node.JS的异步I/O特性很适合I/O密集型任务,再加上JQuery的HTML解析加成,制作简单的网络爬虫非常容易,性能也在可以接受的水平
将用到的知识
基本网络请求
JQuery Selector
fs 文件操作
准备
首先我们安装所需的依赖
superagent
nodejs里一个非常方便的客户端请求代理模块superagent-charset
支持更多字符集部分情况可能用到(此例中暂不使用)cheerio
与jQuery类似的API,用于解析HTML
分析网页与爬虫实现
列表页
http://www.mzitu.com/
示例详情页
http://www.mzitu.com/71235
这里我们使用Paw
这款Mac上常用的接口调试软件来测试一下主页(功能与Postman类似)
可以看到,访问一切正常,接下来我们进行列表的抓取,
函数原型为function catch_list(url,callback)
首先require
一下基本模块 var superagent = require('superagent-charset')(require('superagent'));var cheerio = require('cheerio');var fs= require('fs');var path = require('path');var main_url = 'http://www.mzitu.com/';var meiziURL = 'http://www.mzitu.com/71235';
网络请求
在函数中编写基本的网络请求
function catch_list(url,callback) { superagent .get(url) .end(function (err,sres) { if(err){ console.error(err) } console.log(sres) })}
调用函数,尝试访问,获得了一个Forbidden错误
由此可知网站对于访问进行了检查,我们复制Paw的请求头,重写网络请求function catch_list(url,callback) { superagent .get(url) .set('Connection','close') .set('User-Agent','Paw/2.1 (Macintosh; OS X/10.11.6) GCDHTTPRequest') .set('Host', 'www.mzitu.com') .end(function (err,sres) { if(err){ console.error(err) } console.log(sres) })}
HTML解析
这次访问到了数据,我们开始进行网页解析
关于网页的解析,我们可以借助Chrome直接获得元素的Selector//sres.text 里面存储着网页的 html 内容,将它传给 cheerio.load 之后// 就可以得到一个实现了 jquery 接口的变量,我们习惯性地将它命名为 `$`var $ = cheerio.load(sres.text)$('#pins').find('li').each(function (idx,element) { $element = $(element) var url = $element.find('span:nth-child(2) > a').attr('href') var title = $element.find('img').attr('alt') console.log(title,url)})
函数完成
接下来我们观察控制台已经输出了我们需要的内容
我们来将内容放进数组,通过callback传回function catch_list(url,callback) { superagent .get(url) .set('Connection','close') .set('User-Agent','Paw/2.1 (Macintosh; OS X/10.11.6) GCDHTTPRequest') .set('Host', 'www.mzitu.com') .end(function (err,sres) { if(err){ console.error(err) } var items = [] var $ = cheerio.load(sres.text) $('#pins').find('li').each(function (idx,element) { $element = $(element) var url = $element.find('span:nth-child(2) > a').attr('href') var title = $element.find('img').attr('alt') console.log(title,url) items.push({ title:title, url:url }) }) callback(items) })}
数据的本地保存
我们可以看到,这个网站内容非常多,所以我们考虑保存下每个图集的title和url到本地json文件
function write_to_file_in_JSON(items,dir,filename) { console.log('完成'+items.length +'个抓取'); var fs= require('fs'); var dirname = dir +filename+'.json'; var path = require('path'); fs.writeFile(dirname, JSON.stringify(items));}for (var i = 1;i<=127;i++){ var success = 1 var data = [] catch_list(main_url+'page/'+String(i),function (items) { console.log(items.length) data = data.concat(items) success++ if (success == 2) write_to_file_in_JSON(data,'/Users/xxx/Desktop/','妹子图') })}
这时我们已经将每一个图集的基本信息存储到了桌面上的妹子图.json
文件中了