Edited at

jsoup使い方メモ

More than 5 years have passed since last update.

jsoup は Java で HTML の解析・編集を行うためのライブラリ。

URL を指定すれば実際の Web ページを解析のインプットに指定でき、タグの検索には CSS セレクタが使えるので、 Web スクレイピングをしたい時にとても便利。


導入

Maven のセントラルリポジトリに jar がある。


build.gradle

dependencies {

compile 'org.jsoup:jsoup:1.7.3'
}


解析する HTML の指定


URL を指定して実際の Web ページをインプットにする

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());
}
}


実行結果

<!DOCTYPE html>

<html itemscope="" itemtype="http://schema.org/WebPage">
<head>
<meta content="世界中のあらゆる情報を検索するためのツールを提供しています。さまざまな検索機能を活用して、お探しの情報を見つけてください。" name="description" />
<meta content="noodp" name="robots" />
<meta itemprop="image" content="/images/google_favicon_128.png" />
<title>Google</title>
(以下略)

Jsoup.connect("<URL>").get() で、指定した URL に GET メソッドでアクセスし、結果をパースした Document オブジェクトを取得できる。

あとは、この Document オブジェクトから必要なタグを検索する。

※HTTP のメソッドは GET と POST しか無いようなので、 RESTful API のクライアントとしては利用できないっぽい。(Connection.Method (jsoup 1.7.4-SNAPSHOT API)


リクエストパラメータを設定する

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());
}
}
}


実行結果

Qiita - プログラマの技術情報共有サービス

javaの検索結果
856投稿 • 7163フォロワー

data(String, String) メソッドでリクエストパラメータを設定できる。

URL エンコードは内部でしてくれるので、全角文字もそのまま指定できる。


HTML 形式の文字列をインプットにする

package sample.jsoup;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

public class Main {

public static void main(String[] args) {
String html = "<div><span>hoge</span><p>fuga</p></div>";

Document document = Jsoup.parse(html);
System.out.println(document.html());
}
}


実行結果

<html>

<head></head>
<body>
<div>
<span>hoge</span>
<p>fuga</p>
</div>
</body>
</html>


ローカルのファイルをインプットにする


input.html

<html>

<head>
<title>test page</title>
</head>
<body>
<h1>テストページです。</h1>
</body>
</html>

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());
}
}


実行結果

<html>

<head>
<title>test page</title>
</head>
<body>
<h1>テストページです。</h1>
</body>
</html>


テキスト・ HTML を取得する


input.html

<div id="hoge">

<h1>Hoge</h1>
<ul id="fuga">
<li>Fuga</li>
<li id="piyo">Piyo</li>
</ul>
</div>

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");
}
}


実行結果

[hoge.html()]

<h1>Hoge</h1>
<ul id="fuga">
<li>Fuga</li>
<li id="piyo">Piyo</li>
</ul>

[fuga.text()]
Fuga Piyo

[piyo.outerHtml()]
<li id="piyo">Piyo</li>




  • html() メソッドで、そのタグの中身を HTML 形式の文字列で取得できる。


  • text() メソッドで、そのタグの中身のうち、テキスト部分だけを抽出した文字列を取得できる。


  • outerHtml() メソッドで、そのタグ自身を HTML 形式の文字列で取得できる。


タグの検索


ID 指定で検索する


input.html

<h1 id="hoge">Hoge</h1>

<h1 id="fuga">Fuga</h1>
<h1 id="piyo">Piyo</h1>

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());
}
}


実行結果

<h1 id="hoge">Hoge</h1>



その他検索用メソッド

ID 以外にも、 class や属性指定、兄弟タグ、親タグ、タグ内のテキスト、など様々な検索用メソッドが用意されている。

とりあえず、 Element クラスの API はざっと目を通しておいた方がよさげ。

Element (jsoup 1.7.4-SNAPSHOT API)


CSS セレクタを使って検索する


input.html

<div id="hoge">

<ul>
<li class="error">hoge</li>
<li class="success">fuga</li>
<li class="error">piyo</li>
</ul>

<span class="error">ERROR</span>
</div>

<span id="fuga">Fuga</span>


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());
}
}
}


実行結果

<li class="error">hoge</li>

<li class="error">piyo</li>

select(String cssQuery) メソッドで、 CSS セレクタを使用した検索が可能。

使用できる CSS セレクタについては、以下の Selector クラスの API ドキュメントで説明されている。

Selector (jsoup 1.7.4-SNAPSHOT API)

ほとんどの場合普通の CSS セレクタと同じように使えるが、 E[foo="bar"] タイプのセレクタを使用するときだけ、以下のような違いがある。


input.html

<input id="hoge" name="HOGE" />

<input id="fuga" name="FUGA" />

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());
}
}


実行結果

<input id="hoge" name="HOGE" />


属性の値は ダブルクォーテーション " で括ってはいけない

"[name=\\"HOGE\\"]" ではなく、 "[name=HOGE]" が正)

おそらく、 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();
}
}

認証が不要な場合は簡単で、システムプロパティにプロキシのホストとポートを設定してあげればいい。


認証が必要な場合

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();
}
}


参考