接前一篇文章:
我们想抓取的图片列表是这样的:
然后每个图片都能点,点进去后是 带分页的大图
一开始我的思路是遍历列表页,
然后去请求每个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: true22
}, (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: true7
}, (err, docs) => {8
if (err) {9
reject(err);10
return;11
}12
resolve();13
});14
}) 更新只是把当前对象的 isDownload 变成true 。最后放上项目地址


