кодировка – Problems with encoding when parsing some sites, Golang

Question:

Good day.
Faced such a problem: some sites are parsed adequately – the text from the forms gets in a readable encoding, and some do not.
At first, I sinned on UTF-8 on the site, but Go is a little bit with UTF-8 only and works by default
I get the page like this:

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
}

Examples:
For example, let's parse a quote from everyone's favorite ithappens.
I pass the page to the parser at http://ithappens.me/story/623
We get:

#623
КПД 100%
26 февраля 2009, 11:00

Приятель-программист поделился историей: написал для внутреннего пользования бенчмарк — в шестнадцати потоках перемножаются здоровенные матрицы. Все скомилировалось, запустилось и заработало, причем не просто быстро, а слишком быстро.
Матрицы перемножались мгновенно!
После разбора причин происходящего выяснилось, что тестовые матрицы представляли из себя массивы нулей. Умный интеловский компилято решил не загружать процессор перемножением и сложением нулей и оптимизировал код таким образом, чтобы сразу заполнить матрицы необходимого размера нулями.

Rating: 1866
Tags: чудеса техники, программы

Now we are trying to do the same, for example, with http://bash.im/quote/435048
We get:

#435048
2015-08-06 12:13
���: �� �������� ���� �������� ������, ��������� 15 ��� ������
���: ����� �������: ����, �� �� �����, �� ��� �� ������
���: �� ���, �� � ����. ��� � �� �����, � ����� ������� ����.
���: ���� �������, � ��� ��� ����� ��� ������ �����, �������� ������������ �� ������ ��������� ����� ������ ������
���: �� � � ������� �������, �������� - ���� �������������, ���������.     �������������. ������: ���� �����, 158, 161, 162 (�����, ������, ������), ��������� ��� ��� �� �������� - ���� ����� ������� �� ������ �� ����������. (�� ����� ���� - �����, ����� ����� �� ���� � ������ ������ ������). �, ������, ���������, �� ��� ��� � �� �������.
���: ��� ��������, ��������
���: � ��� �������, ��� �� ��� ������.
���: ��������� ���������. ��������� �� ���������, �� 4 �����, ������� � ���� - ������ ������. ���� ������� �� �����, ������������ ������ - ����� ��� � �������� �����. ���, ��, ����� ����, ����� ����... ���� ����, ��� ���� �������� � ���� �����, ��� ��� � � ����� ����� ���� ����� ����� ��. � ������: ��-�������, ���� �������� �������.
���: ����!!! � � ���� ��������, �� ������� ������, �� �������!!!
Rating:

I noticed that while the bytes of text with ithappens are 1??, the bytes of text bash.im are over 200. What could be the problem and how to solve it?

Answer:

I recommend using the golang.org/x/net/html/charset package and its NewReader function itself.

This function takes the actual io.Reader and Content-Type header if present. The function parses the Content-Type and the first 1024 bytes of the body and returns a UTF-8 encoded io.Reader and an error, if any. Everything is simple and cool.

For example:

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))
}

What is good about this method is that it is universal. You can easily apply it to any site. And there's no need to fiddle around with tags like <meta ...>

Scroll to Top