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
我们获得的内容为#pins > li:nth-child(1) > a
可以看出我们想要的数据保存在id为pins的标签下的列表中
//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
文件中了
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。