- Записки PHP-шника
- Как исправить кодировку сайта в ответ на cURL запрос?
- Перекодировка текста UTF-8 и WINDOWS-1251
- windows-1251 в UTF-8
- UTF-8 в windows-1251
- Когда ни что не помогает
- File_get_contents / CURL
- Как скачать файл с кириллицей в URL?
- Форум PHP программистов ► PHP практикум ► GD, XML, CURL, PEAR & PECL
Записки PHP-шника
Появилась задача распарсить содержание сайта с кириллическим доменом.
Попробовал вставить ссылку в стандартную обёртку для Curl в PHP. Оказалось, что Curl не работает с такими ссылками. Чего и следовало ожидать 🙂
Покопавшись в Интернете, нашёл следующую информацию:
Для интернационализированных доменных имен решение, предлагаемое ICANN, основано на использовании преобразования Puny Code, которое трансформирует набор кодовых символов Unicode (как правило, UTF-8) в цепь символов ASCII уникальным и обратимым способом. Например, в названии доменного имени «académie-française.org» буквы с апострофами не являются кодами ASCII. Puny Code преобразует данное доменное имя в «xn—acadmie-franaise-npb1a.org», а, например, http://русский.idn.icann.org превращает в http://xn—h1acbxfam.idn.icann.org. При этом знаки, не являющиеся кодами ASCII, пропадают в таком названии.
Из сказанного выше следует,что до кириллических доменов можно достучаться ещё и по альтернативному адресу закодированному в Puny Code. Как показывает тестирование, как браузер, так и Curl отлично понимают адреса закодированные через Puny Code. То есть в принципе есть возможность распарсить кириллический домен, нужно только знать его закодированный адрес.
Для перекодирования доменного имени можно воспользоваться готовым решением., которое представлено тут http://www.phpclasses.org/browse/file/5845.html
Приведу решение на PHP для перекодирования доменного имени и получения содержимого страницы через Curl.
$converter = new idna_convert();
$domain = parse_url($url, PHP_URL_HOST);
$encoded_domain = $converter->encode($domain);
$url = str_replace($domain, $encoded_domain, $url);
$resource = curl_init();
curl_setopt($resource, CURLOPT_URL, $url);
curl_setopt($resource, CURLOPT_URL, $url);
curl_setopt($resource, CURLOPT_TIMEOUT, 30);
curl_setopt($resource, CURLOPT_MAXREDIRS, 10);
curl_setopt($resource, CURLOPT_RETURNTRANSFER, true);
Как исправить кодировку сайта в ответ на cURL запрос?
Проблема следующая, в ответ на curl приходит сайт в котором в meta прописана кодировка windows-1251 из-за этого на сайте отображаются иероглифы.
Данную проблему решил с помощью:
$isWinCharset = mb_check_encoding($postResult, "windows-1251"); if ($isWinCharset)
Теперь если в meta стоит кодировка windows-1251 сайт отображается корректно.
Если в meta стоит кодировка utf-8 сайт отображается корректно.
Обрадовался.
Но вдруг нашел пару сайтов, которые слетели после добавления:
$isWinCharset = mb_check_encoding($postResult, "windows-1251"); if ($isWinCharset)
в meta указана кодировка UTF-8 а сайт в результате в иероглифах, пример такого сайта: e-qa.ru/autoprodazha
Таких сайтов не много но они есть и очень раздражают, большинство сайтов где в meta UTF-8 работают корректно. Видимо кодировка самого файла у данного сайта e-qa.ru/autoprodazha отличается от указанной в meta из-за этого происходит конфликт.
Помогите разобраться и устранить иероглифы на всех сайтах, кучу методов перепробовал и все взаимоисключающие 🙁
Собственно Вам удаленный сайт уже и так всё говорит, почему бы не учесть то, что он говорит?
1. Заглядываем в заголовки HTTP ответа, видим:
Content-Type:text/html; charset=UTF-8
2. Заглядываем в контент страницы, видим:
3. Есть еще один метод подсказать кодировку:
Решение — смотрим, чего нам говорят, подставляем в качестве параметра для iconv, но не забываем дефолтное значение на всякий случай.
Вариант решения — если сайтов в ограниченное количество, храните где-то предпочитаемую кодировку.
Фрагмент на python, реализующий автоматическое декодирование на основании заголовка ответа:
encoding='utf-8' # кодировка по умолчанию tmp = r.headers.get('Content-Type').split('=') #режем по =, что справа - кодировка if len(tmp)>1: #если кодировка в заголовке есть - будет 2 элемента encoding=tmp[-1] # тогда берём последний page = r.content.decode(encoding)
1) < $headers[strtolower($tmp[0])] = trim(strtolower($tmp[1])); >> $encoding="utf-8"; //default if (isset($headers['content-type'])) < $tmp = explode("=", $headers['content-type']); if (count($tmp)>1) $encoding = $tmp[1]; > if ($encoding != "utf-8") $postResult = iconv($encoding, "UTF-8", $postResult);
Всё. Получаем расширенный ответ, который содержит заголовки. Вырезаем из него заголовки и режем их в массив, плюс достаём тело ответа.
Парсим заголовки http, вытаскиваем content-type и из него вытаскиваем кодировку
Перекодировка текста UTF-8 и WINDOWS-1251
Проблема кодировок часто возникает при написании парсеров, чтении данных из xml и CSV файлов. Ниже представлены способы эту проблему решить.
windows-1251 в UTF-8
$text = iconv('windows-1251//IGNORE', 'UTF-8//IGNORE', $text); echo $text;
$text = mb_convert_encoding($text, 'UTF-8', 'windows-1251'); echo $text;
UTF-8 в windows-1251
$text = iconv('utf-8//IGNORE', 'windows-1251//IGNORE', $text); echo $text;
$text = mb_convert_encoding($text, 'windows-1251', 'utf-8'); echo $text;
Когда ни что не помогает
$text = iconv('utf-8//IGNORE', 'cp1252//IGNORE', $text); $text = iconv('cp1251//IGNORE', 'utf-8//IGNORE', $text); echo $text;
Иногда доходит до бреда, но работает:
$text = iconv('utf-8//IGNORE', 'windows-1251//IGNORE', $text); $text = iconv('windows-1251//IGNORE', 'utf-8//IGNORE', $text); echo $text;
File_get_contents / CURL
Бывают случаи когда file_get_contents() или CURL возвращают иероглифы (ÐлмазнÑе боÑÑ) – причина тут не в кодировке, а в отсутствии BOM-метки.
$text = file_get_contents('https://example.com'); $text = "\xEF\xBB\xBF" . $text; echo $text;
Ещё бывают случаи, когда file_get_contents() возвращает текст в виде:
Это сжатый текст в GZIP, т.к. функция не отправляет правильные заголовки. Решение проблемы через CURL:
function getcontents($url) < $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_ENCODING, 'gzip'); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); $output = curl_exec($ch); curl_close($ch); return $output; >echo getcontents('https://example.com');
Как скачать файл с кириллицей в URL?
Добрый вечер! Пишу небольшой парсер новостей. Возникла проблема со скачиванием файлов с кириллическими символами в url.
http://blobproxy-cdn.skoda-auto.com/wwk2-sitecollectionimages/news/march/škoda_на_ралли_акрополис_(2)__201403302311.jpg http://blobproxy-cdn.skoda-auto.com/wwk2-sitecollectionimages/news/march/в_млада-болеславе_произведено_11_000_000_автомобилей_škoda_201403302311.jpg
$url = urlencode('http://blobproxy-cdn.skoda-auto.com/wwk2-sitecollectionimages/news/march/в_млада-болеславе_произведено_11_000_000_автомобилей_škoda_201403302311.jpg'); $url = str_replace(array('%3A','%2F'), array(':','/'), $url); $data = file_get_contents($url);
Привет! ) Да — это решение! Спасибо большое. Я тоже думал эти символы поменять, но до дела не дошло)))
http://some.domain.org//Uploads/images/408/А,Б%20секция%203%20этаж%204%20квcrop.jpg
т.е. смесь бульдога с носорогом — и слэши лишние, и нелатиница, и пробел в форме %20 .
Помогло следующее решение, по мотивам Andr’U Sender :
if (preg_match('#^([\w\d]+://)([^/]+)(.*)$#iu', $filenameSrc, $m)) < $filenameSrc = $m[1] . idn_to_ascii($m[2], IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46) . $m[3]; >$filenameSrc = urldecode($filenameSrc); $filenameSrc = rawurlencode($filenameSrc); $filenameSrc = str_replace(array('%3A','%2F'), array(':', '/'), $filenameSrc);
Замечу, что если пытаться использовать urlencode , а не rawurlencode , то тот кодирует пробелы в «+» плюсы и ссылка открываться не желала в таком виде. А с %20 как делает rawurlencode — прокатило.
Надеюсь кому-то спасёт немного волос 🙂
Форум PHP программистов ► PHP практикум ► GD, XML, CURL, PEAR & PECL
Профиль
Группа: Пользователь
Сообщений: 9
Пользователь №: 37550
На форуме:
Карма:
При заполнении Google формы с помощью CURL не передаются русские символы. Например при выполнении кода ниже в поле category будут записаны только «_test» вместо «тест_test». Пробовал перекодировать через iconv, не помогло. Есть идеи?
php
$name = "name1";
$category = "тест_test";
$category=iconv("cp1251","utf-8",$category);
$image = "image1";
$description = "description1";
// Создаем подключение
if( $curl = curl_init() )
// Задаем ссылку
curl_setopt($curl,CURLOPT_URL,'https://docs.google.com/forms/d/15U0zCAAblPxTZLa8vMoHSXRwJLUjpmd3AwmhvRSDy_s/formResponse');
// Нужно помнить кукисы!
curl_setopt($curl, CURLOPT_COOKIESESSION, TRUE);
curl_setopt($curl, CURLOPT_COOKIEFILE, "cookiefile");
// Скачанные данные не выводить поток
curl_setopt($curl,CURLOPT_RETURNTRANSFER,true);
// Активируем GZIP сжатие трафика
curl_setopt($curl,CURLOPT_ENCODING,'gzip,deflate');
// напишем в юзер-агент неправду
curl_setopt($curl,CURLOPT_USERAGENT,'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)');
// Нужно вывести http заголовки в массив
curl_setopt($curl,CURLOPT_HEADER,true);
// Если все ок, в $html вернется html код главной страницы
if( $html = curl_exec($curl) )
// Указываем куда отправлять запрос
curl_setopt($curl,CURLOPT_URL,'https://docs.google.com/forms/d/15U0zCAAblPxTZLa8vMoHSXRwJLUjpmd3AwmhvRSDy_s/formResponse');
// Указываем подключению, что слать нужно не GET (по умолчанию), а POST запросы
curl_setopt($curl,CURLOPT_POST,TRUE);
// Указываем, что именно отправлять в POST данных, на этой стадии происходит ввод логина/пароля
curl_setopt($curl,CURLOPT_POSTFIELDS,"entry.1243554843=$name&entry.1359298278=$category&entry.228695742=$image&entry.1784795327=$description&submit=ok");
// Скачиваем
$out = curl_exec($curl);
// Показываем скачанные данные
echo $out;
>
// Закрываем соединение
curl_close($curl);
>
?>