【PHP】file_get_contents()で取得したWebページの文字化け対策
更新日:2023/03/20
PHPでfile_get_contents()を使ってWebページをダウンロードすると、内容が文字化けすることがあります。
これはPHPの内部エンコードとWebページのエンコードが異なるのが原因です。
そこで文字化け対策として、Webページのエンコードを内部エンコードに変換します。
内部エンコードと一致させる関数
とりあえず、文字化け対策で作成したコードを紹介します。
function html_convert_encoding($html){
$internal = mb_internal_encoding(); // 内部エンコーディング取得
if( $internal === null ) return $html; // 内部エンコーディングが設定されていない
$encode = get_html_encoding($html);
if( $encode === false ){ // htmlにエンコードなし
$html = mb_convert_encoding( $html , mb_internal_encoding() , "auto" );
}elseif( strtoupper($internal) !== strtoupper($encode)){ // 内部エンコードと不一致
try{
$html = mb_convert_encoding( $html , $internal , $encode );
}catch(Exception $e){ // 存在しないエンコードを指定した
}
}
return $html;
}
// エンコードに関するタグからエンコードを取得
function get_html_encoding($html){
$regexs = [
[['regex'=>'#<meta\s*[^>]*charset=([\'"])(.*?)\1.*?>#','index'=>2]],
[
['regex'=>'#<meta\s*[^>]*http-equiv=([\'"])content-type\1.*?>#i','index'=>0],
['regex'=>'#content=([\'"])(.*?)\1#i','index'=>2],
['regex'=>'#charset=([^\s]*)#i','index'=>1],
],
];
foreach( $regexs as $regex_aray ){
$result = $html;
foreach( $regex_aray as $regex ){
if( preg_match( $regex['regex'] , $result ,$matches) === 1 ){
$result = $matches[$regex['index']];
}else continue 2;
}
return $result;
}
return false;
}
使い方は、file_get_contents()で取得したhtmlデータを引数で渡すだけです。
$url = 'http://ドメイン名/xxxx';
$html = file_get_contents($url);
if( $html === false )
return false; // 読み込み失敗
$html = html_convert_encoding($html);
echo $html;
解説
htmlのエンコードは、metaタグで判断します。
時々ですが、metaタグと実際のエンコードが異なることがあります。
このケースはブラウザ表示でも文字化けするので、今回はmetaタグ優先で良いと判断しました。
metaタグの取得は、今回紹介したコードの2つ目の関数get_html_encoding()で行っています。
対象となるのは、次の二つのタグです。
<meta charset="エンコード">
<meta http-equiv="Content-Type" content="text/html; charset=エンコード" />
これを正規表現で取得しているのですが、二つ目のタグは一回で取得するに複雑な正規表現が必要なので無理せずに数回に分けています。
htmlのエンコードを取得できてPHPの内部エンコードと異なるなら、取得したエンコードから内部エンコードに変換しています。
エンコードを取得できなかったら、PHPにお任せでエンコードしています。
更新日:2023/03/20
関連記事
スポンサーリンク
記事の内容について
こんにちはけーちゃんです。
説明するのって難しいですね。
「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。
裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。
掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。
ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php
このサイトは、リンクフリーです。大歓迎です。