2012-03-04

いかにしておっぱい画像をダウンロードするか〜2012 for Node.js


いかにしておっぱい画像をダウンロードするか〜2012 の Node.js 実装です。
こういう動機で頑張るっていうのはいつまでも少年時代であろうとしていていいよね!うちの場合もそれをゲームへ向けたわけだし。

動作には npm で request と async を導入する必要あり。
Node.js の場合、何も考えずに書いてしまうと逆に並列処理が走り過ぎて落ちて終わってしまうという。
ということで async を使って並列処理数の制限を行っている。

2012-03-06 追記
ファイルが既に存在している際に callback が呼ばれずに次のタスクへ進まないという不具合があった。コード修正。


var request = require('request');
var querystring = require('querystring');
var async = require('async');
var crypto = require('crypto');
var fs = require('fs');
var path = require('path');

var appid = '';
var uri = 'http://api.bing.net/json.aspx?';
var dir = './data';

var page_count = 0;
var download_count = 0;

var md5hex = function (str) {
  var md5 = crypto.createHash('md5');
  md5.update(str, 'utf8');
  return md5.digest('hex');
};

(function Oppai() {
  var offset = page_count * 50;
  var params = querystring.stringify({
    Appid : appid,
    Version : '2.2',
    Markert : 'ja-JP',
    Sources : 'Image',
    'Image.Count' : 50,
    'Image.Offset' : offset,
    Adult : 'off',
    Query : 'おっぱい'
  });

  request(uri + params, function (err, res, body) {
    if (err) throw err;

    var ref = JSON.parse(body);
    if (ref.SearchResponse.Image) {
      var results = ref.SearchResponse.Image.Results;
      async.forEachLimit(results, 10, function (result, callback) {
        var url = result.MediaUrl;
        if (url.match(/\.jpg$/)) {
          var filename = md5hex(url) + '.jpg';
          var filepath = dir + '/' + filename;

          path.exists(filepath, function (exists) {
            if (!exists) {
              var output = fs.createWriteStream(filepath);
              output.on('close', function () {
                callback();
              });

              download_count += 1;
              request(url).pipe(output);
              console.log(download_count + ' : Download... ' + url);
            } else {
              callback();
            }
          });
        }
      });

      page_count += 1;
      process.nextTick(Oppai);
    }
  });
})();