简单爬虫,只下载头像是女的图片
到一个网站,想把里面头像是女的图页下载下来,找到face++的人脸api ,识别还可以,下面是代码:
// defer.js
function defer() {
var resolve, reject;
var promise = new Promise(function() {
resolve = arguments[0];
reject = arguments[1];
});
return {
resolve: resolve,
reject: reject,
promise: promise
};
}
module.exports = defer;
// 以上是 defer 文件。
// 下面是 request文件
const _ = require('ramda'),
request = require('superagent'),
fs = require("fs"),
Promise = require("bluebird"),
Defer = require("./defer");
let index = _.range(1, 2000);
// 网址你自己找找,我就不提供了
let getUrl = x => `http://www.cctv.gov.cn/Per_Pic/PerPic_${x}.jpg`;
let face_key = "ca8922f075a28c43ef55ef36c7e619ad";
let face_secret = "_Q_I3Bq83AnUOfRNZod7RUUokEXFfigd"
let face_url = "https://apicn.faceplusplus.com/v2/detection/detect"
let detection = (url) => {
let defer = Defer();
request.get(face_url)
.query({ api_key: face_key })
.query({ api_secret: face_secret })
.query({ url: url })
.query({ attribute: "gender" })
.accept("json")
.end((err, res) => {
if (err || !res.ok) {
defer.reject(err);
} else {
defer.resolve(res.body);
}
})
return defer.promise;
}
let download = url => {
console.log(`start downloading : female : ${url}`);
let defer = Defer();
request
.get(url)
.redirects(0)
.end((err, res) => {
if (err || !res.ok || !Object.keys(res.body).length) {
defer.reject("err");
} else {
fs.writeFile(_.last(url.split("/")), res.body, (e) => {
if (e) {
defer.reject(e);
} else {
console.log(`end downloaded : female : ${url}`);
defer.resolve(null);
}
});
}
})
return defer.promise;
}
let getFemale = url =>
detection(url)
.then(
x => {
let result = _.pipe(_.prop("face"),
_.head,
_.prop("attribute"),
_.prop("gender"),
_.prop("value"))(x) === "Female";
if (result) {
return url;
} else {
return Promise.reject("err");
}
})
.then(download)
.catch(_ => console.log("male"))
Promise.mapSeries(index, (item, index, length) => _.pipe(getUrl, getFemale)(item)).then(_ => console.log("ok")).catch(_ => console.log('err'));
遍历网址没有做,毕竟不需要那么复杂。
8 回复
尖头函数的写法真是浑身不舒服啊,分号党,括号党应该还是比较喜欢那种让人安全的包裹感。
@captainblue2013 确实,之前在网上看的nodejs视频教程,里面的讲师一个分号都不写,看的特别难受
@captainblue2013 熟悉了,你会爱上她。
@htoooth 不会的,正如分号党不能接受没分号,不加几层括号把代码抱起来,我就觉得特别乱
@captainblue2013 只要合适的空行和空格,分号加也可不加也可。团队统一,就行了。
defer.reject() 和defer.resolve()可以用Promise.reject()和Promise.reslove()代替吗?
于是楼主获得了一堆二次元头像的抠脚大汉
@postgetme 不可以,Promise.reject() 和 Promise.reslove() 是生成一个 promise 的快捷方法,要使用的话: 第一种方案,直接返回:
return Promise.reject()`
第二种方案:在回调中使用中间变量,但是中间变量会变成null:
const test = () => {
let promise = null;
test1((errr,r)=>{
promise = Promise.reslove(r);
});
return promise;
}
// 如果test1是同步的话,promise 没有问题,如果是异步的话,promise 就是null;
使用 defer 的作用就是,(1)减少了一层缩进,(2)还有让 this 不变化,还在当前的环境中。