LoginSignup
9
12

More than 3 years have passed since last update.

jsoupによるWebサイトのスクレイピング

Posted at

この記事について

Javaのjsoupというライブラリを使って、Webサイトのスクレイピングをする機会があったのでメモ。
詳細に分かりやすく説明している記事は既にたくさんあるが、メモ書きということで。
公式:https://jsoup.org/

導入方法

公式サイトのダウンロードページからjarを入手して、ライブラリに追加するのみ。
Mavenのリポジトリからでも導入できる。
gradleだったら、build.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>

以下のコードで抽出する。

Example.java
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

9
12
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
12