【PHP】Seleniumを使ったWebスクレイピングのサンプルコードを解説
PHPとSeleniumでWebブラウザを自動操作し、Webサイトから必要な情報を取得するWebスクレイピングの基礎を学びます。開発環境の準備から、Composerでのライブラリ導入、ChromeDriverとSeleniumサーバーの設定、Google検索結果のタイトルとURLを実際に取得するサンプルコードまで、システムエンジニア初心者にも分かりやすく解説します。
開発環境
- Visual Studio Code:version 1.73.0
- OS:Windows10
PHPのSeleniumとは
Selenium(セレニウム)とは、Webブラウザを自動で操作するためのツールです。 このツールを使うと、まるで人間がWebサイトを閲覧したり、ボタンをクリックしたり、文字を入力したりするのと同じように、プログラムからWebブラウザを動かすことができます。
Webサイトによっては、JavaScriptという技術を使ってページが読み込まれた後に内容が変化するものがあります。このような「JavaScriptで動的に生成されるページ」からでも、Seleniumを使えば、特定の情報を自動で集める「スクレイピング」という作業を行うことが可能です。
PHPのプログラムからSeleniumを操作するには、主に以下の2つのライブラリ(プログラムの部品)を組み合わせて使用します。
php-webdriver/webdriver:これは、PHPのプログラムからSeleniumに対して「このボタンをクリックしてください」「このテキストボックスに文字を入力してください」といった指示を送るためのライブラリです。PHP向けのWebDriverクライアントと呼ばれます。se/selenium-server-standalone:これは、php-webdriver/webdriverから送られてきた指示を受け取って、実際にWebブラウザ(Google ChromeやMozilla Firefoxなど)を起動し、操作を実行する役割を担うSeleniumの本体です。スタンドアロンのサーバーとして動作します。
公式ドキュメント:https://php-webdriver.github.io/php-webdriver/
PHPのSeleniumの使い方
PHPのSeleniumの使い方を解説していきます。
Seleniumとは、Webブラウザの操作を自動化するためのツールです。通常、Webサイトを操作するには、人がマウスをクリックしたり、キーボードで文字を入力したりします。Seleniumを使うと、これらの操作をプログラムで自動的に行えるようになります。
システムエンジニアとして、Webサイトの動作テストを繰り返し行ったり、Webサイトから特定の情報を自動的に集めたりする際に、このSeleniumが非常に役立ちます。PHPからSeleniumを操作することで、PHPのプログラムでWebブラウザを意図通りに動かすことが可能になります。
ライブラリをインストール
まずは作業用のフォルダを作成し、Composerで必要なライブラリをインストールします。作業用のフォルダは、プロジェクトのファイルを整理し、管理しやすくするために最初に作ることが一般的です。
Composerは、PHPで開発を行う際に、必要なソフトウェアの部品(ライブラリやパッケージと呼びます)を簡単にインストールし、管理するためのツールです。以下のコマンドを実行することで、PHPからSeleniumを操作するためのライブラリと、Seleniumサーバー本体をダウンロードして、プロジェクトで使えるように準備します。
1composer require php-webdriver/webdriver se/selenium-server-standalone
このコマンドでは、php-webdriver/webdriverというライブラリと、se/selenium-server-standaloneというライブラリの2つをインストールしています。php-webdriver/webdriverは、PHPのコードからSeleniumサーバーに対して命令を送るためのインターフェースを提供します。se/selenium-server-standaloneは、ブラウザを実際に操作するための中心的な役割を果たすSeleniumサーバーの本体です。
ChromeDriverのダウンロード
次にChromeDriverをダウンロードします。ChromeDriverは、SeleniumがGoogle Chromeブラウザを自動で操作するために必要となる、特別なプログラムです。Chromeブラウザのバージョンと、お使いのOSの環境(Windows、macOSなど)に合わせて適切なものをダウンロードする必要があります。
Chromeのバージョン115以降を使用している場合は、Chrome for Testingの可用性ダッシュボードからダウンロードします。これは、最近のChromeブラウザの仕様変更に対応するための専用のダウンロードサイトです。 Chrome for Testing:https://googlechromelabs.github.io/chrome-for-testing/
ダウンロードページにアクセスしたら、安定版を意味する「Stable」の項目から、お使いのChromeのバージョンと、お使いのPCの環境(例えばWindowsの64bit版など)に合ったChromeDriverを見つけてダウンロードしてください。今回はWindowsの64bit環境を想定しているため、「win64」のファイルをダウンロードしています。
ダウンロードしたファイルは圧縮されていますので、解凍してください。解凍するとchromedriver.exeという実行ファイルが見つかります。このchromedriver.exeファイルを、先ほど作成したプロジェクトフォルダの中に配置します。これにより、SeleniumがChromeブラウザを操作する際に、このChromeDriverを見つけて利用できるようになります。
Seleniumサーバーを起動する
次にSeleniumサーバーを起動します。Seleniumサーバーは、PHPプログラムからの指示を受け取り、その指示に基づいてChromeDriverを介して実際のWebブラウザを操作する、いわば「仲介役」のような存在です。
Composerでインストールしたサーバーのjarファイルを指定して、以下のコマンドを実行します。jarファイルとは、Javaの実行可能なプログラムをまとめたファイル形式のことです。
1java -jar vendor/se/selenium-server-standalone/bin/selenium-server-standalone.jar
上記のコマンドは、Javaというプログラム実行環境を使って、vendor/se/selenium-server-standalone/binフォルダ内にあるSeleniumサーバーのjarファイルを実行するという意味です。
このjarファイルの名前は、Seleniumのバージョンアップによって変更されることがあります。そのため、実際にコマンドを実行する前に、vendor/se/selenium-server-standalone/binのフォルダの中を確認し、現在の正確なjarファイル名を指定してください。
Seleniumサーバーが起動すると、通常はポート番号4444でサーバーが待ち受けている状態になります。ポート番号とは、ネットワーク上で特定のサービスを識別するための番号のことです。この状態は、SeleniumサーバーがPHPプログラムからの接続や命令をいつでも受け入れられる準備ができたことを意味します。
このSeleniumサーバーは、Webブラウザの自動操作を行う間は常に起動したままにしておく必要があります。そのため、Seleniumサーバーを起動したターミナルとは別に、新しいターミナルを開いて、その新しいターミナルでPHPファイルを実行することになります。これにより、Seleniumサーバーがブラウザ操作の指示を受け付けながら、PHPプログラムがその指示を送り続けるという分業が可能になります。
PHPのSeleniumでスクレイピングする
次にPHPのSeleniumでスクレイピングするサンプルコードを解説していきます。 「スクレイピング」とは、プログラムを使ってWebサイトから情報を自動的に取得する技術のことです。ここでは、PHPとSeleniumというツールを使って、Googleの検索結果からタイトルとURLを取得する方法を学びます。
スクレイピングのサンプルコード
下記はSeleniumを使用してGoogleで「PHPとは」と検索し、検索結果のタイトルとURLの一覧を取得するサンプルコードです。
1<?php 2require 'vendor/autoload.php'; 3 4use Facebook\WebDriver\Remote\RemoteWebDriver; 5use Facebook\WebDriver\Remote\DesiredCapabilities; 6use Facebook\WebDriver\WebDriverBy; 7use Facebook\WebDriver\WebDriverKeys; 8use Facebook\WebDriver\WebDriverWait; 9use Facebook\WebDriver\WebDriverExpectedCondition; 10 11// プロジェクトフォルダ内のドライバへのパスを指定 12$driverPath = realpath('chromedriver.exe'); 13 14// SeleniumサーバーのURL 15$host = 'http://localhost:4444/wd/hub'; // SeleniumサーバーのURLとポート番号 16 17// ブラウザの希望する設定 (Chromeの場合) 18$capabilities = DesiredCapabilities::chrome(); 19 20// ChromeDriverのパスをシステムプロパティに設定 21putenv("webdriver.chrome.driver=$driverPath"); 22 23// リモートWebDriverのインスタンスを作成 24$driver = RemoteWebDriver::create($host, $capabilities); 25 26try { 27 // Googleのホームページを開く 28 $driver->get("https://www.google.com"); 29 30 // 検索ボックスを見つける 31 $searchBox = $driver->findElement(WebDriverBy::id('APjFqb')); 32 33 // "PHPとは" を入力してEnterキーを押す 34 $searchBox->sendKeys("PHPとは")->sendKeys(WebDriverKeys::ENTER); 35 36 // 検索結果が表示されるまで待機 (例: 検索結果リストの一つ目のリンクが見つかるまで) 37 $wait = new WebDriverWait($driver, 30); // 最大30秒待機 38 $wait->until( 39 WebDriverExpectedCondition::presenceOfElementLocated(WebDriverBy::id('search')) 40 ); 41 42 // 検索結果の a タグ内にある h3 要素を取得 43 $results = $driver->findElements(WebDriverBy::cssSelector('#search a h3')); 44 45 foreach ($results as $result) { 46 // aタグ(親要素)を取得 47 $parentLink = $result->findElement(WebDriverBy::xpath('./ancestor::a')); 48 49 // タイトルとURLを取得 50 $title = $result->getText(); 51 $url = $parentLink->getAttribute('href'); 52 53 if ($title && $url) { 54 echo "タイトル: " . $title . PHP_EOL; 55 echo "URL: " . $url . PHP_EOL; 56 echo PHP_EOL; 57 } 58 } 59 60} finally { 61 // ドライバーを終了 62 $driver->quit(); 63}
作成したファイルは、以下のコマンドで実行できます。
1php index.php
ライブラリを読み込む
まず、Composerでインストールしたライブラリを読み込み、これから使用するクラスを指定します。これは、PHPが外部の機能を利用するための準備です。
1require 'vendor/autoload.php'; 2 3use Facebook\WebDriver\Remote\RemoteWebDriver; 4use Facebook\WebDriver\Remote\DesiredCapabilities; 5use Facebook\WebDriver\WebDriverBy; 6use Facebook\WebDriver\WebDriverKeys; 7use Facebook\WebDriver\WebDriverWait; 8use Facebook\WebDriver\WebDriverExpectedCondition;
それぞれのクラスは、以下の役割を持っています。
RemoteWebDriver:Seleniumサーバーを通して、ブラウザを遠隔で操作するための主要な機能を提供します。DesiredCapabilities:どのウェブブラウザ(Chrome、Firefoxなど)を使い、どのような設定(例えば、ヘッドレスモードで起動するかなど)にするかを定義します。WebDriverBy:ウェブページ上の特定の要素を見つけるための方法(ID、XPath、CSSセレクタなど)を指定します。WebDriverKeys:キーボードの操作(エンターキーを押す、文字を入力するなど)をシミュレートするための機能です。WebDriverWait:特定の条件が満たされるまで、プログラムの実行を一時停止させる(待機する)ための設定を行います。WebDriverExpectedCondition:WebDriverWaitと組み合わせて使用し、どのような状態になったら待機を終了するかという具体的な条件を定義します。
WebDriverの設定をする
次に、ブラウザを操作するための準備として、ChromeDriverというツールへのパスと、SeleniumサーバーというプログラムのURLを設定し、実際にブラウザを操作するためのWebDriverのインスタンスを作成します。
1$driverPath = realpath('chromedriver.exe'); 2 3$host = 'http://localhost:4444/wd/hub'; 4 5$capabilities = DesiredCapabilities::chrome(); 6 7putenv("webdriver.chrome.driver=$driverPath"); 8 9$driver = RemoteWebDriver::create($host, $capabilities);
realpath関数は、chromedriver.exeという、ChromeブラウザをSeleniumで操作するためのプログラムがプロジェクトフォルダのどこにあるかを正確に教えてくれる絶対パスを取得しています。
$hostには、Seleniumサーバーが動いている場所と、通信を行うためのポート番号(4444)を指定します。
DesiredCapabilities::chrome()は、使用するブラウザがChromeであることを設定しています。
putenv関数は、ChromeDriverのパスをシステムが利用できる環境変数として設定します。これにより、SeleniumがChromeDriverを見つけられるようになります。
最後に、RemoteWebDriver::createを使って、設定した情報をもとにブラウザを操作するための準備が整った「インスタンス」と呼ばれるオブジェクトを作成しています。
処理の終了時にドライバーを終了する
ウェブブラウザを操作するプログラムは、処理が終わった後や、途中でエラーが発生した場合でも、必ず開いたブラウザを閉じる必要があります。これを忘れると、たくさんのブラウザが開きっぱなしになり、PCの動作が遅くなる原因となります。
1try { 2 // スクレイピングの処理 3} finally { 4 $driver->quit(); 5}
このtry〜finallyという構文は、tryブロックの中の処理でたとえエラーが起きたとしても、finallyブロックの中の処理(ここでは$driver->quit())は必ず実行されることを保証します。これにより、どんな状況でもブラウザが確実に閉じられるようになります。
Googleにアクセスしてキーワードを検索する
次に、実際にブラウザを操作して、Googleのホームページを開き、検索ボックスに目的のキーワードを入力して検索を実行します。
1$driver->get("https://www.google.com"); 2 3$searchBox = $driver->findElement(WebDriverBy::id('APjFqb')); 4 5$searchBox->sendKeys("PHPとは")->sendKeys(WebDriverKeys::ENTER);
$driver->get("https://www.google.com")は、WebDriverに「Googleのホームページを開いてください」と指示しています。
$searchBox = $driver->findElement(WebDriverBy::id('APjFqb'))の部分では、Googleのページのどこに検索ボックスがあるかを見つけ出しています。このAPjFqbというのは、検索ボックスに割り当てられたidという識別子です。開発者ツールというブラウザの機能を使うと、このような要素のidなどを確認できます。
$searchBox->sendKeys("PHPとは")->sendKeys(WebDriverKeys::ENTER)は、見つけた検索ボックスに対して「PHPとは」という文字を入力し、さらにキーボードのEnterキーを押す操作をシミュレートしています。これにより、実際に手で検索するのと同じ動作が行われます。
検索結果が表示されるまで待機する
コンピューターのプログラムは非常に高速です。そのため、ウェブページが開いたり、検索結果が表示されたりするよりも速く、次の処理に進んでしまうことがあります。もし表示されていない状態で要素を探しに行くと、見つからずにエラーになってしまいます。これを防ぐために「待機処理」が必要です。
1$wait = new WebDriverWait($driver, 30); 2$wait->until( 3 WebDriverExpectedCondition::presenceOfElementLocated(WebDriverBy::id('search')) 4);
$wait = new WebDriverWait($driver, 30)は、「最大で30秒間待機する」という設定を持つ待機オブジェクトを作成しています。
$wait->until(...)は、特定の条件が満たされるまで待機を続けます。ここで指定しているWebDriverExpectedCondition::presenceOfElementLocated(WebDriverBy::id('search'))という条件は、「idがsearchである要素がページ上に表示されるまで」という意味です。Googleの検索結果は通常、このid="search"を持つ要素の中に表示されるため、これによって検索結果の読み込みが完了するのを待っています。
検索結果のタイトルとURLを取得する
最後に、表示された検索結果の中から、それぞれの記事のタイトルとURLという必要な情報を取得し、画面に出力します。
1$results = $driver->findElements(WebDriverBy::cssSelector('#search a h3')); 2 3foreach ($results as $result) { 4 $parentLink = $result->findElement(WebDriverBy::xpath('./ancestor::a')); 5 6 $title = $result->getText(); 7 $url = $parentLink->getAttribute('href'); 8 9 if ($title && $url) { 10 echo "タイトル: " . $title . PHP_EOL; 11 echo "URL: " . $url . PHP_EOL; 12 echo PHP_EOL; 13 } 14}
$results = $driver->findElements(WebDriverBy::cssSelector('#search a h3'))では、検索結果のタイトルが通常h3タグで表示されていることに注目し、idがsearchの要素の中にあるaタグ(リンク)の中のすべてのh3要素をまとめて取得しています。findElementsは、条件に合う要素を複数取得するためのメソッドです。
foreach ($results as $result)で、取得した各h3要素(タイトル)に対して繰り返し処理を行います。
$parentLink = $result->findElement(WebDriverBy::xpath('./ancestor::a'))では、現在のh3要素の親要素をたどっていき、最も近いaタグ(リンク全体)を取得しています。./ancestor::aは、XPathという方法で要素の親子関係を指定する書き方です。
$title = $result->getText()でh3タグのテキスト内容(タイトル)を取得し、$url = $parentLink->getAttribute('href')で親のaタグのhref属性(リンク先URL)を取得しています。
if ($title && $url)の条件を満たした場合(タイトルもURLも取得できた場合)に、ターミナル(コマンドを実行する画面)にタイトルとURLを表示しています。
実行すると、ブラウザが自動で起動して検索が行われ、ターミナルに検索結果のタイトルとURLが出力されます。
おわりに
本記事では、PHPとSeleniumを使ったWebスクレイピングの基礎を学習しました。Visual Studio Codeでの開発環境構築から、Composerによるライブラリ導入、ChromeDriverとSeleniumサーバーの起動方法まで、具体的な手順を理解しました。また、Google検索結果からタイトルとURLを取得するサンプルコードを通して、Webブラウザの自動操作や特定の要素を見つけて情報を取得する実践的な方法を習得しました。特に、try-finallyによるドライバーの確実な終了や、WebDriverWaitを用いたページの読み込み待機処理の重要性も確認できました。今回学んだPHPでのWebスクレイピング技術は、Webサイトの自動テストや情報収集など、システム開発の様々な場面で役立つでしょう。