#この記事について
Javaのjsoupというライブラリを使って、Webサイトのスクレイピングをする機会があったのでメモ。
詳細に分かりやすく説明している記事は既にたくさんあるが、メモ書きということで。
公式:https://jsoup.org/
#導入方法
公式サイトのダウンロードページからjarを入手して、ライブラリに追加するのみ。
Mavenのリポジトリからでも導入できる。
gradleだったら、build.gradleに以下の定義を追加するだけでよい(バージョンは執筆時の最新のもの)
dependencies {
compile('org.jsoup:jsoup:1.12.1')
}
#使用例
以下のページから「お知らせ」の日付・タイトル・URLを抽出する場合を例に挙げる。
<body>
<div class="section">
<div class="block">
<dl>
<dt>2019.08.04</dt>
<dd>
<a href="http://www.example.com/notice/0003.html">お知らせ その3</a>
</dd>
<dt>2019.08.03</dt>
<dd>
<a href="http://www.example.com/notice/0002.html">お知らせ その2</a>
</dd>
<dt>2019.08.02</dt>
<dd>
<a href="http://www.example.com/notice/0001.html">お知らせ その1</a>
</dd>
</dl>
</div>
</div>
</body>
以下のコードで抽出する。
import java.io.IOException;
import java.util.List;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Node;
import org.jsoup.select.Elements;
public class Example {
public static void main(String[] args) throws IOException {
// 指定のURLに対してGETでリクエスト送信して取得(post()メソッドならPOSTも可)
Document document = Jsoup.connect("http://www.example.com").get();
// 取得したdocumentからCSSセレクタで要素を抽出。
// このelementsが前述のHTMLにおける<div class="block">の要素にあたる、sizeが1のList
Elements elements = document.select(".section .block");
// elementsの0番目の要素を取得し、さらにその子要素を取得していく。
// elements.get(0).childNode(0) = 前述のHTMLにおける<dl>の要素
// elements.get(0).childNode(0).childNodes() = <dl>の子の、<dt>と<dd>の要素のList
List<Node> nodeList = elements.get(0).childNode(0).childNodes();
// nodeListから、forループでお知らせの日付・タイトル・URLを取り出していく
for (int i = 0; i < nodeList.size() / 2; i++) {
String newsDate = nodeList.get(i * 2).toString();
String newsTitle = nodeList.get(i * 2 + 1).childNode(0).toString();
String newsUrl = nodeList.get(i * 2 + 1).childNode(0).attr("href");
System.out.println(newsDate);
System.out.println(newsTitle);
System.out.println(newsUrl);
}
}
}
このコード内で使用しているクラスのドキュメントは以下。
使用の際には目を通しておくべきだろう。
Document(jsoup Java HTML Parser 1.12.1 API)
Elements(jsoup Java HTML Parser 1.12.1 API)
Element(jsoup Java HTML Parser 1.12.1 API)
Node(jsoup Java HTML Parser 1.12.1 API)
#実際の活用について
私の身内が在籍している大学院のWebサイトのお知らせページをスクレイピングするのに活用している。
大学のWebサイト内の「大学からのお知らせ」ページ、基本的に自分と関係のないお知らせしか掲載されないが
数ヶ月に一度程度の頻度で重要なお知らせが掲載されるので、頻繁に見なければならず手間なのだそう。
そこで、以下の処理を行うバッチを組んで、1時間に1回cronで動かしてあげることにした。
- 本記事で説明した方法で、お知らせページをスクレイピングしてお知らせを取得
- ローカルDBに記録している過去のお知らせと比較し、新しく掲載されたもののみ抽出
- 新しく掲載されたお知らせをメールで通知
Javaでメールを送信するのにも、多少苦労した。
これについても後日、記事にする予定。
#参考記事
jsoup使い方メモ:https://qiita.com/opengl-8080/items/d4864bbc335d1e99a2d7