yutopp's blog

サンドバッグになりたい

いかにしておっぱい画像をダウンロードするか~2012 Dart編

(こんなこと書いてブログのカテゴリ変わったりしないよね?ね?)

元凶

いかにしておっぱい画像をダウンロードするか〜2012 - ゆーすけべー日記
いかにしておっぱい画像をダウンロードするか〜2012 Haskell編 - 厨二病患者のプログラミング入門
D言語でいかにしておっぱい画像をダウンロードするか〜2012 — Gist
いかにしておっぱい画像をダウンロードするか〜2012 をC#で書きました - モデラート - C#とゲーム開発と雑記

そんなわけで

最近流行り(ステマ)のDartで書けないかなーと試してみました!背徳感がすごいですね!
所々エラー処理は省きました。
(DartEditor build5759、Server applicationで動かせます。dataフォルダの作成と、Bing APIのAppIdの設定を忘れずに~)

(追記)

こうですか、分かりません><

#import("dart:io");
#import("dart:uri");
#import("dart:utf",prefix:"utf");
#import("dart:json");

class Url {
  static String encodeUtf8(final String src) => _encode(src, (s)=>utf.encodeUtf8(s));

  static String _encode(final String rawSrc, List f(final String)) =>
    new String.fromCharCodes((final List src, List dst) {
          src.forEach(
            (c) =>
              dst.addAll(
                ((c >= 65/*'A'*/ && c <= 90/*'Z'*/) || (c >= 97/*'a'*/ && c <= 122/*'z'*/) || (c >= 48/*'0'*/ && c <= 57/*'9'*/) || c == 45/*'-'*/ || c == 95/*'_'*/ || c == 46/*'.'*/ || c == 126/*'~'*/)
                ? [c]
                : [37/*%*/, c.toRadixString(16).charCodes()[0], c.toRadixString(16).charCodes()[1]]
                )
              );
          return dst;
        }(f(rawSrc), new List())
      );
}

void main() {
  final String baseDir = "data";
  final String AppId = "~ここにAppIdを入力~";
  final int perDownloadNum = 10;
  final int maxDownloadNum = 50;
  final String word = "おっぱい";

  int downloadedCount = 0;
  for (int i=0; i<maxDownloadNum/perDownloadNum; ++i) {
    final String queryString = (Map<String, String> q) {
      StringBuffer sb = new StringBuffer();
      q.forEach((k,v) => sb.add("${k}=${v}&"));
      return sb.toString().substring(0, sb.length - 1);
    }({
      "AppId" : AppId,
      "Version" : "2.2",
      "Markert" : "ja-JP",
      "Sources" : "Image",
      "Image.Count" : "${Math.min(maxDownloadNum-i*perDownloadNum, perDownloadNum)}",
      "Image.Offset" : "${i*perDownloadNum}",
      "Adult" : "off",
      "Query" : Url.encodeUtf8( word )
    });
    
    final client = new HttpClient().getUrl(new Uri(scheme: "http", domain: "api.bing.net", path: "/json.aspx", query: queryString));
    client.onResponse = (HttpClientResponse res) {
      StringBuffer resStringBuf = new StringBuffer();
      
      res.inputStream.onData = () =>
        resStringBuf.add(new String.fromCharCodes(res.inputStream.read()));
        
      res.inputStream.onClosed = () =>
        JSON.parse(resStringBuf.toString())["SearchResponse"]["Image"]["Results"].forEach((v) =>
          ((Uri path) =>
            new HttpClient().getUrl(path).onResponse = (HttpClientResponse r) {
              try {
                final ext = const RegExp(@"\w+$").firstMatch(r.headers["content-type"])[0];
                if (ext == "jpeg" || ext == "png" || ext == "gif") {
                  final String filename = const RegExp(@".+/(.+?)\..+$").firstMatch(path.toString())[1];
                  final File file = new File("$baseDir/$filename.$ext");
                  final fileStream = file.openOutputStream();
                  r.inputStream.pipe(fileStream);
                  r.inputStream.onClosed = () => file.create(() => fileStream.close());
                  
                  print("${++downloadedCount}. ダウンロード! : $baseDir/$filename.$ext");
                }
              } catch(NullPointerException e) {
                print("error.");
              }
            }
          )(new Uri.fromString(v["MediaUrl"]))
        );
    };
  }
}

いい感じですね!さぁ、Dart使いましょう!!


(昔の)

#import("dart:io");
#import("dart:uri");
#import("dart:utf");
#import("dart:json");

class Url {
  static String encode( final String src )
  {
    List ls = <int>[];
    for( final int c in encodeUtf8( src ) ) {
      if ( ( c >= 65/*'A'*/ && c <= 90/*'Z'*/ ) || ( c >= 97/*'a'*/ && c <= 122/*'z'*/ ) ||
          ( c >= 48/*'0'*/ && c <= 57/*'9'*/ ) ||
            c == 45/*'-'*/ || c == 95/*'_'*/ || c == 46/*'.'*/ || c == 126/*'~'*/ )
      {
        ls.add( c );
      } else {
        ls.add( 37/*%*/ );
        ls.addAll( c.toRadixString(16).charCodes() );
      }
    }

    return new String.fromCharCodes( ls );
  }
}

void main() {
  final String baseDir = "data";
  final int perDownloadNum = 10;
  final int maxDownloadNum = 50;
  final String word = "おっぱい";
  
  int downloadedCount = 0;
  for ( int i=0; i<maxDownloadNum/perDownloadNum; ++i ) {
    final Map<String, String> query = {
      "AppId" : "~ここにAppIdを入力~",
      "Version" : "2.2",
      "Markert" : "ja-JP",
      "Sources" : "Image",
      "Image.Count" : "${Math.min(maxDownloadNum-i*perDownloadNum, perDownloadNum)}",
      "Image.Offset" : "${i*perDownloadNum}",
      "Adult" : "off",
      "Query" : Url.encode( word )
    };
    
    StringBuffer sb = new StringBuffer();
    query.forEach( (k,v) => sb.add("${k}=${v}&") );
    final String queryString = sb.toString().substring( 0, sb.length - 1 );
    
    final String uri = "http://api.bing.net/json.aspx?${queryString}";    
    final client = new HttpClient().getUrl( new Uri.fromString( uri ) );
    client.onResponse = ( HttpClientResponse res ) {
        StringBuffer resStringBuf = new StringBuffer();
        res.inputStream.onData = () {
          resStringBuf.add( new String.fromCharCodes( res.inputStream.read() ) );
        };
        
        res.inputStream.onClosed = () {       
          final resJson = JSON.parse( resStringBuf.toString() );
          
          for( final Map v in resJson["SearchResponse"]["Image"]["Results"] ) {
            final Uri imageUri = new Uri.fromString( v["MediaUrl"] );
            final picClient = new HttpClient().getUrl( imageUri );
            picClient.onResponse = ( HttpClientResponse r ) {
              try {
                ++downloadedCount;
                final String ext = r.headers["content-type"].replaceAll( const RegExp(@"(\w+)/"), "");
                  
                if ( ext == "jpeg" || ext == "png" || ext == "gif" ) {
                  final String filename = imageUri.path.replaceAll( const RegExp(@"(\w+/)"), "" ).replaceAll( const RegExp(@"/"), "" ).replaceAll( const RegExp(@"(\.\w+)"), "" );
                  print( "$downloadedCount : ダウンロード! : ${baseDir}/${filename}.${ext}" );

                  final File file = new File( "${baseDir}/${filename}.${ext}" );
                  final fileO = file.openOutputStream();
                  r.inputStream.pipe( fileO );
                  r.inputStream.onClosed = () => file.create( () => fileO.close() );
                }
                
              } catch( NullPointerException e ) {
                print( "error." );
                
              }
            };
            
          }
        };
        
      };  
  }
}