--- title: 今更ながらPHPでスクレイピングをしてみる tags: PHP author: zaburo slide: false --- 以前は、PHP Simple HTML DOM Parserってのを使っていましたが、久しぶりに調べてみると、phpQueryというのがあるようなので、それを使ってみる。 オリジナルのものは[ここ](https://code.google.com/archive/p/phpquery/downloads)からダウンロードできるようです。 が、しばらくメンテされてないようです。[ForkしてComposerに対応したもの](https://github.com/zomberg/phpquery)もあるようです(試してません)。 なお、あまりTableを対象としたサンプルが無かったのでテーブルのスクレイピングを中心に書きます。 ##シンプルなデモ このようなHTML(test.html)があるとすると、 ```html scraping test

hoge

Hello
name hoge
email hoge@hoge.com
address tokyo
tel 03-1234-5678
image
detail more..
aaa
bbb
``` 例えば、タイトルを取得するのは、 下記のように取れるようである。 ```php text(); ``` なお、要素は、pq()メソッドを使って、 ```php echo pq("title")->text(); ``` と書くこともできるようです。 pq()は、jQueryの$()と等価であると共に、DOMをphpQueryで処理できるよう構造化する機能もあるようです。 ##基本的な使い方 $doc[""](もしくはpq(""))の""の中身はjQueryのセレクタが使えるので、基本、jQueryと同じように利用すればいいのですが、ちょっとしたクセもあるので、基本的な使い方のメモ。 必要な要素にidが振られていれば、操作に苦労はあまりないのですが、一意なidが振られていない場合は、要素の指定に少々工夫が必要です。 ###idで指定する ```php echo $doc["#greeting"]->text(); ``` ###classで指定する クラスの場合は複数の要素が存在するので、必要に応じて取得する要素を限定するようにします。 ```php echo $doc[".btn:eq(1)"]->text(); ``` ###静的に指定する 先述のHTMLには2行2列の2つのテーブルがあります。その2つ目のテーブルの1行目の2列目の要素(tokyo)を取得する場合は、 ```php echo $doc["table:eq(1) tr:eq(0) td:eq(1)"]->text(); ``` のように指定する。find()を利用して、 ```php echo $doc["table:eq(1)"]->find("td:eq(1)")->text(); ``` とも書けるようす。 ###foreachで回す 複数の値が返ってくる要素は、原則としてforeach()が利用できるようです。 ただ、tableの場合は、各td要素の値を個別に取得することができないようで、あまり使い勝手は良くありません。 ```php foreach($doc["table:eq(0) tr"] as $row) { //各要素取得 $key = pq($row)->find("td:eq(0)")->text(); $value = pq($row)->find("td:eq(1)")->text(); //表示 echo $key . " " . $value . "
"; } ``` 実務では、後述のcontains等を利用するこの方が多くなります。 ##利用サンプル ここでは実開発で利用するサンプルを随時の記述していきます。 ###特定の行の値を抽出 実運用では、テーブルの場合、特定の要素を抜く需要が多いかとおもいます。 例えばemailという項目を値を取得する場合は、containsと+を利用して、となりの要素を指定したりします。 ```php echo $doc["table"]->find("td:contains('email') + td")->text(); ``` ###HTMLをそのまま取得 ->text()ではなく、->html()を利用すれば、そのままのHTMLが取得できる。 ```php $html = $doc["table:eq(1)"]->find("td:contains('image') + td")->html(); ``` ###アトリビュートを取得 ```php $src = $doc["table:eq(1)"]->find("td:contains('image') + td img")->attr("src"); $href = $doc["table:eq(1)"]->find("td:contains('detail') + td a")->attr("href"); ```