いかにしておっぱい画像をダウンロードするか〜2012 をC#で書きました

元ネタ
いかにしておっぱい画像をダウンロードするか〜2012


他にもいくつかの言語で書かれています。
http://d.hatena.ne.jp/D_Rascal/20120320/1332244651


Bing API の制限?があるらしく、ダウンロード枚数が1000枚に届く前に終了してしまいます。

依存ライブラリ

DynamicJson 1.2.0.0
Interactive Extensions 1.1.10621

Program.cs

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web;
using System.Web.Security;
using Codeplex.Data;

namespace App
{
    class Program
    {
        static void Main()
        {
            const string appid = "";
            const string dir = "./data";
            Directory.CreateDirectory(dir);
            const int num = 50;

            foreach (var response in Enumerable.Range(0, int.MaxValue)
                .Select(_ => (long)_ * 50)
                .Select(page =>
                {
                    var q = HttpUtility.ParseQueryString(string.Empty);
                    q.Add(new NameValueCollection
                        {
                            {"AppId", appid},
                            {"Version", "2.2"},
                            {"Markert", "ja-JP"},
                            {"Sources", "Image"},
                            {"Image.Count", num.ToString(CultureInfo.InvariantCulture)},
                            {"Image.Offset", page.ToString(CultureInfo.InvariantCulture)},
                            {"Adult", "off"},
                            {"Query", "おっぱい"}
                        });
                    return q;
                })
                .Select(q => new Uri("http://api.bing.net/json.aspx?" + HttpUtility.UrlDecode(q.ToString())))
                .Select(WebRequest.CreateDefault)
                .Select(_ => _.GetResponse()))
            {
                string[] urls = EnumerableEx.Using(
                    response.GetResponseStream,
                    stream => (IEnumerable<string>)ToUrls(DynamicJson.Parse(stream)))
                    .ToArray();
                if (!urls.Any())
                {
                    Console.WriteLine("error");
                    return;
                }

                Parallel.ForEach(
                    urls.Select(_ => new
                    {
                        url = _,
                        ext = Path.GetExtension(_),
                        fileName = Path.Combine(dir,
                                                FormsAuthentication.HashPasswordForStoringInConfigFile(
                                                    HttpUtility.UrlEncode(_), "md5") +
                                                Path.GetExtension(_))
                    })
                    .Where(_ => new[] {".jpg", ".jpeg", ".png", ".gif", ".bmp"}.Contains(_.ext)),
                    s =>
                    {
                        Console.WriteLine(s.url);
                        try
                        {
                            using(var wc = new WebClient())
                                wc.DownloadFile(s.url, s.fileName);
                        }
                        catch { }
                    });
            }
        }
        static IEnumerable<string> ToUrls(dynamic source)
        {
            if (source.IsDefined("SearchResponse") &&
                source.SearchResponse.IsDefined("Image") &&
                source.SearchResponse.Image.IsDefined("Results"))
            {
                foreach(var _ in source.SearchResponse.Image.Results)
                {
                    if (!_.IsDefined("MediaUrl")) continue;
                    yield return _.MediaUrl;
                }
            }
        }
    }
}