--- title: jsoup使い方メモ tags: Java jsoup:1.7.3 Webスクレイピング author: opengl-8080 slide: false --- jsoup は Java で HTML の解析・編集を行うためのライブラリ。 URL を指定すれば実際の Web ページを解析のインプットに指定でき、タグの検索には CSS セレクタが使えるので、 Web スクレイピングをしたい時にとても便利。 #導入 Maven のセントラルリポジトリに jar がある。 ```groovy:build.gradle dependencies { compile 'org.jsoup:jsoup:1.7.3' } ``` #解析する HTML の指定 ##URL を指定して実際の Web ページをインプットにする ```java: package sample.jsoup; import java.io.IOException; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; public class Main { public static void main(String[] args) throws IOException { Document document = Jsoup.connect("http://www.google.co.jp").get(); System.out.println(document.html()); } } ``` ```text:実行結果 Google (以下略) ``` `Jsoup.connect("").get()` で、指定した URL に GET メソッドでアクセスし、結果をパースした `Document` オブジェクトを取得できる。 あとは、この `Document` オブジェクトから必要なタグを検索する。 ※HTTP のメソッドは GET と POST しか無いようなので、 RESTful API のクライアントとしては利用できないっぽい。([Connection.Method (jsoup 1.7.4-SNAPSHOT API)](http://jsoup.org/apidocs/org/jsoup/Connection.Method.html)) ###リクエストパラメータを設定する ```java: package sample.jsoup; import java.io.IOException; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; public class Main { public static void main(String[] args) throws IOException { Document document = Jsoup.connect("http://qiita.com/search") .data("q", "java") .get(); Elements elements = document.select(".brand, .page-title, .stats"); for (Element element : elements) { System.out.println(element.text()); } } } ``` ```text:実行結果 Qiita - プログラマの技術情報共有サービス javaの検索結果 856投稿 • 7163フォロワー ``` `data(String, String)` メソッドでリクエストパラメータを設定できる。 URL エンコードは内部でしてくれるので、全角文字もそのまま指定できる。 ##HTML 形式の文字列をインプットにする ```java: package sample.jsoup; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; public class Main { public static void main(String[] args) { String html = "
hoge

fuga

"; Document document = Jsoup.parse(html); System.out.println(document.html()); } } ``` ```text:実行結果
hoge

fuga

``` ##ローカルのファイルをインプットにする ```html:input.html test page

テストページです。

``` ```java: package sample.jsoup; import java.io.File; import java.io.IOException; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; public class Main { public static void main(String[] args) throws IOException { Document document = Jsoup.parse(new File("input.html"), "UTF-8"); System.out.println(document.html()); } } ``` ```text:実行結果 test page

テストページです。

``` #テキスト・ HTML を取得する ```html:input.html

Hoge

``` ```java: package sample.jsoup; import java.io.File; import java.io.IOException; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; public class Main { public static void main(String[] args) throws IOException { Document document = Jsoup.parse(new File("input.html"), "UTF-8"); Element hoge = document.getElementById("hoge"); System.out.println("[hoge.html()]\r\n" + hoge.html() + "\r\n"); Element fuga = document.getElementById("fuga"); System.out.println("[fuga.text()]\r\n" + fuga.text() + "\r\n"); Element piyo = document.getElementById("piyo"); System.out.println("[piyo.outerHtml()]\r\n" + piyo.outerHtml() + "\r\n"); } } ``` ```text:実行結果 [hoge.html()]

Hoge

[fuga.text()] Fuga Piyo [piyo.outerHtml()]
  • Piyo
  • ``` - `html()` メソッドで、そのタグの中身を HTML 形式の文字列で取得できる。 - `text()` メソッドで、そのタグの中身のうち、テキスト部分だけを抽出した文字列を取得できる。 - `outerHtml()` メソッドで、そのタグ自身を HTML 形式の文字列で取得できる。 #タグの検索 ##ID 指定で検索する ```html:input.html

    Hoge

    Fuga

    Piyo

    ``` ```java: package sample.jsoup; import java.io.File; import java.io.IOException; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; public class Main { public static void main(String[] args) throws IOException { Document document = Jsoup.parse(new File("input.html"), "UTF-8"); Element element = document.getElementById("hoge"); System.out.println(element.outerHtml()); } } ``` ```text:実行結果

    Hoge

    ``` ###その他検索用メソッド ID 以外にも、 class や属性指定、兄弟タグ、親タグ、タグ内のテキスト、など様々な検索用メソッドが用意されている。 とりあえず、 Element クラスの API はざっと目を通しておいた方がよさげ。 [Element (jsoup 1.7.4-SNAPSHOT API)](http://jsoup.org/apidocs/org/jsoup/nodes/Element.html) ##CSS セレクタを使って検索する ```html:input.html
    ERROR
    Fuga ``` ```java: package sample.jsoup; import java.io.File; import java.io.IOException; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; public class Main { public static void main(String[] args) throws IOException { Document document = Jsoup.parse(new File("input.html"), "UTF-8"); Elements elements = document.select("#hoge ul .error"); for (Element element : elements) { System.out.println(element.outerHtml()); } } } ``` ```text:実行結果
  • hoge
  • piyo
  • ``` `select(String cssQuery)` メソッドで、 CSS セレクタを使用した検索が可能。 使用できる CSS セレクタについては、以下の Selector クラスの API ドキュメントで説明されている。 [Selector (jsoup 1.7.4-SNAPSHOT API)](http://jsoup.org/apidocs/org/jsoup/select/Selector.html) ほとんどの場合普通の CSS セレクタと同じように使えるが、 `E[foo="bar"]` タイプのセレクタを使用するときだけ、以下のような違いがある。 ```html:input.html ``` ```java: package sample.jsoup; import java.io.File; import java.io.IOException; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.select.Elements; public class Main { public static void main(String[] args) throws IOException { Document document = Jsoup.parse(new File("input.html"), "UTF-8"); Elements elements = document.select("[name=HOGE]"); System.out.println(elements.outerHtml()); } } ``` ```text:実行結果 ``` 属性の値は __ダブルクォーテーション `"` で括ってはいけない__ 。 ( `"[name=\\"HOGE\\"]"` ではなく、 `"[name=HOGE]"` が正) おそらく、 Java のコード上ではダブルクォーテーションにエスケープが必要になるので、より簡潔に書けるようにこのような違いがあると思われる。 #プロキシ環境下で使う ##認証が不要な場合 ```java: package jsoup; import java.io.IOException; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; public class Main { public static void main(String[] args) throws IOException { System.setProperty("http.proxyHost", "プロキシホスト名"); System.setProperty("http.proxyPort", "プロキシポート"); Document doc = Jsoup.connect("http://www.google.co.jp").get(); } } ``` 認証が不要な場合は簡単で、システムプロパティにプロキシのホストとポートを設定してあげればいい。 ##認証が必要な場合 ```java: package jsoup; import java.io.IOException; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import java.net.Authenticator; import java.net.PasswordAuthentication; public class Main { public static void main(String[] args) throws IOException { // プロキシの設定(ホストとポート) System.setProperty("http.proxyHost", "プロキシホスト名"); System.setProperty("http.proxyPort", "プロキシポート"); // 認証情報の設定 Authenticator.setDefault(new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("ユーザー名", "パスワード".toCharArray()); } }); // Jsoup 取得し Document doc = Jsoup.connect("http://www.google.co.jp").get(); } } ``` #参考 - [jsoup Java HTML Parser, with best of DOM, CSS, and jquery](http://jsoup.org/) - [Java内でjQueryを使う!jsoup ::: Serendipity 2 future lies'n sundome. (´・ω・)](http://www.h3.dion.ne.jp/~alpha-pz/misc2763.html) - [jsoupでHTMLをパースする - するめとめがね](http://tm8r.hateblo.jp/entry/2013/11/26/125937) - [ウェブスクレイピング - Wikipedia](http://ja.wikipedia.org/wiki/%E3%82%A6%E3%82%A7%E3%83%96%E3%82%B9%E3%82%AF%E3%83%AC%E3%82%A4%E3%83%94%E3%83%B3%E3%82%B0) - [Selectors Level 3 | W3C](http://www.w3.org/TR/css3-selectors/#selectors) - [java - How can I configure HTTPClient to authenticate against a SOCKS proxy? - Stack Overflow](http://stackoverflow.com/questions/1388822/how-can-i-configure-httpclient-to-authenticate-against-a-socks-proxy) - [Jakarta Commons によるHTTP処理(HttpClient) - Java入門](http://www.syboos.jp/java/doc/jakarta-commons-httpclient.html) - [java - How to add proxy support to Jsoup (HTML parser)? - Stack Overflow](http://stackoverflow.com/questions/7482748/how-to-add-proxy-support-to-jsoup-html-parser) - [Java Proxy Authentication - Stack Overflow](http://stackoverflow.com/questions/8669726/java-proxy-authentication)