さとうさんのキロク

生活と雑記と時々ネコ

PHPでHTMLをパースして解析、編集して保存する方法

あるページをPHPで解析して、余分な箇所を除去したい。そんなことがありました。
そこでなーんかいい方法はないものかと調べたところ「PHP Simple HTML DOM Parser」なる物があることがわかりました。
実際は結構前からわかっていたけど記事起こしが今回初。

PHPでHTML解析するのは結構めんどくさい

方法の一つとしてUTF-8へエンコーディング変換した後のHTMLをDOMDocumentクラスを利用して整形後、
出力結果をsimplexml_load_string関数でHTMLをオブジェクトとして取得し、結果を元に値の取得はできます。
こちらのページで詳しく記載されています。(PHPでHTMLをパースして解析する簡単な方法

本当にしたい事はHTMLの解析だけではなく編集もして保存すること

単純にHTMLページの解析をして値を取得するのはできますが、本当に私がしたいことは「あるHTMLページの余分な部分除去」です。
例えばページ内のリンクを全てカットしてHTMLを保存する。
解析でDOMDocumentをつかって〜だと、またHTMLに戻すのに手間がかかるのでそのまま編集して使いたい。
そこで登場するのが「PHP Simple HTML DOM Parser」になります。

ダウンロードやマニュアルはこちら

PHP Simple HTML DOM Parser
PHP Simple HTML DOM Parser Manual

HTMLを読み込む

URL、ファイルからHTMLを読み込む
$dom = file_get_html('http://www.google.co.jp/');
HTMLデータをそのまま読み込む*1
$dom = str_get_html('<div>Hello</div><div>World</div>');

要素を探して除去する

検索結果の1つ目を除去する
$dom->find('script',0)->outertext = '';

発見されたscript要素が開始タグ〜終了タグまるごと消去されます。

img要素を検索した際のsrc属性の値がすべてを除去する
foreach ($dom->find('img') as $el) {
    $el->src = null;
}

結果、img要素のsrc値がすべて消えるためHTMLで定義されている画像すべてが表示されなくなります。
(cssで定義したものは残ります)

保存する

$body = $dom->save();
$dom->clear();

実行サンプル

読み込むHTML

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
  <title>sample</title>
  <meta name="viewport" content="width=device-width; initial-scale=1.0" />
  <script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
  <script>
  alert("TEST SCRIPT");
  </script>
</head>
<body>
  <div>
    <header>
      <h1>sample</h1>
    </header>
    <nav>
      <p><a href="/">Home</a></p>
    </nav>
    <div>
      <img src="sample1.png">
      <img src="sample2.png">
      <img src="sample3.png">
      <img src="sample4.png">
    </div>
    <footer>
     <p>&copy; Copyright  by satosan</p>
    </footer>
  </div>
</body>
</html>

実行PHP

<?php
require_once 'simple_html_dom.php';
	
//ファイル形式で読み込む
$dom = file_get_html("sample.html");
	
//1つめに見つかったscript要素を除去
$dom->find('script',0)->outertext = '';
	
//img要素のsrc属性除去
foreach ($dom->find('img') as $el) {
	$el->src = null;
}
	
//実行結果を保存しHTMLを取得
$body = $dom->save();
$dom->clear();
	
//HTML結果の表示
echo $body;
?>

実行によって得られたHTMLの結果

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
  <title>sample</title>
  <meta content="width=device-width; initial-scale=1.0" name="viewport">
  <script>
  alert("TEST SCRIPT");
  </script>
</head>
<body>
  <div>
    <header>
      <h1>sample</h1>
    </header>
    <nav>
      <p>
      <a href="/">Home</a>
      </p>
    </nav>
    <div>
      <img>
      <img>
      <img>
      <img>
    </div>
    <footer>
      <p>&copy; Copyright by satosan</p>
    </footer>
  </div>
</body>
</html>

まとめ

実行サンプルを見て頂くわかる通り、1つ目のscriptタグが除去とimg要素のsrcも除去される。
(jquery読み込み行と4つあるimgタグのsrcがなくなっていると思います。)
これにより、状況に応じた表示の結果を変更することも可能になる。逆に属性の追加なんかも可能です。
ただ、今回のテーマが余分な要素、属性の除去であるため今回は割愛します。

私もこの「simple_html_dom.php」は余分な要素除去にのみしか利用したことがなく、
他にいい感じの利用方法までまだ試していませんが、特定のクラスやID、属性による検索などもできるので、
応用の幅は非常に高いと思います。

*1:すべてのHTMLである必要はなく部分的なHTMLでも解析が可能です。