Článek v rubrikách:

»PHP
»XML
»HTML

Parsování HTML pomocí DOM, kódování stránky windows-1250, ISO-8859-2 a další.

Parsovat české html stránky pomocí XPATH a DOMDOCUMENTu není žádná sranda. Trápil jsem se s tím hodně dlouho.


Zkuste si někdy parsovat html stránku s kódováním windows-1250 nebo jiným než ISO-8859-1. Za použití DOMDocumentu je to práce na dlouhé večery.

Jestli jsem něco přehlédl budu rád, když mi to někdo vysvětlí. Nicméně něco je špatně a nepodařilo se mne to standardní cestou rozchodit.

Základní věc je, že DOM interně pracuje v UTF-8, xpath pracuje také v UTF-8, výsledek, který ovšem získáte z parsování je v původním kódování. Tedy jakákoli další práce je v podstatě nemožná.

Pomocí funkce loadHTML se DOM pokusí detekovat o jaké kódování se jedná, to se snaží zjistit z tagu <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-2" />, nejen že další práce s DOM je nespolehlivá (vytáhutá data z dom stromu jsou neurčitého kódování) ona není spolehlivá ani ta detekce. Někdy prostě nefunguje. V takovém případě dojde k načtení textu v kódování ISO-8859-1 a jeho převední do UTF-8, což kompletně stránky rozhodí.

Přes veškeré snahy se mi podařilo uskutečnit pouze tento plán:

  1. detekce vstupního kódování, parsování tagu meta pomocí regulárních výrazů,
  2. pomocí ICONV převod na kódování UTF-8 s parametrem //IGNORE,
  3. odstranění případného tagu <?xml ... ?> pomocí regulárních výrazů,
  4. nahrazení meta tagu s informací charset za <meta http-equiv="content-type" content="text/html; charset=utf-8" /> pomocí regulárních výrazů,
  5. teď jsme převedli html stránku do kódování UTF-8, což ještě musím DOMDocumentu oznámit takto @$dom->loadHTML('<?xml encoding="UTF-8">' . $html);

Nyní se teprve mohu spolehnout na výstup, který pomocí xpath získám a mohu uložit třeba do databáze.

Máte někdo jednodušší workaround?


 

 

komentáře

RSS Komentáře k článku RSS Komentáře   Add to Google
18.05.2010 20:52 | Anonym (Karel Hák) | Jednodušší postup

Nejprve zdrojový kód stránky převedu na utf-8 pomocí funkce autoUTF od DG a poté

<?php
$doc->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'utf-8'));
?>
20.05.2010 10:02 | Administrátor | Re: Jednodušší postup

pletu se nebo to nebude fungovat?

1. ano, první dva kroky by mohla nahradit fce autoUTF od dg

<?php

function autoUTF($s)
{
    // detect UTF-8
    if (preg_match('#[\x80-\x{1FF}\x{2000}-\x{3FFF}]#u', $s))
        return $s;
    // detect WINDOWS-1250
    if (preg_match('#[\x7F-\x9F\xBC]#', $s))
        return iconv('WINDOWS-1250', 'UTF-8', $s);
    // assume ISO-8859-2
    return iconv('ISO-8859-2', 'UTF-8', $s);
}


?>

nicméně spoléhá jen na dvě kódování což by nemusela být pravda

2. DOM pozná kódování podle charsetu v meta tagu, proto, by se měl nahradit, ale ani to není spolehlivé, proto byl přidán ještě bod 5

Jméno
Název
Text
Lze používat Texy! syntax. Příklad syntaxe: "text odkazu":odkaz, **tučně**, *kurzíva*, `code`. PHP kód uzavírejte do <?php ... ?> a JavaScript do <script> ... </script>