Кракозябры при парсинге черег GET запрос

  • Автор темы Автор темы kasper
  • Дата начала Дата начала
Приветствую!
Вот ссылочка http://www.prirodlekar.ru/archives/569
Если данные с этого сайта брать через GET-запрос, то вообще только крякозябры. Кодировка GET-запроса и соответствует и кодировке сайта и заголовку. Как тут быть?

Проект приложил
 

Вложения

Последнее редактирование:
это очередной баг зенопостера
вообще правильно при запросе по умолчанию всегда указывать хоть какой нибудь тип зжатия
http://en.wikipedia.org/wiki/HTTP_compression
но зенопостер этого не делает
а точнее - уже не может (в предыдущей версии мог, в более старых скорей всего не мог никогда) распаковывать сжатые респонсы.
Accept-Encoding: gzip, deflate по-просту нет (да и не только этого не хватает), а если указать то прийдут крякозябры
Единственный выход для того сайта указать так как на скриншоте
47rbVq4.png
 
  • Оценить
Реакции: Roman*, LmPopo и barkasian
Поставил таску.
 
Приветствую!
Вот ссылочка http://www.prirodlekar.ru/archives/569
Если данные с этого сайта брать через GET-запрос, то вообще только крякозябры. Кодировка GET-запроса и соответствует и кодировке сайта и заголовку. Как тут быть?
Проект приложил
на последней версии у нас не воспроизводится, уточните на какой версии у вас возникает данная проблема?
 
на последней версии у нас не воспроизводится, уточните на какой версии у вас возникает данная проблема?
Хм, сейчас проверил, уже без вышеописанных проблем.
Но на момент создания поста действительно в ответ приходили крякозябры.
 
Хм, сейчас проверил, уже без вышеописанных проблем.
Но на момент создания поста действительно в ответ приходили крякозябры.
у меня тоже)
будем смотреть
 
на последней версии у нас не воспроизводится, уточните на какой версии у вас возникает данная проблема?
5.7.1.0, сейчас тоже проверил и уже без вышеописанных проблем.
 
сделали правки для будущего билда
 
и доведити до ума кодировку. Отправлять данные в windows-1251 просто дикость.
а если учесть что все джейсоны должны уходить только в utf, то вобще - преступление.
сделайте уже хоть раз и навсегда! И НЕ ЛАЗЬТЕ ТУДА БОЛЬШЕ!!!!
 
мы бы рады решить проблему с кодировкой, но curl упорно отправляет в ASCII, скорее всего придется от него отказаться, и сделать без curl.
 
проверил этот момент.
использовать внутренности зеновского post метода не удалось, потому как все методы хранятся на сервере (очередной изврат)
так же не удалось использовать старый libcurl.NET (http://sourceforge.net/projects/libcurl-net/)
думал что все есть в зп, но нет, не все и даже со всем остальным зп не подгружает все либы.
оставил это дело и скомпилил себе https://github.com/masroore/CurlSharp
послал запрос c русскими буквами, сохранил сессию в фидлере, проверил кодировку - utf-8!!!!
она вобще по умолчанию стоит!!!

Код:
Развернуть Свернуть Копировать
Curl.GlobalInit(CurlInitFlag.All);
using (var easy = new CurlEasy())
{
easy.Proxy = "http://localhost:8888";
easy.Url = "http://hostname/testpost.php";
easy.Post = true;
var postData = "parm1=12345&parm2=фаф ыва ыа фываыфва";
easy.PostFields = postData;
easy.PostFieldSize = postData.Length;
easy.Perform();
}
 

Вложения

  • Оценить
Реакции: ZX, Gidz и darkdiver
ок, спасибо, проверим.
 
поправили для след. билда
 
напишите пожалуйста от том что конкретно исправили, у меня есть подозрение что - не все.
 
Post запрос отправляется в указанной кодировке
Добавлены заголовки Accept-Encoding и Accept-Language если они не указаны пользователем
Gzip детектиться автоматом и распаковывается
Файл качает в сразу, без использования оперативки.
Что ещё?
 
просто Accept
в текущей версии если его указывать то передаются два поля: Accept мой и зеновский Accept: *\* (как-то так)
и самое глованое что там с исходящей кодировкой?
 
о, круто!
аксепт только в кубике дублируется. в снепиете все норм
 
Решил проблему, отмучился, расписываю решение:

1) Делаем GET запрос к странице с выставленной кодировкой Windows-1251, получаем заголовки и содержимое.
2) Парсим регулярками кодировки из заголовков и из мета:
Код:
Развернуть Свернуть Копировать
(?i)(?<=\r\nContent-Type.*charset=)[\d\w-]*
(?i)(?<=meta.*charset=)[\d\w-]*
3) Приводим полученные кодировки к нижнему регистру.
4) Сравниваем сначала (приоритет заголовкам) кодировку из заголовка (если есть) с windows-1251 (и с её синонимом cp1251), если отличается - выполняем C# код представленный ниже -> PROFIT!
5) Если же кодировки из заголовка нет, то сравниваем кодировку из meta с windows-1251 (и с её синонимом cp1251), если отличается - выполняем C# код представленный ниже -> PROFIT!

Код:
Развернуть Свернуть Копировать
string content = project.Variables["content"].Value;
string charset = project.Variables["charset"].Value;
Encoding charset_en = Encoding.GetEncoding(charset);
Encoding win1251 = Encoding.GetEncoding("Windows-1251");
byte[] charsetBytes = win1251.GetBytes(content);
byte[] win1251Bytes = Encoding.Convert(charset_en, win1251, charsetBytes);
return win1251.GetString(win1251Bytes);

content - полученное содержимое
charset - кодировка в которой содержимое

PS: Если ни в заголовке, ни в meta кодировка не прописана - то остаётся только надеяться, что данные на странице были в Windows-1251. Тут уж поможет только определение кодировки другими алгоритмами, например Mozilla Universal Charset Detector (думаю было бы круто прикрутить к зеннке, в качестве автоопределятора/перегона кодировки).

PS2: интересно то, что если запрос изначально делать в UTF-8 то потом перевести полученные данные в другую кодировку не получается (кракозябры остаются).
Метод авто-определения (или точнее "авто-исправления") кодировки из поста работает, автору спасибо. Но может за 3 года появились какие-то более оптимальные костыли? Если нет, то отпишитесь кто в теме, а то не знаю стоит ли это использовать в работе. Ну и там надо регулярки более универсальные сделать для отлавливания кодировки в мета тегах, протестирую и скину вариант с правками.
 
Вот весь процесс конвертирования с проверками условий в одном кубике на C#. Добавляете его в шаблон после GET-запроса. От себя добавил удаление лишних заголовки от редиректов, а то в них может быть указана кодировка, которая нам вовсе не нужна, и она часто отличается от кодировки последнего ответа сервера.
Еще надо создать в проекте переменную «charset_info», туда будет записываться метод конвертирования (какую кодировку обрабатывали).
C#:
Развернуть Свернуть Копировать
string content = project.Variables["content"].Value; // получаем из переменной "content" код ответа сервера на наш запрос в windows-1251 кодировке (заголовки и содержимое). 
content = System.Text.RegularExpressions.Regex.Replace(content, @"^[\w\W]{100,4000}(?=\sHTTP/1)", ""); // удаляем лишние заголовки от редиректов, если такие есть
var charset = "";

Regex reg = new Regex(@"(?<=\r\nContent-Type.*charset=)[\d\w-]*", RegexOptions.IgnoreCase); // Парсим регулярками кодировки из заголовков 
Match match1 = reg.Match(content);
charset = match1.Value;
if (charset != "") // Если кодировка из заголовка есть, то идем дальше
{
    charset = charset.ToLower(); // Приводим полученные кодировки к нижнему регистру.
    if (charset == "windows-1251" || charset == "cp1251") // Сравниваем сначала (приоритет заголовкам) кодировку из заголовка. Если есть с windows-1251 (или с её синонимом cp1251), то не конвертируем, и отдаем тот контент что был
    {
        project.Variables["charset_info"].Value = "кодировка windows-1251 в заголовке, не конвертировали";
        return content;
    }
    else {
        Encoding charset_en = Encoding.GetEncoding(charset);
        Encoding win1251 = Encoding.GetEncoding("Windows-1251");
        byte[] charsetBytes = win1251.GetBytes(content);
        byte[] win1251Bytes = Encoding.Convert(charset_en, win1251, charsetBytes);
        project.Variables["charset_info"].Value = "кодировка " + charset + " в заголовке, конвертировали";
        return win1251.GetString(win1251Bytes);
    }
}
else // Если кодировки из заголовка нет, то идем дальше к проверке мета
{
    Regex reg2 = new Regex(@"(?<=meta.*charset\s*=[""'\s]*)[\d\w-]+(?=[""'\s]*)", RegexOptions.IgnoreCase); // Парсим регулярками кодировки из мета
    Match match2 = reg2.Match(content);
    charset = match2.Value;
    if (charset != "")
    {
       
        charset = charset.ToLower(); // Приводим полученные кодировки к нижнему регистру.
        if (charset == "windows-1251" || charset == "cp1251") // Сравниваем  кодировку из мета. Если есть с windows-1251 (или с её синонимом cp1251), то не конвертируем, и отдаем тот контент что был
        {
            project.Variables["charset_info"].Value = "кодировка windows-1251 в мета, не конвертировали";
            return content;
        }
        else
        {
            Encoding charset_en = Encoding.GetEncoding(charset);
            Encoding win1251 = Encoding.GetEncoding("Windows-1251");
            byte[] charsetBytes = win1251.GetBytes(content);
            byte[] win1251Bytes = Encoding.Convert(charset_en, win1251, charsetBytes);
            project.Variables["charset_info"].Value = "кодировка " + charset + " в мета, конвертировали";
            return win1251.GetString(win1251Bytes);
        }
       
       
    }
    else
    {
        project.Variables["charset_info"].Value = "кодировка не определилась, не конвертировали";
        return content;
    }
   
}
 
Последнее редактирование:

Кто просматривает тему: (Всего: 0, Пользователи: 0, Гости: 0)