酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

ASP.NET MVC 4でganrefをスクレイピングして、おねーさまを眺めれるようにしてみた。

元ネタ:Nancyでganrefをスクレイピングして、おねーさまを眺めれるようにしてみた。 - atelier:mitsuba

「ganref」っていうのが何かよくわかってないけど、おねーさまを眺めることができるサイトらしい。みつばたんのコードを参考にして、ASP.NET MVC 4用に書き換えてみました。

書いたコードはこんなかんじ。ソースコードは基本的にみつばたんの記事からのコピペなので、みつばたんが作ったサイトと同じ挙動になるはず。ちゃんと動いてなかったら教えてくださいな。

Controllers/GanrefController.cs

/ganref/でアクセスしたいので、Ganrefコントローラーを作成する。コントローラーの作成の仕方は「ASP.NET MVC 4で新規のプロジェクトを作成する - 酢ろぐ!」を参考にしてください。

using Sgml;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Xml.Linq;

namespace Test1.Controllers
{
    public class GanrefController : Controller
    {
        // GET: /Ganref/Lady/{id}
        public ActionResult Lady(int? id = null)
        {
            // ページ数の指定がなかったり0だったら1に遷移させる
            if (!id.HasValue || id.Value == 0)
            {
                return new RedirectResult("~/Ganref/Lady/1", false);
            }

            // アクセスするURLの組み立て
            var urlString = string.Format("http://ganref.jp/photo_searches/result/page:{0}/sort:created/direction:desc?", id);
            var param = new Dictionary<string, string>();
            param["keyword"] = "";
            param["parent_category"] = "%E4%BA%BA%E7%89%A9";
            param["category"] = "%E5%A5%B3%E6%80%A7";
            urlString += string.Join("&", param.Select(p => string.Format("{0}={1}", p.Key, p.Value)));

            // HTMLのパース処理(みつばたんの処理をそのまま)
            var xml = default(XDocument);
            using (var sgml = new SgmlReader() { Href = urlString, IgnoreDtd = true })
            {
                xml = XDocument.Load(sgml);
            }

            var ns = xml.Root.Name.Namespace;
            var imgroot = xml.Descendants(ns + "div")
                .Where(div => div.FirstAttribute.Value == "thumb140");
            var imgUrls = imgroot.Select(xElement =>
            {
                return xElement.Descendants(ns + "a")
                    .Descendants(ns + "img")
                    .Skip(2).First()
                    .FirstAttribute.Value;
            });

            // ビューに直接文字列のリストを投げてる
            return View(imgUrls);
        }
    }

}

典型的なスクレイピング。のいえさんのブログを参考にしたらしいです。SgmlReaderは本当に素晴らしいHTMLパーサーだと思います。

パースした結果(画像URLのリスト、imgUrls)をViewへ渡しています。

Views/Ganref/Lady.cshtml

次にView側で渡された画像URLのリストをどのように展開するか?ですが、foreach文で渡されたList<string>を取り出しaタグのsrcに詰めています。htmlを書いているはずなのに、C#な構文で書けるのは本当楽ですね。

@{
    ViewBag.Title = "Ganref Lady";
}

<h2>Ganref Lady</h2>

<p>
    <a href="https://blog.ch3cooh.jp/">解説記事</a>    
</p>
<p>
    <a href="http://c-mitsuba.hatenablog.com/entry/2014/07/15/024702">元ネタ</a>
</p>

@foreach (string uriString in Model)
{
    <img src="@uriString" />
}

……ってことで、出来上がったものがこちらです。