如果我们想:如果能够获取翻页数据,那数据不就丰富了。这里也可以解决这个问题。

本程序在上一篇文章爬虫程序写入mongodb中的程序依赖中增加eventproxy包,请自行创建node项目并安装,推荐使用webstorm直接创建一个node.js express App。

eventproxy是管理异步操作的一个npm包,

1.引入依赖模块

1
2
3
4
5
6
7
8
9
10
11
12
//导入包
const http = require("http");
const path = require("path");
const url = require("url");
const fs = require("fs");

const eventproxy = require('eventproxy');
const mongoose = require("mongoose");
const superagent = require("superagent");
const cheerio = require("cheerio");

const ep = eventproxy();

2.连接数据库,建数据模型

推荐使用MongoDB可视化工具Studio 3T,安装MongoDB数据库自行参考网上资料。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//连接本地mongodb数据库Douban
var mongourl = 'mongodb://localhost/DBBook';
mongoose.connect(mongourl);
var Schema = mongoose.Schema;
//创建模型
var topBookSchema = new Schema({
title: String,
enTitle: String,
bookId: Number,
copyrightInfo: String,
grade: String,
remark: String,
bookImg: String,
description: String
});
var TopBook = mongoose.model('topBook', topBookSchema, 'topbooklist');

3.初始化结果数组和url数组

1
2
3
4
5
6
7
8
9
//存放结果和url数组的
let resultArr = [];
let desUrlList = [];

//页码拼接url遍历
for (let i = 1; i <= 10; i++){
let pageIndex = 25*(i-1);
desUrlList.push(`https://book.douban.com/top250?start=${pageIndex}`);
}

4.遍历url数组,调用superagent的get方法和end方法处理

get(): 此方法参数为获取数据的链接
end(): 此方法第一的参数为error对象,第二个参数为get中页面的所有DOM结果

1
2
3
4
5
6
7
for (let desUrl of desUrlList){
superagent
.get(desUrl)
.end((error, response)=>{
// ...5...
})
}

5.分析结构,提取相应的数据,派发异步事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
if(error) console.log(error);

//获取页面文档数据
var content = response.text;

//cheerio也就是node下的jquery 将整个文档包装成一个集合,定义一个$接收
var $ = cheerio.load(content);

//分析文档结构 先获取每个li 再遍历里面的内容(此时每个li里面就存放着我们想要获取的数据)
$(".indent table").each(function(index,value){

//提取url链接中的id
var address = $(value).find(".item td a").attr("href");
var bookId = address.replace(/[^0-9]/ig,"");

//将获取的数据以对象的形式添加到数组中
var oneBook = {
title: $(value).find(".item td .pl2 a").text().replace(/\ +/g,"").replace(/[\r\n]/g,""),
enTitle: $(value).find(".item td .pl2 span").text(),
bookId: bookId,
copyrightInfo: $(value).find(".item td p.pl").text(),
grade: $(value).find(".item td .star .rating_nums").text(),
remark: $(value).find(".item td .star .pl").text().replace(/\ +/g,"").replace(/[\r\n]/g,""),
bookImg: $(value).find(".item td .nbg img").attr("src").replace(/^https:/g,""),
description: $(value).find(".item td .quote .inq").text()
};

resultArr.push(oneBook);
//将每个书本信息实例化到newBook模型中
var topBook = new TopBook(oneBook);

//保存到mongodb
topBook.save(function(err){
if(err){
console.log('保存失败:'+ err);
return;
}
console.log("OK!");
});

ep.emit('allBooks',oneBook); //派发一个事件

});

ep是eventproxy的实例,这里通过emit()方法派发一个事件allBooks,用来监测oneBook数据,当一个oneBook数据源抓取完毕,就会告诉ep一个数据源抓取完成。

6.在所以异步操作执行完后执行某些处理

1
2
3
4
// 此代码放于for循环后
ep.after('allBooks',desUrlList.length,function () {
//......
});

完整代码请参考:https://github.com/joydezhong/SimpleCrawler/blob/master/pageEventproxy.js