Доброго времени суток! Я парсю страницу которая находится в кодировке windows-1251, либо в др. кодировках. Мой скрипт в кодировке utf-8. Вопрос в том, как определить кодировку загруженного HTML кода и перекодировать его в utf-8? Перекодировать я могу(iconv), а вот как определить незнаю. Регулярные выражения не помогают, mb_detect_encoding врет. Регялярками пытаюсь сделать так Код (Text): preg_match('/(?<=charset=)(.*)(?=(?:")|(?:\'))/iu',$html, $matches); Но эта регулярка работает только в том случае, если $HTML в кодировке UTF-8. Вот и получается что определить не получается соответственно и весь скрипт летит в топку. Помогите пожалуйста решить проблему! Заранее спасибо.
добро пожаловать в интернеты)))) тут кодировку много кто устанавливает. когда я писал поисковик я опирался на: 1. то что вебмастер написал в метатеге своего сайта 2. то что пришло заголовками от сервера у второго вес больше. на основании полученной кодировки я пробовал перегонять текст в юникод или сразу работал с ним
У меня парсер работает только с UTF-8 другие не признает, подскажи как решить проблему, на хабре кучу статей читал результат 0 все функции обманывают
единственный вопрос - откуда страница берется? если с локальной файловой системы, то я пасс - много времени потратил на изобретение идеального распознания кодировки и все бес толку, если честно. если же от веб-серверов - то, как уже было описано выше - 1 это грабим метатег из исходного кода, 2 заменяем значение из первого шага кодировкой полученной от сервера (если такая была). и чтоб лишних вопросов не было сразу ясность вносим - 1 я как и ты через регулярки цеплял, 2 же разбор работы cURL с опцией CURLOPT_HEADER в true
Скрипт парсит сайты в сети, не локал. Вот именно что регулярки не работает если кодировка загруженной страницы не UTF-8
теперь внимание вопрос. какое может быть значение у метатега кодировки? [a-z0-9-] - вот все варианты которые там можно встретить. флаг юникода тут не нужен. как может быть задана кодировка? по-старинке: <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> или ближе к хтмл5: <meta charset="utf-8"> в мозгах вебмастеров могут быть отклонения от стандартов. например, одинарные кавычки для значения атрибутов или пробел(ы) между именем-равно-значением
предлагаю тебе просто забить на это - пробела между именем и значением атрибута не будет по стандарту, а одинарные кавычки или их отсутствие допускается хоть и не прощается. если человек пишет инвалидные страницы - зачем тебе прогибаться под него? он метатегом может давать тебе одну кодировку, пых быть настроен на другую, апач на третью, а файл вообще в четвертой сохранен. это клиника уже, конечно, но и такое видали... ищи последовательность charset= и после нее одна какая-нибудь кавычка или ее не будет и дальше все подстановкой, указанной мною выше. и всё. да, можно конечно добавить еще что это обязательно метатег должен быть, а то вдруг речь в на странице идет про кодировку.
блин задолбала эта кодировка уже... вот например есть три сайта m.mail.ru stihi.in.ua php.ru у всех разные кодировки, мне просто искать в коде совпадения со строками charset=utf-8 charset=windows-1251 и др.? Добавлено спустя 40 минут 10 секунд: Вроде решил трабл так: Код (Text): preg_match('/(?<=charset=)(.*)(?=(?:")|(?:\'))/iu',$html, $xd); if(strlen($xd['1'])!=0) {$charset=$xd['1'];} else {$charset='';} if($charset=='') { $zxdsl = iconv(detect_encoding($html),'utf-8', $html); preg_match('/(windows-1251)/iu',$zxdsl, $xd).'<hr />'; if(strlen($xd['1'])!=0) {$charset=$xd['1'];} else {$charset='';} if($charset!='') {$html=$zxdsl;} else {} } Работает так: 1)Если кодировка не найдена создаем переменную $zxdsl и присваиваем ей значение переменной $html только в перекодированном из полученной с помощью detect_encoding функции(она у меня в коде, чуть ниже скину код) в utf-8 виде, что бы английские буквы стали понятны 2)Если кодировка найдена, значит все найс 3)Если кодировка не найден то будь что будет, сами виноваты А вот собственно функция detect_encoding которая работает лучше чем mb_detect_encoding. Код (Text): function detect_encoding($string, $pattern_size = 50) { $list = array('cp1251', 'utf-8', 'ascii', '855', 'KOI8R', 'ISO-IR-111', 'CP866', 'KOI8U'); $c = strlen($string); if ($c > $pattern_size) { $string = substr($string, floor(($c - $pattern_size) /2), $pattern_size); $c = $pattern_size; } $reg1 = '/(\xE0|\xE5|\xE8|\xEE|\xF3|\xFB|\xFD|\xFE|\xFF)/i'; $reg2 = '/(\xE1|\xE2|\xE3|\xE4|\xE6|\xE7|\xE9|\xEA|\xEB|\xEC|\xED|\xEF|\xF0|\xF1|\xF2|\xF4|\xF5|\xF6|\xF7|\xF8|\xF9|\xFA|\xFC)/i'; $mk = 10000; $enc = 'ascii'; foreach ($list as $item) { $sample1 = @iconv($item, 'cp1251', $string); $gl = @preg_match_all($reg1, $sample1, $arr); $sl = @preg_match_all($reg2, $sample1, $arr); if (!$gl || !$sl) continue; $k = abs(3 - ($sl / $gl)); $k += $c - $gl - $sl; if ($k < $mk) { $enc = $item; $mk = $k; } } return $enc; }