Jsoupを使ってJavaでHTMLを解析する
1概要
Jsoup
は、主にHTMLからデータを抽出するために使用されるオープンソースのJavaライブラリです。 HTMLを操作して出力することもできます。それは着実な開発ライン、素晴らしいドキュメンテーション、そして流暢で柔軟なAPIを持っています。 JsoupはXMLの解析と構築にも使用できます。
このチュートリアルでは、jsoupのいくつかの機能を実演するスクレーピング演習を説明するためにhttps://spring.io/blog[Spring Blog]を使用します。
-
Loading:HTMLを取得して
Document
に解析する -
フィルタリング:目的のデータを
Elements
に選択してトラバースする
それ
** 抽出:ノードの属性、テキスト、HTMLを取得する
-
修正:ノードの追加/編集/削除とそれらの属性の編集
2 Mavenの依存関係
プロジェクトでjsoupライブラリを利用するには、
pom.xml
に依存関係を追加します。
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.10.2</version>
</dependency>
jsoup
の最新バージョンを見つけることができます。 Maven Centralリポジトリ
3一目でわかるJsoup
JsoupはページHTMLを読み込み、対応するDOMツリーを構築します。このツリーはブラウザのDOMと同じように機能し、jQueryやJavaScriptのようなテキスト/HTML/属性の選択、トラバース、操作、要素の追加/削除を行うメソッドを提供します。
クライアントサイドのセレクタとDOMのトラバース/操作に慣れている人は、jsoupがとてもおなじみでしょう。ページの段落を印刷するのがどれほど簡単かを確認します。
Document doc = Jsoup.connect("http://example.com").get();
doc.select("p").forEach(System.out::println);
jsoupはHTMLのみを解釈し、JavaScriptは解釈しません。したがって、JavaScript対応のブラウザでページを読み込んだ後に通常行われるDOMへの変更は、jsoupでは表示されません。
4ロード中
ロードフェーズは、HTMLを
Document
にフェッチして解析することからなります。
Jsoupは、最新のブラウザが行うように、最も無効なものから完全に検証されたものまで、あらゆるHTMLの解析を保証します。これは、
String
、
InputStream
、
File
、またはURLをロードすることによって実現できます。
Spring BlogのURLから
Document
をロードしましょう。
String blogUrl = "https://spring.io/blog";
Document doc = Jsoup.connect(blogUrl).get();
get
メソッドに注目してください。これはHTTP GET呼び出しを表します。 HTTP POSTを
post
メソッドで実行することもできます(または、HTTPメソッドタイプをパラメータとして受け取る
method
を使用することもできます)。
異常なステータスコード(404など)を検出する必要がある場合は、
HttpStatusException
例外を捕捉する必要があります。
try {
Document doc404 = Jsoup.connect("https://spring.io/will-not-be-found").get();
} catch (HttpStatusException ex) {
//...
}
時々、接続はもう少しカスタマイズされる必要があります。
Jsoup.connect(…)
は
Connection
を返します。これを使用すると、とりわけ、ユーザーエージェント、参照元、接続タイムアウト、Cookie、投稿データ、およびヘッダーを設定できます。
Connection connection = Jsoup.connect(blogUrl);
connection.userAgent("Mozilla");
connection.timeout(5000);
connection.cookie("cookiename", "val234");
connection.cookie("cookiename", "val234");
connection.referrer("http://google.com");
connection.header("headersecurity", "xyz123");
Document docCustomConn = connection.get();
接続は流暢なインターフェースをたどるので、目的のHTTPメソッドを呼び出す前にこれらのメソッドを連鎖させることができます。
Document docCustomConn = Jsoup.connect(blogUrl)
.userAgent("Mozilla")
.timeout(5000)
.cookie("cookiename", "val234")
.cookie("anothercookie", "ilovejsoup")
.referrer("http://google.com")
.header("headersecurity", "xyz123")
.get();
Connection
設定の詳細については、https://jsoup.org/apidocs/org/jsoup/Connection.html[対応するJavadocを参照]を参照してください。
5フィルタリング
HTMLを
Document
に変換したので、今度はそれをナビゲートして探しているものを見つける時間です。 jQuery/JavaScriptとの類似性は、セレクターとトラバース方法が似ているため、より明白になります。
5.1.
を選択
Document
select
メソッドは、セレクタを表す
String
を、同じセレクタ構文https://api.jquery.com/category/selectors/[CSSまたはJavaScriptの場合]を使用して受け取り、一致する
Elements
のリストを取得します。このリストは空にすることができますが
null
にすることはできません。
select
メソッドを使用していくつかの選択を見てみましょう。
Elements links = doc.select("a");
Elements sections = doc.select("section");
Elements logo = doc.select(".spring-logo--container");
Elements pagination = doc.select("#pagination__control");
Elements divsDescendant = doc.select("header div");
Elements divsDirect = doc.select("header > div");
一般的な
select
の代わりに、ブラウザDOMからヒントを得た、より明示的なメソッドを使用することもできます。
Element pag = doc.getElementById("pagination__control");
Elements desktopOnly = doc.getElementsByClass("desktopOnly");
Element
は
Document
のスーパークラスなので、
Document
およびhttps://jsoupで選択方法の操作についてさらに学ぶことができます。 org/apidocs/org/jsoup/nodes/Element.html[
Element
]Javadocs。
5.2. トラバース
-
Jsoupは、
Document
、一連の
Element、または特定の
Element__を操作するメソッドを提供し、ノードの親、兄弟、または子にナビゲートすることを可能にします。
また、
Elements
の集合の最初、最後、およびn番目(0から始まるインデックスを使用)の
Element
にジャンプすることもできます。
Element firstSection = sections.first();
Element lastSection = sections.last();
Element secondSection = sections.get(2);
Elements allParents = firstSection.parents();
Element parent = firstSection.parent();
Elements children = firstSection.children();
Elements siblings = firstSection.siblingElements();
選択を繰り返すこともできます。実際、
Elements
型のものは何でも反復できます。
sections.forEach(el -> System.out.println("section: " + el));
選択を前の選択(サブ選択)に限定することができます。
Elements sectionParagraphs = firstSection.select(".paragraph");
6. 抽出
特定の要素に到達する方法がわかったので、その内容、つまり属性、HTML、または子テキストを取得します。
ブログから最初の記事を選択し、その日付、最初のセクションのテキスト、そして最後にその内側と外側のHTMLを取得する次の例を見てください。
Element firstArticle = doc.select("article").first();
Element timeElement = firstArticle.select("time").first();
String dateTimeOfFirstArticle = timeElement.attr("datetime");
Element sectionDiv = firstArticle.select("section div").first();
String sectionDivText = sectionDiv.text();
String articleHtml = firstArticle.html();
String outerHtml = firstArticle.outerHtml();
セレクタを選択して使用するときに留意する必要があるいくつかのヒントがあります。
-
ページだけでなく、ブラウザの「ソースの表示」機能に依存
DOMが変更された可能性があるため(ブラウザコンソールで選択すると、
jsoupとは異なる結果になります)
**
https://jsoup.org/apidocs/index.html?org/jsoup/select/Selector.html
[Know
たくさんあるので、それを持っていることは常に良いことです。
少なくともそれらを以前に見たことがあります。セレクタの習得に時間がかかる
**
セレクタ用の遊び場を使用
それらを使って(そこにサンプルHTMLを貼り付けてください)
** ページ変更への依存度を低くする
妥協しているセレクタ(例:IDベースを好む)
7. 修正中
変更には、要素の属性、テキスト、およびHTMLの設定、要素の追加と削除が含まれます。それは以前にjsoupによって生成されたDOMツリー –
ドキュメント
– に対して行われます。
7.1. 属性と内部テキスト/HTMLの設定
jQueryと同様に、属性、テキスト、およびHTMLを設定するメソッドは同じ名前を持ちますが、設定される値も受け取ります。
-
attr()
– 属性の値を設定します(属性の値が
存在しない)
**
text()
– 要素の内部テキストを設定し、内容を置き換えます
-
html()
– 要素の内部HTMLを設定し、内容を置き換えます
これらの方法の簡単な例を見てみましょう。
timeElement.attr("datetime", "2016-12-16 15:19:54.3");
sectionDiv.text("foo bar");
firstArticle.select("h2").html("<div><span></span></div>");
7.2. 要素の作成と追加
新しい要素を追加するには、まず
Element
をインスタンス化してそれを構築する必要があります。
Element
が構築されたら、
appendChild
メソッドを使用して別の
Element
に追加することができます。新しく作成されて追加された
Element
は、
appendChild
が呼び出される要素の末尾に挿入されます。
Element link = new Element(Tag.valueOf("a"), "")
.text("Checkout this amazing website!")
.attr("href", "http://baeldung.com")
.attr("target", "__blank");
firstArticle.appendChild(link);
7.3. 要素を削除する
要素を削除するには、まずそれらを選択して
remove
メソッドを実行する必要があります。
たとえば、
Document
から“
navbar-link”
クラスを含むすべての
<li>
タグ、および最初の記事のすべての画像を削除します。
doc.select("li.navbar-link").remove();
firstArticle.select("img").remove();
7.4. 修正文書をHTML
に変換する
最後に、
Document
を変更していたので、作業内容を確認したいと思うかもしれません。
これを行うには、提示されているメソッドを使用して選択、トラバース、および抽出することによって
Document
DOMツリーを探索するか、または
html()
メソッドを使用して単にそのHTMLを
String
として抽出します。
String docHtml = doc.html();
String
の出力はきれいなHTMLです。
8結論
Jsoupはどのページも掻き取るための素晴らしいライブラリです。 Javaを使用していてブラウザベースのスクレイピングを必要としない場合は、考慮に入れるべきライブラリです。フロントエンド開発に関してあなたが持っているかもしれない知識を利用し、そして良い習慣とデザインパターンに従うので、それはおなじみで使いやすいです。
jsoup API
を学び、https://jsoup.org/cookbook/[jsoup Cookbook]を読むことで、jsoupを使ってWebページをスクラップすることについてさらに学ぶことができます。
このチュートリアルで使用されているソースコードはhttps://github.com/eugenp/tutorials/tree/master/jsoup[GitHubプロジェクト]にあります。