Goutte(PHP)の使い方|HTMLを解析(パース)する方法

400px-PHP-logo.svg

こんにちは、永橋です。

今回は「PHPでHTMLを解析(パース)する方法」を紹介したいと思います。

PHPでのHTMLパースはPHP Simple HTML DOM Parserを使った手法がメジャーですが、今回はGoutteというライブラリを使用します。

Goutteのダウンロード
https://github.com/fabpot/Goutte/archive/master.zip

また、一緒に必要になるGoutte.pharもダウンロードします。

Goutte.pharのダウンロード
http://get.sensiolabs.org/goutte.phar

これらのファイルをアップロードすると準備完了です。

Goutteの詳しい使い方は、以下のサイトを参考にさせていただきました。

WebスクレイピングライブラリGoutteで遊んでみる
http://d.hatena.ne.jp/hnw/20120115

さっそくHTMLの解析を実行!

試しにこんなPHPスクリプトを実行してみると……

<?php
require_once 'goutte.phar';
use Goutte\Client;
$client = new Client();
$crawler = $client->request('GET', 'http://www.ss-complex.com');
$crawler->filter('title')->each(function($node)
{
echo $node->text();
});
?>

Smart Style Complex Inc. | さいたま市浦和区のホームページ制作会社|スマートスタイルコンプレックス株式会社のWebサイトです。

というテキストが表示されます。

  • $client->request()で指定されたURLからソースを取得
  • $crawler->filter()でタグの絞込検索
  • $crawler->filter()->each(function($node)
    {
    //処理
    });
    の処理と書かれている部分で見つかったタグに対してループ処理

という感じですね。

$nodeという変数には、いくつかの関数がありますが、今回はtext()を使っています。

text()を使うと、filterにて絞りこまれたタグの中にある文章をそのまま返してくれます。これの注意点は、返してくれる文章にタグが含まれない、ということです。

ブログなどの記事の本文を抜き出すときにこのtext()を使うと、改行が省かれずらーっと文章が続いてしまうのです。

こういうときはどうするか、というと、text()ではなくhtml()を使います。

$node->html()


というようにすると、タグ情報も全て返してくれます。

特殊文字を文字列に戻す方法

ただこれも一癖あり、全て数値文字参照で返ってきます。&#00000;...とかいう文字ばかりになり、ちょっとめんどくさいです。そのまま使うと、見かけ上普通の文章で表示されますがソースを見てみると…あれっというふうになっているのです。

こういうときは、mb_convert_encoding()という関数を使います。

mb_convert_encoding($node->html(), 'UTF-8', 'HTML-ENTITIES')

としてやると、ソースもちゃんとした文章で表示されます。

それではこれらを利用した例として、自分が先日書いた、アプリ紹介の記事からアプリ名を取得してくるPHPスクリプトを示します。

<?php
require_once 'goutte.phar';
use Goutte\Client;
$client = new Client();
$crawler = $client->request('GET', 'http://ss-complex.com/2014/04/famous_android_apps/');
$crawler->filter('a')->each(function($node)
{
if($node->attr('target')==="_blank"&&!strstr($node->html(), 'html()."
\n"; echo mb_convert_encoding($node->html(), 'UTF-8', 'HTML-ENTITIES')."
\n"; } }); ?>

これを実行すると、5つのアプリ名が2回ずつ表示されると思います。

それぞれ、html()のみで表示した場合、mb_convert_encoding()を使用した場合となっており、ソースを見てみると日本語のアプリ名は片方が&#~という形になっているのがわかるでしょう。

一見、何ができるの?と思うかもしれませんが、実はこれでブログ記事の抽出ができたり、他サイトの更新内容を取得して自分だけのポータルサイトを作る…ということができてしまいます。

自分はこれを使い、特定のサイトの内容をメールで自分宛てに送信する…というスクリプトを作っています。

興味があればみなさんもいろいろ試してみてください!