Форум программистов, компьютерный форум, киберфорум
Haskell
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.57/21: Рейтинг темы: голосов - 21, средняя оценка - 4.57
 Аватар для NoobsEnslaver
136 / 48 / 2
Регистрация: 31.07.2014
Сообщений: 238

Декодирование русских символов

18.12.2015, 23:10. Показов 4337. Ответов 12
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Привет народ. Парсю тут сайт, в учебных целях, и столкнулся с тем, что если вытягивать оттуда русский текст он представляется в виде кодов отдельных символов (пример: 147 \235.\241.,где 147 и точки реально присутствуют в тексте, а \235 это л, \241 с. Вытягиваю страничку с помощью Network.HTTP.simpleHTTP, парсю с помощью Text.HTML.TagSoup . Пробовал использовать Data.Encoding.decodeString , но только коды поменялись (пробовал все разумные кодировки (cp1251, utf8, utf16, ASCII, KOI8R). В хэдере документа написано, что кодировка windows-1251, эту пробовал в первую очередь, получаю такие коды: 147 \204.\211..
Думал сначала, может у меня консоль барахлит, кодироки не поддерживает - записал результат в файл - то-же. Хотел еще на винде попробовать, но там чёто пакет encoding отказался ставиться, зависимости не разрешаются вроде, забил на это (а без перекодирования тоже коды).
Есть идеи?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
18.12.2015, 23:10
Ответы с готовыми решениями:

Декодирование символов
Добрый день! Имеется следующая последовательность: cf f0 e8 e2 e5 f2 (Привет cp1251). Исходно получена из: \'cf\'f0\'e8\'e2\'e5\'f2...

Как настроить ввод русских символов и в дальнейшем вывод этих символов
Подскажите как в этом коде настроить ввод русских символов и в дальнейшем вывод этих символов. Данный код выводит лишь всякую ерунду место...

Чтение русских символов. Отрицательные значения у символов
Добрый вечер. Считую файл .txt. Но русские буквы получают отрицательное значение. И в итоге при попытке перевести в String не распознаются....

12
97 / 78 / 12
Регистрация: 07.06.2015
Сообщений: 132
Записей в блоге: 12
18.12.2015, 23:22
есть две идеи:
1) работать с сайтом с помощью селениума - у хаскелла есть подходящие библиотеки. На форуме где-то есть тема, где есть код работы с selenium+haskell
2) попытаться каким-нибудь php дернуть нужную страницу - там 4 строки кода. Легко гуглится. Если там такая же проблема, то "виноват сайт, а не хаскелл"
0
 Аватар для NoobsEnslaver
136 / 48 / 2
Регистрация: 31.07.2014
Сообщений: 238
19.12.2015, 13:07  [ТС]
Попробовал wget +less - те же коды.
Конечно, есть шанс, что силениум будет не просто возвращать файл страницы, а фоново заниматься кодировками, но маловероятно. Есть еще какие нибудь варианты? Силениум это просто с пушки по воробьям.
0
97 / 78 / 12
Регистрация: 07.06.2015
Сообщений: 132
Записей в блоге: 12
19.12.2015, 13:12
если не секрет, что за сайт?
0
 Аватар для NoobsEnslaver
136 / 48 / 2
Регистрация: 31.07.2014
Сообщений: 238
19.12.2015, 13:14  [ТС]
Вот конкретно вот эту ссылку парсю
0
97 / 78 / 12
Регистрация: 07.06.2015
Сообщений: 132
Записей в блоге: 12
19.12.2015, 14:04
оу Новосибирск. Земляк)
я смогу только завтра заняться этим вопросом к сожалению
0
Модератор
 Аватар для Curry
5158 / 3488 / 536
Регистрация: 01.06.2013
Сообщений: 7,567
Записей в блоге: 9
19.12.2015, 16:39
В Haskell (и, в других языках, создатели которых билгейсохейтеры) с национальными кодировками наблюдаются некоторые траблы. Да, мы должны это признать. Увы. Ещё и ситуация от версии к версии компилятора меняется.
Пакетом encoding вообще лучше не пользоваться, он даже не включён в stackage-сборки. Для перекодирования рекомендуется использовать text-icu которая юзает сишную библиотеку ICU, которую вначале надо поставить самому. Не юзал. Для конвертации из под винды я просто использовал Win API. Пардон за лишние импорты - это выдранный кусок, непричёсанный
Кликните здесь для просмотра всего текста
Haskell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import System.Win32.Types
import System.Win32.NLS
import Graphics.Win32.Misc
import Foreign.Ptr
import Foreign.C.Types
import Foreign.Marshal.Alloc
import Foreign.C.String
import Control.Applicative
 
import qualified Data.Text as T
import qualified Data.Text.IO as T
import qualified Data.ByteString.Char8 as B8
import qualified Data.ByteString as B
 
type  WideCharToMultiByteType = CodePage -> DWORD -> LPCWSTR -> CInt -> LPSTR -> CInt -> LPCSTR -> LPBOOL -> IO CInt
 
foreign import stdcall unsafe "Windows.h &WideCharToMultiByte"   
    pWideCharToMultiByte :: FunPtr WideCharToMultiByteType
 
foreign import stdcall unsafe "dynamic"  
  mkWideCharToMultiByte :: FunPtr WideCharToMultiByteType -> WideCharToMultiByteType
 
wideCharToMultiByte:: WideCharToMultiByteType
wideCharToMultiByte = mkWideCharToMultiByte  pWideCharToMultiByte
 
--------- Преобразование из буфера содержащего win1251 в OEM(866), т.е. то что можно вывести на консоль --------------
to866:: B.ByteString -> IO String
to866 s 
  | B.null s = return ""
  | otherwise = B.useAsCStringLen s $ \ ( str,sz) -> do
                   outsz <- multiByteToWideChar 1251 0 (castPtr str) (fromIntegral sz) nullPtr 0 
                   allocaBytes ( 2 * fromIntegral outsz ) $ \ buf -> 
                       multiByteToWideChar 1251 0 (castPtr str) (fromIntegral sz) buf outsz      
                       >> peekCWStringLen (castPtr buf, fromIntegral outsz)
 
 
toUTF8:: B.ByteString -> IO B.ByteString 
toUTF8 s 
  | B.null s = return ""
  | otherwise  = B.useAsCStringLen s $ \ ( str,sz) -> do
    outsz <- multiByteToWideChar 1251 0 (castPtr str) (fromIntegral sz) nullPtr 0 
    allocaBytes ( 2 * fromIntegral outsz ) $ \ buf -> do
        _ <- multiByteToWideChar 1251 0 (castPtr str) (fromIntegral sz) buf outsz      
        utfsz <- wideCharToMultiByte 65001 0 (castPtr buf) (fromIntegral outsz) 
                                                           nullPtr 0 nullPtr nullPtr
        allocaBytes (fromIntegral utfsz) $ \ utfbuf -> do
            _ <- wideCharToMultiByte 65001 0 (castPtr buf)    (fromIntegral outsz) 
                             (castPtr utfbuf) (fromIntegral utfsz) nullPtr nullPtr    
            B.packCStringLen (castPtr utfbuf,  fromIntegral utfsz)

С неанглискими буквами нужно помнить, что:
- сам исходник должен быть в кодировке utf-8 без BOM.
- Текст (особенно большой) лучше не обрабатывать в String, но в Text, в крайнем случае ByteString.
- Что бы текстовые строковые литералы в исходнике "сами" конвертировались в Text или ByteString, нужно вначале вставить прагму
Haskell
1
2
{-# LANGUAGE OverloadedStrings #-}
module Main where
- при чтении и записи в/на консоль и в файлы в текстовом режиме уже производится перекодировка. В куда? Можете узнать из функций getThreadLocale, getFileSystemEncoding. При чём, откровенно, так и пишут, что под виндой это работает криво "On Windows, this encoding *should not* be used if possible because the use of code pages is deprecated: Strings should be retrieved via the "wide" W-family of UTF-16 APIs instead".
Но, всё же, если Вы создадите
Haskell
1
2
3
4
5
6
7
{-# LANGUAGE OverloadedStrings #-}
module Main where
 
import qualified Data.Text as T
 
main:: IO ()
main = T.putStrLn "Пример нормального отображение русских букв в консоли"
То, в Вашем, любимом, emacse (насколько я помню) уведите нормальный вывод.

А вот пример, в котором я прочитал страничку в кодировке 1251 в файл с помощью simpleHTTP, и оно сохранилось в 1251
Haskell
1
2
3
4
5
6
7
8
9
10
import System.IO
import Network.HTTP
 
main :: IO ()
main = do
    r <- simpleHTTP (getRequest "http://winrus.com/")
    case r of
        (Left err) -> print err
        (Right resp) -> let body = rspBody resp
                        in withBinaryFile "d:\\samples\\Haskell\\tstout.txt" WriteMode $ \h -> hPutStr h body
По хорошему то надо потоками ByteString-ов читать.

p.s. Уточняю: я не гуру в интернационализации Haskell. Если кто хочет мне показать как я неправ, то я только за. В основном интересно под винду.
1
 Аватар для Dastin
23 / 23 / 3
Регистрация: 21.06.2014
Сообщений: 36
19.12.2015, 19:42
Вот рабочий вариант.

Haskell
1
2
3
4
5
6
import Network.HTTP.Conduit 
import Data.Text.Lazy
import Data.Text.Lazy.Encoding
 
q <- simpleHttp str
Data.Text.Lazy.unpack (Data.Text.Lazy.Encoding.decodeUtf8 q)
1
Модератор
 Аватар для Curry
5158 / 3488 / 536
Регистрация: 01.06.2013
Сообщений: 7,567
Записей в блоге: 9
19.12.2015, 20:54
Причесал. Код ниже читает (из под винды) страницу в кодировке 1251, преобразует в utf-8 и записывает в файл.
На этот раз, с пайпами.
Кликните здесь для просмотра всего текста
Haskell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
{-# LANGUAGE OverloadedStrings #-}
module Main where
 
import System.IO
import Pipes
import Pipes.HTTP
import qualified Pipes.Prelude as PP
import qualified Pipes.ByteString as PB  -- from `pipes-bytestring`
 
import Foreign.C.Types (CInt(..))
import Foreign (FunPtr,nullPtr,allocaBytes,castPtr)
import qualified Data.ByteString as B
--- Начало непортабельности ---
import System.Win32 (DWORD,LPCWSTR,LPSTR,LPCSTR,LPBOOL,CodePage,multiByteToWideChar)
 
type  WideCharToMultiByteType = CodePage -> DWORD -> LPCWSTR -> CInt -> LPSTR -> CInt -> LPCSTR -> LPBOOL -> IO CInt
 
foreign import stdcall unsafe "Windows.h &WideCharToMultiByte"
    pWideCharToMultiByte :: FunPtr WideCharToMultiByteType
 
foreign import stdcall unsafe "dynamic"
  mkWideCharToMultiByte :: FunPtr WideCharToMultiByteType -> WideCharToMultiByteType
 
wideCharToMultiByte:: WideCharToMultiByteType
wideCharToMultiByte = mkWideCharToMultiByte  pWideCharToMultiByte
 
toUTF8:: B.ByteString -> IO B.ByteString
toUTF8 s
  | B.null s = return ""
  | otherwise  = B.useAsCStringLen s $ \ ( str,sz) -> do
    outsz <- multiByteToWideChar 1251 0 (castPtr str) (fromIntegral sz) nullPtr 0
    allocaBytes ( 2 * fromIntegral outsz ) $ \ buf -> do
        _ <- multiByteToWideChar 1251 0 (castPtr str) (fromIntegral sz) buf outsz
        utfsz <- wideCharToMultiByte 65001 0 (castPtr buf) (fromIntegral outsz)
                                                           nullPtr 0 nullPtr nullPtr
        allocaBytes (fromIntegral utfsz) $ \ utfbuf -> do
            _ <- wideCharToMultiByte 65001 0 (castPtr buf)    (fromIntegral outsz)
                             (castPtr utfbuf) (fromIntegral utfsz) nullPtr nullPtr
            B.packCStringLen (castPtr utfbuf,  fromIntegral utfsz)
--- Окончание непортабельности ---
 
main = do
    req <- parseUrl "http://winrus.com/"
    withManager tlsManagerSettings $ \m ->
        withHTTP req m $ \resp ->
            withBinaryFile "d:\\samples\\Haskell\\tstout.txt" WriteMode $ \h ->
                runEffect $ responseBody resp >-> PP.mapM toUTF8 >-> PB.toHandle h
Требуются пакеты bytestring,pipes,http-client,http-client-tls,pipes-http,pipes-bytestring,Win32

p.s. Что интересно: Win API-шная функция multiByteToWideChar давно в пакете Win32 описана, а симметричная ей wideCharToMultiByte нет. Приходится ручками.

Не по теме:

Определённо, заговор!

1
 Аватар для NoobsEnslaver
136 / 48 / 2
Регистрация: 31.07.2014
Сообщений: 238
22.12.2015, 11:30  [ТС]
Цитата Сообщение от Dastin Посмотреть сообщение
Вот рабочий вариант.
Вроде не особо рабочий, не дожал я несоответствие типов, да и сама затея сомнительна, читаем описани функции в хаскедже: "Decode a ByteString containing UTF-8 encoded text" т.е. дешифрует байтстринг, содержищий UTF-8, а у меня он содержит cp1251, а такой функции в этом пакете нет.

Цитата Сообщение от KolodeznyDiver Посмотреть сообщение
Причесал. Код ниже читает (из под винды) страницу в кодировке 1251, преобразует в utf-8 и записывает в файл.
Большое спасибо конечно за проделанную работу, если мне так уж сильно прижмёт поработать с cp1251 неприменно буду иметь ввиду этот вариант, но пока, пожалуй, обойду эту проблему, пока не встречу более элегантного решения (когда увидел nullPtr мне аж поплошало ) или не встанет крайняя нужда в этом (lazy evaluation) Если что нарою - отпишусь здесь.
0
Модератор
 Аватар для Curry
5158 / 3488 / 536
Регистрация: 01.06.2013
Сообщений: 7,567
Записей в блоге: 9
22.12.2015, 13:22
Цитата Сообщение от NoobsEnslaver Посмотреть сообщение
увидел nullPtr мне аж поплошало
Ну, прошу пардону. Я и не говорил что это лучшее решение. Наверное, лучшее, на сегодняшний день - поставить сишную библиотеку ICU и пакет text-icu. Ссылки в 7-ом сообщении.
1
 Аватар для NoobsEnslaver
136 / 48 / 2
Регистрация: 31.07.2014
Сообщений: 238
23.12.2015, 01:47  [ТС]
Да, кажется icu это сможет, в Data.Text.ICU.Convert есть ф-я toUnicode, которой передаешь кодировку и строку и на выходе строка в другой кодировке, но списка поддерживаемых кодировок я не в хаскедже не на их сайте не нашел, просто строкой пишешь, что тебе нужно. Но в своем проекте я тоже её не буду использовать т.к. парсер названия кодировки в кодировку... не чистый! IO Convert, зачем бы это небыло. И мне придется перекраивать всю программу, чтобы протащить этот побочный эффект, так что уже в другой раз.

Добавлено через 2 часа 36 минут
Короче посидел я, подумал, вспомнил, что всё гениальное просто и написал вот это:
Haskell
1
2
3
4
5
fromCP1251::String->String
fromCP1251 = map (\chr -> case lookup chr rusTable of
                   Just x -> x
                   _ -> chr)
  where rusTable = zip ['\192'..'\255'] ['А'..'я']
и оно круто работает без присяданий со штангой

Добавлено через 44 минуты
P.S. на пробном примере ф-я показала себя хорошо, а в бою плохо - потому что в реальном тексте есть запятые и тд и если их не перекодировать то смешанная кодировка в строке получается. По кодам узнал Data.Encoding - я уже получал такой результат, значит он правильно работает, только такая особенность, что если выводишь только русские символы - всё норм, если мешаешь с английскими (хоть и ко всей строке перекодирование применено) то русские становятся кодами.
1
Модератор
 Аватар для Curry
5158 / 3488 / 536
Регистрация: 01.06.2013
Сообщений: 7,567
Записей в блоге: 9
23.12.2015, 11:25
NoobsEnslaver, Вам никто не мешает сделать перекодировку всей второй половины таблицы 1251 в unicode, но делать это на списках - тормоза, лучше сделать таблицу в Data.Vector.Unboxed (пакет vector).
Цитата Сообщение от NoobsEnslaver Посмотреть сообщение
только такая особенность, что если выводишь только русские символы - всё норм, если мешаешь с английскими (хоть и ко всей строке перекодирование применено) то русские становятся кодами.
Появилось подозрение что у Вас GHC ранее версии 7.10. И/или Ваш emacs недостаточно совершенен.
Haskell
1
2
3
4
5
6
7
8
9
10
11
12
{-# LANGUAGE OverloadedStrings #-}
module Main where
 
import qualified Data.Text.IO as T
import Data.Char
 
main:: IO ()
main = do
    T.putStrLn "Пример нормального отображение русских букв в консоли, as well as English letters."
    let s = "Пример нормального отображение русских букв в консоли, as well as English letters."
    putStrLn s
    print $ map ord s
У меня, при выводе в НАСТОЯЩУЮ консоль (а не в окно вывода IDE), в обоих случаях отображаются нормально все символы. В более старых версиях GHC отображалось нормально только через T.putStrLn.
Отображение кодов символов показывает что это юникод. Вообще, работа с большими объёмами текста предпочтительней в Text, особенно если выполняется ещё чтото, кроме "отсчипывания" начала строки и добавления символа к началу строки. Всё остальное на односвязанном списке тормоза.

Добавлено через 1 час 34 минуты
Цитата Сообщение от NoobsEnslaver Посмотреть сообщение
Но в своем проекте я тоже её не буду использовать т.к. парсер названия кодировки в кодировку... не чистый! IO Convert, зачем бы это небыло. И мне придется перекраивать всю программу, чтобы протащить этот побочный эффект, так что уже в другой раз.
Не нужно IO протаскивать куда не требуется. Создали один раз convert и пользуйтесь в чистом коде.
Однако, про data Converter сказано : Note: this structure is not thread safe.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
23.12.2015, 11:25
Помогаю со студенческими работами здесь

Декодирование HTML символов на яваскрипт
Как раскодировать символы html на яваскрипте? Скажем есть строка в виде freelancers.... Делаю так: results =...

Декодирование символов, полученных с сайта
Здравствуйте! Хочу попросить подсказки. Начинаю брать данные с сайта, получаю строки вида: Начал думать, как можно декодировать,...

Перевести строку, состоящую из русских символов в строку из латинских символов, используя translit
Надо написать программу, которая переводит строку, состоящую из русских символов в строку из латинских символов, используя таблицу...

Перехват русских символов
Здравствуйте, мне, к сожалению понадобилась помощь. Я пишу программу, которая перехватывает вводимые с клавиатуры данные и у меня...

Ввод русских символов
Здравствуйте. В Java, всё отлично с выводом русских символов. Но когда я ввожу русские символы через Scanner и nextLine, потом вывожу...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Новые блоги и статьи
Автозаполнение реквизита при выборе элемента справочника
Maks 27.03.2026
Программный код из решения ниже на примере нетипового документа "ЗаявкаНаРемонтСпецтехники" разработанного в конфигурации КА2. При выборе "Спецтехники" (Тип Справочник. Спецтехника), заполняется. . .
Сумматор с применением элементов трёх состояний.
Hrethgir 26.03.2026
Тут. https:/ / fips. ru/ EGD/ ab3c85c8-836d-4866-871b-c2f0c5d77fbc Первый документ красиво выглядит, но без схемы. Это конечно не даёт никаких плюсов автору, но тем не менее. . . всё может быть. . .
Автозаполнение реквизитов при создании документа
Maks 26.03.2026
Программный код из решения ниже размещается в модуле объекта документа, в процедуре "ПриСозданииНаСервере". Алгоритм проверки заполнения реализован для исключения перезаписи значения реквизита,. . .
Команды формы и диалоговое окно
Maks 26.03.2026
1. Команда формы "ЗаполнитьЗапчасти". Программный код из решения ниже на примере нетипового документа "ЗаявкаНаРемонтСпецтехники" разработанного в конфигурации КА2. В качестве источника данных. . .
Кому нужен AOT?
DevAlt 26.03.2026
Решил сделать простой ланчер Написал заготовку: dotnet new console --aot -o UrlHandler var items = args. Split(":"); var tag = items; var id = items; var executable = args;. . .
Отправка уведомления на почту при создании или изменении элементов справочника
Maks 24.03.2026
Программная отправка письма электронной почты на примере типового справочника "Склады" в конфигурации БП3. Перед реализацией необходимо выполнить настройку системной учетной записи электронной. . .
модель ЗдравоСохранения 5. Меньше увольнений- больше дохода!
anaschu 24.03.2026
Теперь система здравосохранения уменьшает количество увольнений. 9TO2GP2bpX4 a42b81fb172ffc12ca589c7898261ccb/ https:/ / rutube. ru/ video/ a42b81fb172ffc12ca589c7898261ccb/ Слева синяя линия -. . .
Midnight Chicago Blues
kumehtar 24.03.2026
Такой Midnight Chicago Blues, знаешь?. . Когда вечерние улицы становятся ночными, а ты не можешь уснуть. Ты идёшь в любимый старый бар, и бармен наливает тебе виски. Ты смотришь на пролетающие. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru