ホーム > ブログ [果報は寝て待て] > PHP で DOM をいじくって href や src の内容を書き換えてみる

ブログ [果報は寝て待て]|Blog

PHP で DOM をいじくって href や src の内容を書き換えてみる

2017年3月17日 14:14

しばらくブログをまーったく書いていなかったので、久しぶりにちょいと技術的なメモを。

今回は、とある HTML ファイル(HTMLのパーシャル)をメインの PHP に取り込んで表示させるっていう必要に迫られたんですが、その HTML の中身は直接編集不可…という罰ゲームっぽいものになっておりますw

で、直接編集不可な上に、a タグの href やら img タグの src なんかに記載されている相対パスにベース URL をくっつけるという…何やら魔術的なことを行うと・・・w

js でちょちょっとやろうかとも思ったんですが、パーシャルなので PHP 側で取り込む時にどーにかしたいなと…色々調べた結果、ありました!「PHP の DOM 拡張」。

何はともあれ…書いてみる。

<?php
// DOMDocument クラスのインスタンス作成
$dom = new DOMDocument();
 
// 何はともあれ取り込みたいファイルの内容を取得
$doc = mb_convert_encoding(file_get_contents('test.html'), 'UTF-8', 'sjis-win, sjis');
 
// 中身の HTML をパース
@$dom->loadHTML($doc);
 
// a タグを全て取得
$anchors = $dom->getElementsByTagName('a');
 
// 取得したタグの href 属性値を書き換える
foreach ($anchors as $anchor) {
    $value = $anchor->getAttribute('href');
 
    if (preg_match('/^https?/', $value)) continue;
 
    $anchor->setAttribute('href', 'http://shape-design.jp/' . $value);
}
 
// HTML はパーシャルで欲しいのでいらないもの削除
$html = preg_replace('/^<!DOCTYPE.+?>/', '',
    str_replace(
        array('<html>', '</html>', '<body>', '</body>'),
        array('', '', '', ''),
        $dom->saveHTML()
    )
);
 
// 表示(ホントはこれを PHP 側に取り込む)
echo $html;
?>

こいつは便利じゃないかーっ!

ちなみに、文字化けしちゃう場合は以下のようにしてエンティティ化すればよいとか…。

$doc = mb_convert_encoding(file_get_contents('test.html'), 'HTML-ENTITIES', 'sjis-win, sjis');

そんなわけで、いろいろなタグやら属性値に対応できるように関数化してできあがったのがこちらっ!
※細かいこと言えば、ページ内リンクとかその他色々どーするんだよって話ですが…。
※ちなみに、この記事向けに書き直したので、このままで動くかは不明です(汗

<?php
$base_url = 'http://shape-design.jp/';
 
echo convert_paths();
 
/**
 * 全てのタグ属性のファイルパスを絶対 URL に変換
 *
 * @return string
 */
function convert_paths() {
    $dom = new DOMDocument();
    $dom->preserveWhiteSpace = false;
    $dom->formatOutput       = true;
    @$dom->loadHTML(mb_convert_encoding(
        file_get_contents($base_url . 'test.html'), 'HTML-ENTITIES', 'sjis-win, sjis'
    ));
 
    $tag_anchors = $dom->getElementsByTagName('a');
    convert_path($tag_anchors, 'href');
 
    $tag_images = $dom->getElementsByTagName('img');
    convert_path($tag_images, 'src');
 
    $tag_forms = $dom->getElementsByTagName('form');
    convert_path($tag_forms, 'action');
 
    // パーシャルな HTML のみに整形
    $html = preg_replace('/^<!DOCTYPE.+?>/', '',
        str_replace(
            array('<html>', '</html>', '<body>', '</body>'),
            array('', '', '', ''),
            $dom->saveHTML()
        )
    );
    return $html;
}
 
/**
 * タグ属性のファイルパスを絶対 URL に変換
 *
 * @param object $nodes
 * @param string $attribute
 * @return object
 */
function convert_path($nodes, $attribute) {
    foreach ($nodes as $node) {
        $value = $node->getAttribute($attribute);
        if (preg_match('/^https?/', $value)) continue;
 
        $node->setAttribute($attribute, $base_url . $value);
    }
 
    return $nodes;
}
?>

ちなみに、サーバーにインストールされている PHP に DOM 拡張モジュールが必要なので、使用する際は phpinfo() なんかで要確認ってとこでしょうか。
そんなわけで、今回はここまで!ではまたっ!←いつになるやら(苦笑

※このスクリプトにおいて、動作の検証は行っていませんので、責任は一切負いません。
※参考 URL
PHP: DOMDocument - Manual
絶対URLから相対URLに変換する処理(PHP)|teratail
PHP5のDOM拡張モジュールでHTMLをパースする | Firegoby
【PHP】DOMDocument::loadHTML()で日本語が化けるときの対処法と残った謎 - Fatal Error: Unexpected BLOG

shape DESIGN - シェイプデザイン, 徳島県徳島市名東町, tel/fax 088-635-5859, 営業時間 平日10:00〜18:00

まずはお気軽にお問い合わせください
お問い合わせ・お見積り・ご相談はこちら
お気軽にご相談ください

徳島県徳島市名東町
tel/fax 088-635-5859
営業時間 平日 10:00〜18:00

※打ち合わせ等で不在の場合は、お電話でのお問い合わせに対応できない場合がありますので、ご了承ください。

フォームからのお問い合わせ

徳島・香川・愛媛・高知および大阪・京都を中心にご依頼を承ります。その他の地域でも、メール・お電話・FAX・Skype等での作業が可能であれば柔軟に対応いたします。

  • Become our fan on Facebook, facebook.com/shape.design