JavaでWebのデータをスクレイピングするために、jsoupを利用します。jsoupはJavaのWebスクレイピングライブラリとして人気があるため、Web上で情報が多く見つかります。また記述方法もシンプルで分かりやすいといった特徴があります。
プロジェクトの準備
build.gardle
に以下を追加します。
dependencies {
implementation group: 'org.jsoup', name: 'jsoup', version: '1.15.4'
}
スクレイピングするコードの作成
以下のライブラリをimportします。
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
実際にスクレイピングするコードを記述します。
public static void jsoupScraping() throws IOException {
Document subreddit = Jsoup.connect("https://www.reddit.com/r/java/").userAgent("Mozilla").data("name", "jsoup").get();
System.out.println(subreddit);
}
コンソールに取得したHTMLが出力されれば成功です。
ログイン画面の対策
Webスクレイピングしたいサイトがログイン後の場合、先程の方法ではうまくいきません。そのため、先にログインページに対してユーザー名とパスワードをPOSTし、発行されたクッキーをセットした状態で実際にスクレイピングしたいページにアクセスする必要があります。これを実装すると以下のようになります。
public static void jsoup() {
Document document;
// ユーザ名・パスワード
final String USERNAME = "ユーザー名";
final String PASS = "パスワード";
// ログインページのURL
final String LOGIN_URL = "ログインページのPOST先URL";
String mainUrl = "スクレイピングしたいページのURL";
// ユーザーエージェント
final String UA = "Mozilla";
try {
// ログインページからレスポンスを取得
Connection.Response response = Jsoup.connect(LOGIN_URL)
.method(Connection.Method.GET)
.execute();
// フォームのname
response = Jsoup.connect(LOGIN_URL)
.data("フォームname(ログイン名)", USERNAME, "フォームのname(パスワード)", PASS)
.userAgent(UA)
.cookies(response.cookies())
.method(Connection.Method.POST)
.execute();
System.out.println(response.statusCode());
System.out.println(response.parse());
// ログインページから取得したクッキーを使ってアクセス
document = Jsoup.connect(mainUrl)
.userAgent(UA)
.cookies(response.cookies())
.get();
// System.out.println(document);
} catch (IOException e) {
e.printStackTrace();
}
}
以下のフォームの場合、各パラメータは次のとおりです。
- ログインページのPOST先URL:
https://loginurl
- フォームname(ログイン名):
email
- フォームのname(パスワード):
passwd
<form id="login" name="login" action="https://loginurl" method="post">
<div>ログインはコチラ</div><input type="text" name="email" value="" id="email" class="lginFmId" placeholder="メールアドレスを入力してください" title="メールアドレス">
<input type="password" name="passwd" id="passwd" class="lginFmPw" placeholder="パスワードを入力してください" title="パスワード">
<input type="submit" value="ログイン" class="lginFmLi"><div class="clear"></div>
<input type="hidden" name="url" id="hiddenURL" value="https://xxx">
<input type="hidden" name="done" value="https://xxx/">
</form>
フォーム上入力項目がIDとパスワードだけであっても、以下のようにhidden
パラメータで、ログイン画面で生成されたトークンをログインURLに一緒にPOSTする必要がある場合もあります。
<form id="login" name="login" action="https://loginurl" method="post">
<div>ログインはコチラ</div><input type="text" name="email" value="" id="email" class="lginFmId" placeholder="メールアドレスを入力してください" title="メールアドレス">
<input type="password" name="passwd" id="passwd" class="lginFmPw" placeholder="パスワードを入力してください" title="パスワード">
<input type="submit" value="ログイン" class="lginFmLi"><div class="clear"></div>
<input type="hidden" name="postkey" id="postkey" value="32aa027553e3e5a8139118e240b6323d">
<input type="hidden" name="refToken" id="refToken" value="e2f4aae6781d8905611665292773929c817777e526ac81de9289152ea98f19cb">
<input type="hidden" name="url" id="hiddenURL" value="https://xxx">
<input type="hidden" name="done" value="https://xxx">
</form>
この場合は以下のようにもう一ステップを挟む必要があります。
- 一度ログインページのURLにアクセスしhiddenパラメータのトークンを取得
- ID、パスワード、トークンをログインURLにPOST
- Cookieを保持した状態で実際にWebスクレイピングしたいページにアクセス
jsoupのデメリットと代替策
jsoupは、広く使われており情報が探しやすい、記述が簡単といったメリットがありますが、一方でデメリットもあります。
それは、javascriptに対応していないということです。Webサイトの中にはjavascriptが無効な状態でアクセスすると正常に表示されない、正しく機能しないといったことが発生し、期待するWebスクレイピングが行えない可能性があります。
そのような場合は、以下のような代替策が考えられます。
- Javascriptに対応したスクレイピングライブラリを使用する
- ChromeのようなWebブラウザをJavaで操作することで自動化するSeleniumを用いる
サイトポリシーを確認しよう
スクレイピングは大変強力な手法ですが、実際に利用する前にサイトポリシーで禁止されていないか確認するようにしましょう。また、禁止されていなくてもWebサーバーに負担をかけないように実行間隔を長めに取る、不必要にスクレイピングを行わないなど注意しましょう。