Webの画面から情報を取得する際に、プログラムで取得する手段があります。本記事ではJavaプログラムでSeleniumを使ってブラウザの自動化を行い、Webページのデータを取得する方法を紹介します。
Seleniumとは
SeleniumはWebブラウザの操作を自動化するためのライブラリです。SeleniumはThoughWorks社が2004年にWebアプリケーションのUIテストの自動化目的で開発されました。元々はWebアプリケーションのUIテスト目的で開発されましたが、現在ではテスト以外にもWebサイトのクローリングやタスクの自動化といった様々な用途で使用されています。
Selenium環境を構築する2種類の方法
Selenium環境には主に2種類あります。
- DockerでSeleniumサーバを立てて、ブラウザとWeb DriverはDockerコンテナ上で動かす方法
- SeleniumもWeb Driverもローカルで動かす方法
1はSeleniumがDockerコンテナを提供しており、セットアップが簡単です。また、Seleniumを動作させるためには、ChromeのバージョンとWeb Driverが動作するバージョンが一致していないと動作しないという面倒な問題がありますが、公式のDockerイメージではChromeとWeb Driverがそれぞれ適切なバージョンでインストール済なのでバージョンについて気にする必要がありません。
本記事では方法2を紹介します。
SeleniumをMacのローカル環境で構築する
Chromeがインストールされていなければ、まずChromeをインストールします。
chromedriverをインストールします。
brew install chromedriver
Javaアプリケーションを作成します。ビルドツールにはGradleを使用する前提で記述しますが、Maven等を使う場合は読み替えて頂ければ問題ありません。
build.gradleに以下を追加します。
dependencies {
implementation group: 'org.seleniumhq.selenium', name: 'selenium-java', version: '4.8.1'
}
以下がサンプルコードです。私の環境ではchromedriver
のパスは指定しなくても動きました。
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class Main {
public static void main(String[] args) throws IOException, InterruptedException {
// Optional. If not specified, WebDriver searches the PATH for chromedriver.
// System.setProperty("webdriver.chrome.driver", "/path/to/chromedriver");
WebDriver driver = new ChromeDriver();
driver.get("http://www.google.com/");
Thread.sleep(5000); // Let the user actually see something!
WebElement searchBox = driver.findElement(By.name("q"));
searchBox.sendKeys("ChromeDriver");
searchBox.submit();
Thread.sleep(5000); // Let the user actually see something!
driver.quit();
}
}
これで実行すると、初回起動時は以下のダイアログが表示されます。
“chromedriver” can’t be opened because Apple cannot check it for malicious software.
System > Security
でchromedriverに許可を与える必要があります。許可を与えた後に再実行すると、正常にChromeが立ち上がり、Webブラウザが自動的に操作されます。
要素の指定方法や要素に対する操作
要素の指定方法
driver.findElement(…)
はマッチした最初の要素をWebElement
で返します。
driver.findElements(…)
はマッチしたすべての要素をList<WebElement>
で返します。
findElementは続けて呼び出すことができます。
driver.findElement(…).findElement(…)
要素の指定例
IDで指定する
By.ById("要素のID")
CSSのセレクターで指定する
By.cssSelector("tr .className")
XPathで指定する
By.xpath("td[@class='className']//td[1]//div")
[1]
で指定すると、同じタグが複数あった場合に1番目のタグを取得するという意味になります。//
は間に複数のタグがあった場合に省略するという意味になります。
要素に対する操作
取得した要素WebElementのオブジェクトは以下のメソッドを持っています。
テキストを取得する
.getText()
要素に指定されている特定の属性を取得する
.getAttribute("属性の名前")
findElementはマッチする要素が見つからなかった場合NoSuchElementException
を発生させます。要素が見つからないことは想定されると思いますので、適切にtry/catch
構文で処理するようにしましょう。
参考
要素に対する処理としては、このあたりが参考になります。
Finding web elements | Selenium
Pythonの場合はこちらが参考になります。
4. Locating Elements — Selenium Python Bindings 2 documentation
xpath記法についてはこちらが参考になります。