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

barkasian

Client
Регистрация
03.12.2014
Сообщения
127
Благодарностей
137
Баллы
43
Приветствую!
Вот ссылочка http://www.prirodlekar.ru/archives/569
Если данные с этого сайта брать через GET-запрос, то вообще только крякозябры. Кодировка GET-запроса и соответствует и кодировке сайта и заголовку. Как тут быть?

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

Вложения

Последнее редактирование:

LexxWork

Client
Регистрация
31.10.2013
Сообщения
1 190
Благодарностей
786
Баллы
113
это очередной баг зенопостера
вообще правильно при запросе по умолчанию всегда указывать хоть какой нибудь тип зжатия
http://en.wikipedia.org/wiki/HTTP_compression
но зенопостер этого не делает
а точнее - уже не может (в предыдущей версии мог, в более старых скорей всего не мог никогда) распаковывать сжатые респонсы.
Accept-Encoding: gzip, deflate по-просту нет (да и не только этого не хватает), а если указать то прийдут крякозябры
Единственный выход для того сайта указать так как на скриншоте
 
  • Спасибо
Реакции: Roman*, LmPopo и barkasian

rostonix

Известная личность
Регистрация
23.12.2011
Сообщения
29 067
Благодарностей
5 707
Баллы
113
Поставил таску.
 

darkdiver

Administrator
Команда форума
Регистрация
13.01.2009
Сообщения
2 284
Благодарностей
2 728
Баллы
113
Приветствую!
Вот ссылочка http://www.prirodlekar.ru/archives/569
Если данные с этого сайта брать через GET-запрос, то вообще только крякозябры. Кодировка GET-запроса и соответствует и кодировке сайта и заголовку. Как тут быть?
Проект приложил
на последней версии у нас не воспроизводится, уточните на какой версии у вас возникает данная проблема?
 

LmPopo

Client
Регистрация
06.12.2012
Сообщения
299
Благодарностей
136
Баллы
43
на последней версии у нас не воспроизводится, уточните на какой версии у вас возникает данная проблема?
Хм, сейчас проверил, уже без вышеописанных проблем.
Но на момент создания поста действительно в ответ приходили крякозябры.
 

rostonix

Известная личность
Регистрация
23.12.2011
Сообщения
29 067
Благодарностей
5 707
Баллы
113
Хм, сейчас проверил, уже без вышеописанных проблем.
Но на момент создания поста действительно в ответ приходили крякозябры.
у меня тоже)
будем смотреть
 

barkasian

Client
Регистрация
03.12.2014
Сообщения
127
Благодарностей
137
Баллы
43
на последней версии у нас не воспроизводится, уточните на какой версии у вас возникает данная проблема?
5.7.1.0, сейчас тоже проверил и уже без вышеописанных проблем.
 

rostonix

Известная личность
Регистрация
23.12.2011
Сообщения
29 067
Благодарностей
5 707
Баллы
113
сделали правки для будущего билда
 

LexxWork

Client
Регистрация
31.10.2013
Сообщения
1 190
Благодарностей
786
Баллы
113
и доведити до ума кодировку. Отправлять данные в windows-1251 просто дикость.
а если учесть что все джейсоны должны уходить только в utf, то вобще - преступление.
сделайте уже хоть раз и навсегда! И НЕ ЛАЗЬТЕ ТУДА БОЛЬШЕ!!!!
 

darkdiver

Administrator
Команда форума
Регистрация
13.01.2009
Сообщения
2 284
Благодарностей
2 728
Баллы
113
мы бы рады решить проблему с кодировкой, но curl упорно отправляет в ASCII, скорее всего придется от него отказаться, и сделать без curl.
 

LexxWork

Client
Регистрация
31.10.2013
Сообщения
1 190
Благодарностей
786
Баллы
113
проверил этот момент.
использовать внутренности зеновского 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();
}
 

Вложения

darkdiver

Administrator
Команда форума
Регистрация
13.01.2009
Сообщения
2 284
Благодарностей
2 728
Баллы
113
ок, спасибо, проверим.
 

rostonix

Известная личность
Регистрация
23.12.2011
Сообщения
29 067
Благодарностей
5 707
Баллы
113
поправили для след. билда
 

LexxWork

Client
Регистрация
31.10.2013
Сообщения
1 190
Благодарностей
786
Баллы
113
напишите пожалуйста от том что конкретно исправили, у меня есть подозрение что - не все.
 

LexxWork

Client
Регистрация
31.10.2013
Сообщения
1 190
Благодарностей
786
Баллы
113

darkdiver

Administrator
Команда форума
Регистрация
13.01.2009
Сообщения
2 284
Благодарностей
2 728
Баллы
113
Post запрос отправляется в указанной кодировке
Добавлены заголовки Accept-Encoding и Accept-Language если они не указаны пользователем
Gzip детектиться автоматом и распаковывается
Файл качает в сразу, без использования оперативки.
Что ещё?
 

LexxWork

Client
Регистрация
31.10.2013
Сообщения
1 190
Благодарностей
786
Баллы
113
просто Accept
в текущей версии если его указывать то передаются два поля: Accept мой и зеновский Accept: *\* (как-то так)
и самое глованое что там с исходящей кодировкой?
 

darkdiver

Administrator
Команда форума
Регистрация
13.01.2009
Сообщения
2 284
Благодарностей
2 728
Баллы
113

LexxWork

Client
Регистрация
31.10.2013
Сообщения
1 190
Благодарностей
786
Баллы
113
о, круто!
аксепт только в кубике дублируется. в снепиете все норм
 

orka13

Client
Регистрация
07.05.2015
Сообщения
2 165
Благодарностей
2 165
Баллы
113
Решил проблему, отмучился, расписываю решение:

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 года появились какие-то более оптимальные костыли? Если нет, то отпишитесь кто в теме, а то не знаю стоит ли это использовать в работе. Ну и там надо регулярки более универсальные сделать для отлавливания кодировки в мета тегах, протестирую и скину вариант с правками.
 

orka13

Client
Регистрация
07.05.2015
Сообщения
2 165
Благодарностей
2 165
Баллы
113
Вот весь процесс конвертирования с проверками условий в одном кубике на 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;
    }
   
}
 
Последнее редактирование:

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