jsoupを使ってみたメモ（Yahoo!ニュース トピックス一覧取得）

# jsoup
Javaで HTML のパースを行うためのライブラリ。
公式サイトの [Cookbook](http://jsoup.org/cookbook/) がシンプルで分かりやすいです。

CSS, jQuery のセレクタっぽい探索が可能なので比較的使いやすそう。

# 作ってみたコード
Yahoo!ニュースのトピックス一覧ページから指定した日付のトピックス一覧を取得。
利用価値ない気がしますがJSON形式で出力もします。

```java:Topic.java
package ksugimori.sample.jsoup;

public class Topic {
    private String title;
    private String url;
    private String category;
    private String date;

    /**
     * Constructor
     */
    public Topic(String title, String url, String category, String date) {
        this.title = title;
        this.url = url;
        this.category = category;
        this.date = date;
    }

    public String toString() {
        StringBuilder s = new StringBuilder();
        s.append(String.format(" Title   : %s%n", this.title));
        s.append(String.format(" Category: %s%n", this.category));
        s.append(String.format(" Date    : %s%n", this.date));
        s.append(String.format(" URL     : %s%n", this.url));
        return s.toString();
    }

    public String toJSON() {
        String keyValFormat = "\"%s\": \"%s\"";
        StringBuilder s = new StringBuilder();
        s.append("{");
        s.append(String.format(keyValFormat, "title"   , this.title   )).append(", ");
        s.append(String.format(keyValFormat, "url"     , this.url     )).append(", ");
        s.append(String.format(keyValFormat, "category", this.category)).append(", ");
        s.append(String.format(keyValFormat, "date",     this.date    ));
        s.append("}");

        return s.toString();
    }
}
```

```java:YahooTopicsParser.java
package ksugimori.sample.jsoup;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class YahooTopicsParser {
    public static final String DATE_FORMAT = "yyyyMMdd";
    public static final String URL = "http://news.yahoo.co.jp/list/";

    /**
     * 指定した日付の Topics を取得します
     * 
     * @param date 対象日付
     * @return Topic のリスト
     */
    public static List<Topic> parseAll(Date date) {
        String dateStr = new SimpleDateFormat(DATE_FORMAT).format(date);

        try {
            Document doc = Jsoup.connect(URL).data("d", dateStr).get(); // リクエストパラメータを Connection.data() で指定 
            Elements topicElements = doc.select("ul.list li"); // Topics のリストを抽出
            List<Topic> topicList = new ArrayList<Topic>();
            for (Element element : topicElements) {
                topicList.add(parse(element));
            }
            return topicList;
        } catch (IOException e) {
            System.out.println("Something wrong.");
            return Collections.emptyList();
        }
    }

    /**
     * １トピックの内容を取得します
     * 
     * @param element 
     * @return Topic オブジェクト
     */
    private static Topic parse(Element element) {
        String title = element.select("span.ttl").first().text();
        String url = element.select("a").first().attr("href");
        String category = element.select("span.cate").first().text();
        String date = element.select("span.date").first().text();

        return new Topic(title, url, category, date);
    }
}
```

```java:Main.java
package ksugimori.sample.jsoup;

import java.util.Date;

public class Main {
    public static void main(String[] args) {
        Date today = new Date();
        for (Topic topic : YahooTopicsParser.parseAll(today)) {
            System.out.println(topic.toJSON());
            System.out.println(topic);
        }
    }
}
```

#出力例
```
{"title": "野生トキ 今季初の抱卵始まる", "url": "http://news.yahoo.co.jp/pickup/6195256", "category": "科学", "date": "2016年3月21日 22時21分"}
 Title   : 野生トキ 今季初の抱卵始まる
 Category: 科学
 Date    : 2016年3月21日 22時21分
 URL     : http://news.yahoo.co.jp/pickup/6195256

...
```