LoginSignup
22
21

More than 5 years have passed since last update.

DOMDocument::loadHTML が meta の charset を解釈してくれない問題と対策

Last updated at Posted at 2013-06-23

概要

HTMLソースに「<meta charset="…" />」が指定してあっても DOMDocument::loadHTML は文字コード解釈に失敗することがあるよ、というお話。

実験対象

Qiita のトップページ。「<meta charset="UTF-8">」という記述があり、DOMDocument はこれを解釈できそうに見えます。

qiita.html
<!DOCTYPE html>
<html xmlns:og="http://ogp.me/ns#">
    <head><script type="text/javascript">var NREUMQ=NREUMQ||[];NREUMQ.push(["mark","firstbyte",new Date().getTime()]);</script>
    <meta charset="UTF-8">
    <title>Qiita [キータ] - プログラマの技術情報共有サービス</title>

サンプルコード

dom_charset.php
<?php
$url = "http://qiita.com/";
$body = file_get_contents($url);
$dom = new DOMDocument();
@$dom->loadHTML($body);
$title = $dom->getElementsByTagName('title')->item(0)->textContent;
print "$title\n";

サンプル実行結果

$ php dom_charset.php 

      Qiita [ã­ã¼ã¿] - ãã­ã°ã©ãã®æè¡æå ±å±æãµã¼ãã¹

文字化けだ!/(^o^)\

原因・対策

原因

環境によるかもしれないが、少なくとも自分の環境 (PHP 5.3.3) では、
どうやら DOMDocument::loadHTML は「<meta charset=…」ではなく「<meta http-equiv=…」のタグ情報を元に文字コードを判定しているらしい。

<!-- これがあっても意味がない -->
<meta charset="UTF-8" />

<!-- こっちを解釈する -->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

コード修正

全サイトの管理者に「<meta http-equiv=…」のタグを埋め込んでもらうことを期待するのは現実的ではないので、
取得したHTMLソースを置換してやると良い。(今回はあくまでも対症療法として単純な置換で済ませます)

dom_charset2.php
<?php
$url = "http://qiita.com/";
$body = file_get_contents($url);
$body = str_replace('<meta charset="UTF-8">', '<meta charset="UTF-8"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">', $body);
$dom = new DOMDocument();
@$dom->loadHTML($body);
$title = $dom->getElementsByTagName('title')->item(0)->textContent;
print "$title\n";

実行結果

$ php dom_charset2.php 

      Qiita [キータ] - プログラマの技術情報共有サービス

直った!\(^o^)/

22
21
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
21