本文目标:执行脚本,可以自动请求大量图片地址,将图片下载到本地。
下载单张图片到本地
来直接动手!!!
新建个js文件,如single.js,里面放上下面的代码,然后node single.js就会看到同个文件夹下多了一个图片
let fs = require('fs')
let request = require('request')
let path = require('path')
// 下载单张图片 src是图片的网上地址 dest是你将这图片放在本地的路径 callback可以是下载之后的事}
const downloadImage = (src, dest, callback) => {
request.head(src, (err, res, body) => {
if (err) { console.log(err); return }
src && request(src).pipe(fs.createWriteStream(dest)).on('close', () => {
callback && callback(null, dest)
})
})
}
downloadImage('https://article-fd.zol-img.com.cn/t_s640x2000/g4/M06/06/0B/ChMly11592GIf2IZABGTyV_p7DgAAXpLwH8ztgAEZPh660.jpg', './就是这张图.jpg', (err, data) => { err ? console.log(err) : console.log(`下载成功!图片地址是:${path.resolve(data)}`) })
批量下载图片
理论上,循环上面的代码就可以批量下载图片,但是由于图片链接比较多,总是在下载到一部分图片后出现一些错误。所以批量的时候就借用一些工具。
async
建个文件夹multi吧,cd multi;npm init -y再npm i async,再建个async.js,放上下面的代码,然后node async.js就会看到同个文件夹下多了很多图片。
const async = require("async");
const request = require("request");
const fs = require("fs");
const path = require("path");
const downloadImage = (src, dest, callback) => {
request.head(src, (err, res, body) => {
if (err) {
console.log(err);
return;
}
src &&
request(src)
.pipe(fs.createWriteStream(dest))
.on("close", () => {
callback && callback(null, dest);
});
});
};
let imageLinks = [
{
title: "这才是未来大屏该有的样子",
url:
"https://article-fd.zol-img.com.cn/t_s640x2000/g1/M03/02/02/ChMljl2ENKuIV553AAKEYP9wZOQAAP23wGEctEAAoR4006.jpg"
},
{
title: "智慧屏",
url:
"https://article-fd.zol-img.com.cn/t_s640x2000/g1/M05/01/06/ChMljV1_QwqIEEeTACmpHidBeUkAAPz4QMudwgAKak2877.jpg"
}
];
const getSuffix = str => str.slice(str.lastIndexOf("."));
async.mapSeries(imageLinks, function(item, callback) {
setTimeout(function() {
var destImage = `${item.title}${getSuffix(item.url)}`;
destImage = `./dist/${destImage}`;
downloadImage(item, destImage, (err, data) => {
err ? console.log(err) : console.log(path.resolve(data));
});
callback && callback(null, item);
}, 100);
});
bagpipe
建个文件夹multi吧,cd multi;npm init -y再npm i async,再建个bagpipe.js,放上下面的代码,然后node bagpipe.js就会看到同个文件夹下多了很多图片。
// 这里粘贴 single.js里面的代码
let Bagpipe = require('bagpipe')
// 1表示同时发出多少个请求 timeout表示多长时间下载完 这里自定义吧
let bagpipe = new Bagpipe(1, { timeout: 5000 })
let imageLinks = [{ title: '这才是未来大屏该有的样子', url: 'https://article-fd.zol-img.com.cn/t_s640x2000/g1/M03/02/02/ChMljl2ENKuIV553AAKEYP9wZOQAAP23wGEctEAAoR4006.jpg' }, { title: '智慧屏', url: 'https://article-fd.zol-img.com.cn/t_s640x2000/g1/M05/01/06/ChMljV1_QwqIEEeTACmpHidBeUkAAPz4QMudwgAKak2877.jpg' }]
const getSuffix = str => str.slice(str.lastIndexOf('.'))
for (let i = 0; i < imageLinks.length; i++) {
let item = imageLinks[i]
let destImage = `${item.title}${getSuffix(item.url)}`
bagpipe.push(downloadImage, item.url, destImage, (err, data) => err ? console.log(err) : console.log(path.resolve(data)))
}
async和bagpipe都是很优秀的nodejs包,本身async功能十分强大,bagpipe使用起来简单方便,对原有的异步代码几乎不必做太多改动。因此可以根据自己喜好选择使用。
request
request很神奇,可以直接发起请求。正如上面看到的那样。这里简单说下使用方式。 任何响应都可以输出到文件流。默认是get请求。
将response写到本地文件里
const request = require('request')
const fs = require('fs')
// 直接写到文件里
request('https://www.baidu.com').pipe(fs.createWriteStream('baidu.html'))
// 也可以拿到响应体
request('https://www.baidu.com', (error, response, body) => {
if (!error && response.statusCode === 200) {
// 可以拿到响应体
console.log(body)
// 有兴趣的话 可以 npm i cheerio,cheerio可以对字符串进行类似于jquery的读取 这样能做更多的事
/*
const cheerio = require('cheerio')
const $ = cheerio.load(body)
console.log($('#btop').html())
console.log($('#btop').attr('href'))
*/
}
})
post
request支持application/x-www-form-urlencoded和multipart/form-data实现表单上传。
- x-www-form-urlencoded很简单:
// 这样可以爬虫某些接口
request.post('http://service.com/upload', {form:{key:'value'}},(error, response, body) => {
if (!error && response.statusCode === 200) {
// 可以拿到响应体
console.log(body)
}
})
- multipart/form-data也容易
var r = request.post('http://service.com/upload')
var form = r.form()
form.append('my_field', 'my_value')
form.append('my_buffer', new Buffer([1, 2, 3]))
form.append('my_file', fs.createReadStream(path.join(__dirname, 'doodle.png'))
form.append('remote_file', request('http://google.com/doodle.png'))