Článek v rubrikách:
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:
- detekce vstupního kódování, parsování tagu meta pomocí regulárních výrazů,
- pomocí ICONV převod na kódování UTF-8 s parametrem //IGNORE,
- odstranění případného tagu <?xml ... ?> pomocí regulárních výrazů,
- nahrazení meta tagu s informací charset za <meta http-equiv="content-type" content="text/html; charset=utf-8" /> pomocí regulárních výrazů,
- 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
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



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