接前一篇文章:
我们想抓取的图片列表是这样的:
然后每个图片都能点,点进去后是 带分页的大图
一开始我的思路是遍历列表页,
然后去请求每个detail页, detail 做一个递归,最后把所有的图片都保存到一个 imgList里面。
然后保存并下载这个list。
但是实现后发现一个问题,就是有时候循环列表页的时候遇到某种异常报错了,比如说 第十个detail 可能有一个分页页面找不到。那我们只能再来一遍,这很不友好。
所以我决定每次爬取完一个detail后 ,都保存到数据库,然后再爬取下一个。这样即使中间断了,也损失不大,因为之前的你已经保存过了。
那下次开始的时候我先去数据库查询有没有未下载的图片,有的话直接下载,没有就开始继续爬。
安装mongodb请百度。接下来安装 node 驱动包 mongodb,
链接数据库操作:
数据库保存的字段类似这样:
[
2
{
3
url: '图片地址',
4
time: '保存时间',
5
isDownload: false //'是否下载到本地'
6
}
7
]
刚开始保存的时候 isDownload 都是 false, 等最后下载图片的时候,完成一个 就更新数据库把 isDownload 变成 true 代码类似这样
插入图片
insert(list){
2
return new Promise((resolve, reject) => {
3
this.getMongo().then((db) => {
4
let collection = db.collection(documents),
5
doneNum = 0;
6
let done = () => {
7
if (doneNum == list.length) {
8
resolve();
9
}
10
};
11
if(!list.length){
12
reject('图片列表为空');
13
return;
14
}
15
list.forEach(data =>{
16
collection.updateOne(data,{
17
$set: {
18
time: new Date().getTime()
19
}
20
},{
21
upsert: true
22
}, (err, docs) => {
23
if (err) {
24
reject(err);
25
return;
26
}
27
doneNum ++;
28
done();
29
});
30
});
31
})
插入的时候用的也是updateOne方法, 然后第三个参数upsert:true 表示没有就插入,有就更新。这样不会插入重复的图片
更新图片:
this.getMongo().then((db) => {
2
let collection = db.collection(documents);
3
collection.findOneAndUpdate(data, {$set: {isDownload: true}}, {
4
returnOriginal: false,
5
//sort: [[a,1]],
6
upsert: true
7
}, (err, docs) => {
8
if (err) {
9
reject(err);
10
return;
11
}
12
resolve();
13
});
14
})
更新只是把当前对象的 isDownload 变成true 。最后放上项目地址