简单爬虫,只下载头像是女的图片
发布于 9 年前 作者 htoooth 5416 次浏览 最后一次编辑是 8 年前 来自 分享

到一个网站,想把里面头像是女的图页下载下来,找到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 不变化,还在当前的环境中。

回到顶部