目录
0、使用到的库
cheerio、fs、axios、node-cmd
其中 fs 为 nodejs 内置的,不用下载;node-cmd 是用来执行Dos命令的,不是必须。
不使用 axios 也可以使用 nodejs 内置的 http、https模块;
const cheerio = require('cheerio'); // 爬虫
const fs = require('fs'); // 用于操作文件(文件下载到本地)
const axios = require('axios'); // 用于发送请求
const cmd = require('node-cmd'); // 用于执行 dos 命令
1、准备工作
物色好目标网站,在网站中打开控制台,使用元素查看器观察 img 类型元素的一般结构。
如示例目标网站 target 为 “xxxxxx”
目标 img 元素的一般结构可以确定为 li > a > img
2、请求网页内容
使用 axios 发送 GET 请求给该网页的地址,可以把该网页的源代码请求回来。
const targetURL = 'https://xxxxxxx';
// 请求目标网页
function getTarget(){
// 将指定的网页请求回来
axios.get(targetURL).then(res=>{
// 爬取 img 资源
cheerioAction(res.data);
}).catch(err=>{
console.log(err);
})
}
3、爬取目标资源
使用 cheerio 解析该网页的源代码,将所需要的 img 标签(all)获取到,然后将 img 元素中的 src 属性值解析出来,添加到一个预先定义的数组中。
// 爬出所有图片的src
function cheerioAction(HtmlData){
// 加载当前网页资源
const $ = cheerio.load(HtmlData);
// 获取到所有 li > a > img 标签
/*
arr 是一个对象,设获取到的img有2项,则可用的资源为
{
'0':{第一个img元素相关的内容},
'1':{第二个img元素相关的内容},
...
}
*/
let arr = $('li a img');
let srcArr = [];
for(let i = 0 ; i < arr.length ; i ++){
// 把 img 元素中的 src 内容提取出来,加入到数组中
srcArr.push(arr[i + ''].attribs.src);
}
// 创建一个新的目录,然后开始下载图片到该目录下
createDir((dir)=>{
downloadImg(srcArr, dir, 0);
});
}
4、创建一个新的目录
下载图片资源前,先使用 fs.mkdir 方法创建一个新的目录,以当前的时间戳命名。
当文件夹创建成功,调用 cmd.run 方法(异步)打开文件资源管理器,显示到新创建的文件夹下观察图片的下载。同时执行回调函数将图片下载到该文件夹中。
Explorer /root, D:\dirA\dirB 表示进入到D盘 dirA / dirB 的目录下
Explorer /select, D:\dirA\dirB 表示进入到D盘 dirA目录下,并默认选中 dirB 目录
// 创建一个文件夹专门存放图片
function createDir(callback){
// 使用当前时间戳来命名文件夹
let time = new Date().getTime();
let dir = './' + time;
fs.mkdir(dir, (err)=>{
// 创建文件夹成功
if(!err){
// 执行cmd命令,打开资源管理器到该文件夹目录下,观察图片下载
cmd.run(`Explorer /root,${process.cwd()}\\${time}`,(err, data, stderr)=>{
if(err){
console.log(err);
}
})
// 回调函数,下载图片到指定文件夹中
callback(dir);
}else{
console.log('make dir fail');
}
})
}
5、下载图片资源到文件夹中
当使用 axios 请求图片时,设置返回的类型为二进制:responseType : "arraybuffer";
使用 fs.writeFile() 方法下载图片时,同样设置为二进制的格式:'binary'
// 批量下载图片到指定文件夹中
function downloadImg(srcArr, dir, index){
let url = srcArr[index];
axios.get(url, {
// 设置返回的类型是二进制
responseType:'arraybuffer',
}).then(res =>{
// 下载当前图片文件到文件夹中
fs.writeFile(`${dir}/${index}.png`, res.data, 'binary', (err)=>{
if(err){
console.log(`${index} error`,err);
}else{
console.log(`${index} finish`);
if(index < srcArr.length){
// 如果还有图片资源,则继续下载
downloadImg(srcArr, dir, index + 1);
}else{
console.log('all picture download finished');
}
}
})
})
}
6、开始工作
getTarget();
7、参考资料
[1] Welcome to Cheerio! | cheerio