#кодировка #парсер #golang #unicode
Доброго времени суток. Столкнулся с такой проблемой: некоторые сайты парсятся адекватно - текст из формочек достается в читабельной кодировке, а некоторые - нет. Сначала грешил на UTF-8 на сайте, но ведь Go искаропки только с UTF-8 и работает по-дефолту Получаю странику таким кодом: func FetchHTML(url string) (string, bool){ page := "" resp, HttpErr := http.Get(url) if HttpErr != nil { err := HTTPError{url, "", HttpErr.Error()} fmt.Println(err.Error()) return "", false } defer resp.Body.Close() body, IoErr := ioutil.ReadAll(resp.Body) if IoErr != nil { fmt.Println("IO error: ", IoErr.Error()) return "", false } fmt.Println(body) page = string(body) fetched = true return page, true } Примеры: Например, спарсим цитату из любимого всеми ithappens. Передаю парсеру страничку по адресу http://ithappens.me/story/623 Получаем: #623 КПД 100% 26 февраля 2009, 11:00 Приятель-программист поделился историей: написал для внутреннего пользования бенчмарк — в шестнадцати потоках перемножаются здоровенные матрицы. Все скомилировалось, запустилось и заработало, причем не просто быстро, а слишком быстро. Матрицы перемножались мгновенно! После разбора причин происходящего выяснилось, что тестовые матрицы представляли из себя массивы нулей. Умный интеловский компилято решил не загружать процессор перемножением и сложением нулей и оптимизировал код таким образом, чтобы сразу заполнить матрицы необходимого размера нулями. Rating: 1866 Tags: чудеса техники, программы Теперь пытаемся сделать то же самое, например, с http://bash.im/quote/435048 Получаем: #435048 2015-08-06 12:13 ���: �� �������� ���� �������� ������, ��������� 15 ��� ������ ���: ����� �������: ����, �� �� �����, �� ��� �� ������ ���: �� ���, �� � ����. ��� � �� �����, � ����� ������� ����. ���: ���� �������, � ��� ��� ����� ��� ������ �����, �������� ������������ �� ������ ��������� ����� ������ ������ ���: �� � � ������� �������, �������� - ���� �������������, ���������. �������������. ������: ���� �����, 158, 161, 162 (�����, ������, ������), ��������� ��� ��� �� �������� - ���� ����� ������� �� ������ �� ����������. (�� ����� ���� - �����, ����� ����� �� ���� � ������ ������ ������). �, ������, ���������, �� ��� ��� � �� �������. ���: ��� ��������, �������� ���: � ��� �������, ��� �� ��� ������. ���: ��������� ���������. ��������� �� ���������, �� 4 �����, ������� � ���� - ������ ������. ���� ������� �� �����, ������������ ������ - ����� ��� � �������� �����. ���, ��, ����� ����, ����� ����... ���� ����, ��� ���� �������� � ���� �����, ��� ��� � � ����� ����� ���� ����� ����� ��. � ������: ��-�������, ���� �������� �������. ���: ����!!! � � ���� ��������, �� ������� ������, �� �������!!! Rating: Заметил, что в то время как байты текста с ithappens имеют значение 1??, байты текста bash.im переваливают в значениях за 200. В чем может быть проблема и как ее решить?
Ответы
Ответ 1
Я рекомендую использовать пакет golang.org/x/net/html/charset и собственно его функцию NewReader. Эта функция принимает собственно io.Reader и заголовок Content-Type если он есть. Функция анализирует Content-Type и первые 1024 байта тела и возвращает io.Reader в кодировке UTF-8, а так же ошибку, если она имеет место. Всё просто и круто. Для примера: package main import ( "fmt" "golang.org/x/net/html/charset" "io/ioutil" "net/http" ) func main() { url := "http://bash.im/quote/435048" resp, err := http.Get(url) if err != nil { fmt.Println("HTTP error:", err) return } defer resp.Body.Close() // вот здесь и начинается самое интересное utf8, err := charset.NewReader(resp.Body, resp.Header.Get("Content-Type")) if err != nil { fmt.Println("Encoding error:", err) return } // оп-па-ча, готово body, err := ioutil.ReadAll(utf8) if err != nil { fmt.Println("IO error:", err) return } fmt.Println(string(body)) } Чем хорош этот способ - тем, что он универсален. Можно спокойно применять его для любого сайта. И нет нужды ковыряться в тегах вроде golang кодировка парсерОтвет 2
Посмотрите на код того же bash.im'а: Страница в кодировке Windows-1251. Чтобы перевести в UTF-8, пользуйтесь пакетами из golang.org/x/text. Например: dec := charmap.Windows1251.NewDecoder() // Разные кодировки = разные длины символов. newBody := make([]byte, len(body)*2) n, _, err := dec.Transform(newBody, body, false) if err != nil { panic(err) } newBody = newBody[:n]
Комментариев нет:
Отправить комментарий