サンプル・プログラムの実行例

サンプル・プログラム
DOMscraping.php | サンプル・プログラム本体。 |
pahooScraping.php | スクレイピング処理に関わるクラス pahooScraping。 スクレイピング処理に関わるクラスの使い方は「PHPで作るRSSビューア」を参照。include_path が通ったディレクトリに配置すること。 |
pahooInputData.php | データ入力に関わる関数群。 使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。 |
バージョン | 更新日 | 内容 |
---|---|---|
4.0.1 | 2023/09/29 | bug-fix |
2.0.0 | 2023/09/18 | pahooScrapingクラスに変更 |
1.1 | 2021/05/08 | PHP8対応,リファラ・チェック改良 |
1.0 | 2015/10/20 |
関数/メソッド | 機能 | 詳細 |
---|---|---|
class::pahooScraping | ||
__construct | コンストラクタ | |
__destruct | デストラクタ | |
isJapanese | 使用言語が日本語かどうかを判定する | |
setLanguage | 使用言語を設定する. | |
isError | エラーが発生しているかどうかを取得する. | |
getError | エラー番号を取得する. | |
getErrorMessage | エラー・メッセージを取得する. | |
resetError | エラー状態をリセットする. | |
isphp8over | PHP8以上かどうか検査する | |
evalXPath | 指定したXPath式を評価し,結果を返す. | |
queryXPath | 指定したXPath式を評価する. | |
getTitle | titleを取得 | |
getDescription | descriptionを取得 | |
getValueFistrXPath | 指定したXPath式に合致する最初のタグの値もしくは属性値を返す. |
バージョン | 更新日 | 内容 |
---|---|---|
1.8.0 | 2024/11/12 | validRegexPattern() 追加 |
1.7.0 | 2024/10/09 | validURL() validEmail() 追加 |
1.6.0 | 2024/10/07 | isButton() -- buttonタグに対応 |
1.5.0 | 2024/01/28 | exitIfExceedVersion() 追加 |
1.4.2 | 2024/01/28 | exitIfLessVersion() メッセージ修正 |
解説:初期化処理
DOMscraping.php
29: //プログラム・タイトル
30: define('TITLE', 'DOMDocumentを使ってスクレイピング');
31:
32: //データ入力に関わる関数群:include_pathに配置すること
33: require_once('pahooInputData.php');
34:
35: //PHPバージョン・チェック
36: exitIfLessVersion(MINUMUM_VERSION);
37:
38: //リファラチェック+リリースフラグの設定
39: if (isset($_SERVER['HTTP_HOST']) && ($_SERVER['HTTP_HOST'] == 'localhost')) {
40: define('FLAG_RELEASE', FALSE);
41: define('REFER_ON', '');
42: ini_set('display_errors', 1);
43: ini_set('error_reporting', E_ALL);
44: } else {
45: //リリース・フラグ(公開時にはTRUEにすること)
46: define('FLAG_RELEASE', TRUE);
47: //リファラ・チェック(直リン防止用;空文字ならチェックしない)
48: define('REFER_ON', 'www.pahoo.org');
49: }
50:
51: //表示幅(ピクセル)
52: define('WIDTH', 600);
53:
54: //スクレイピングURL(デフォルト)
55: define('DEF_URL', 'https://www.pahoo.org/e-soul/webtech/php02/php02-41-01.shtm');
56:
57: //スクレイピング処理に関わるクラス:include_pathが通ったディレクトリに配置
58: require_once('pahooScraping.php');

関数 require_once を使って、スクレイピング処理を行うクラス pahooScraping.php を読み込む。include_pathが通ったディレクトリに配置しておくこと。
解説:pahooScrapingクラスとDOMDocumentクラスの使い方
pahooScraping.php
13: class pahooScraping {
14: private $dom; //DOMDocument
15: private $xpath; //DOMXPath
16: private $language; //使用言語(初期値は日本語)
17: private $error; //エラー・メッセージ
18: private $errorTable; //エラー番号 => エラー・メッセージ 一覧
19:
pahooScraping.php
20: /**
21: * コンストラクタ
22: * @param string $contents 解析対象テキスト(UTF-8)
23: * @return object /NULL:PHP8未満のため実行できない.
24: */
25: function __construct($contents) {
26: //PHPのバージョンをチェックする.
27: if (! $this->isphp8over()) {
28: $this->error = 111;
29: throw new Exception($this->getErrorMessage());
30: return NULL;
31: }
32: //プロパティの初期値を設定する.
33: try {
34: // Unicodeの範囲を指定
35: $map = [ 0x80, 0xFFFF, 0, 0xFFFF ];
36: // DOMの文字化け対策:UTF-8文字を数値エンティティに変換
37: $contents = mb_encode_numericentity($contents, $map, 'UTF-8');
38: // DOMDocument クラス
39: $this->dom = new DOMDocument();
40: libxml_use_internal_errors(TRUE);
41: @$this->dom->loadHTML($contents);
42: libxml_clear_errors();
43: $this->xpath = new DOMXPath($this->dom);
44: } catch (Exception $e) {
45: $this->error = 121;
46: throw new Exception($e->getMessage());
47: return FALSE;
48: }
49:
50: //エラー番号 => エラー・メッセージ 一覧
51: $this->errorTable = array(
52: 111 => array('PHP8以上が必要です', 'PHP8 or higher is required'),
53: 121 => array('DOMエラーです', 'DOM error'),
54: 999 => array('不明のエラー', 'unknown error'),
55: );
56: }
まず、pahooScrapingg クラス内で使用するプロパティ $dom, $xpath, $error を宣言する。

コンストラクタは、__construct によって定義する。引数は、クラスを呼び出した時の引数である。ここでは解析対象のテキストを引数とする。UTF-8でエンコードしたテキストを渡すこと。戻り値はない。

次に DOMDocumentクラスの使い方だが、その前に DOM について簡単に説明しておこう。
DOM とは Document Object Model の略で HTML や XML 文書をオブジェクトとして扱えるようにしたモデルのことだ。モデルというと分かりにくいのだが、要するに、HTMLやXMLをツリー構造(階層構造)のデータとして扱うことができるようになり、タグや属性名を指定して、目的のコンテンツを読み込んだり編集したりする手段を提供してくれる。
たとえば、<title> タグの内容を取得したり、<a> タグで指し示すリンクを全て取得する、といった処理が簡単にできるようになる。スクレイピングするのに、打って付けの仕組みだ。

2024年(令和6年)10月現在、DOMDocumentクラス にコンテンツを投入するとき、エンコード指定より前に日本語などUTF-8文字があると文字化けが起きることがわかっている。そこで、投入する前に、 mb_encode_numericentity 関数を使って、UTF-8文字を数値エンティティ(HTMLエンティティ)に変換しておく。

コンストラクタで DOMDocument インスタンスを生成したら、DOMDocument::loadHTML を使って文字列からHTMLを読み込む。
DOM のエラー(例外)発生時に対応して、例外を返すようにしている。

ここで、文字コードに注意しなければならない。
DOMDocument::loadHTML は、HTML文書に記載されている文字コードセットを解釈しないようで、UTF-8などの日本語文字が文字化けを起こす。そこで、DOMDocument::loadHTML に渡す前に、関数 mb_convert_encoding を使って HTML-ENTITIES にエンコードしてやる。こうすることで、日本語文字などは16進数に変換されるので、文字化けを起こすことはなくなる。
pahooScraping.php
58: /**
59: * デストラクタ
60: * @return なし
61: */
62: function __destruct() {
63: unset($this->dom);
64: unset($this->xpath);
65: }
解説:XPath式の使い方
pahooScraping.php
134: /**
135: * 指定したXPath式を評価し,結果を返す.
136: * @param string $e XPath式
137: * @return DOMNodeList/FALSE:評価失敗
138: */
139: function evalXPath($e) {
140: return $this->error ? FALSE : $this->xpath->evaluate("string({$e})");
141: }
pahooScraping.php
152: /**
153: * titleを取得
154: * @return titleの内容
155: */
156: function getTitle() {
157: return $this->evalXPath('/html/head/title');
158: }
pahooScraping.php
160: /**
161: * descriptionを取得
162: * @return descriptionの内容
163: */
164: function getDescription() {
165: return $this->evalXPath('/html/head/meta[@name="description"]/@content');
166: }
PHPでは、DOMXPath クラスを使う。コンストラクタで、DOMXPath でオブジェクトを生成するところまでは実行している。
次に、DOMXPath::evaluate を使ってXPath式の評価(検索)をしていく。そのためのメソッド evalXPath を用意した。

titleタグの内容を取り出すメソッド getTitle と、'meta name="description" content=' の内容を取り出すメソッド getDescription を用意した。

ここで、XPath式 の書き方のエッセンスを紹介する。
XPath式は、HTML文書やXML文書をツリー構造として扱う。ツリーのノードとなるのはタグである。XPath式 を活用することで、HTML文書やXML文書からターゲット情報を簡単に取り出すことができる。

'/' は階層をあらわす。'/html/head/title]' は、「htmlタグ→headタグ→titleタグ」にマッチする。これに DOMXPath::evaluate を適用すると、titleタグの内容を取得できる。

'//' はドキュメント全体をあらわす。'//h2' は、bodyタグの直下にあるh2タグや、divタグで囲まれた内側にあるh2タグなど、どの階層のh2タグにもマッチする。

タグの中にある属性を示すには '@' を使う。たとえば '//a/@href' はあらゆる階層にあるaタグのhrefの値(=ハイパーリンク)にマッチする。
また、'//meta[@name="description"]/@content' は、あらゆる階層にある 「meta name="description"」タグの属性contentにマッチする。

述語 contains は、特定の文字列が含まれる要素にマッチする。たとえば //p[contains(text(), ‘PHP’)] は、あらゆる階層にあるpタグのうち「PHP」を含むpタグにマッチする。

PHPには XPath式を評価するメソッドとして、DOMXPath::evaluate、DOMXPath::query の2種類がある。
DOMXPath::evaluate は XPath式の評価結果によって返る値が異なる。たとえば '/html/head/title]' はマッチするtitleは1つだけのはずなので、titleタグで囲まれた文字列が返される。一方、'//h2' は複数あれば、DOMNodeList が返される。1つ1つのノードを調べたいときには、foreach文を使う。
DOMXPath::query は XPath式の評価結果が1つであろうが複数あろうが、常に DOMNodeList を返す。

XPath式の書き方は「【超便利!】XPathの基本や書き方まで、Webスクレイピング初心者にも分かりやすく解説」(JITERA)が詳しい。
参考サイト
- DOMDocumentクラス:PHP公式
- DOMXPath クラス:PHP公式
- 【超便利!】XPathの基本や書き方まで、Webスクレイピング初心者にも分かりやすく解説:JITERA
PHPバージョン5以上では、HTMLやXMLドキュメントをオブジェクトとして扱うことができる DOMDocumentクラスが用意されている。
そこで今回は、DOMDocumentクラスを使ってスクレイピングを行ってみることにする。他のプログラムでも利用できるよう、DOMDocumentクラスを利用する形のユーザー・クラス pahooScraping を用意した。
(2024年10月31日)__construct() 文字化け対策pahooScrapingクラスに変更
(2024年9月29日)getValueFistrXPath() 属性値でない指定に対応