最近用golang采集网页中遇到了各类不能识别的的乱码字符串,他们大多编码是gbk、gb23十二、big五、windows-1252 等编码。有时候,网页上并无声明编码,却使用上面这种编码的网页也有,也有网页声明的编码和实际使用的编码不一样的网页,致使网页编码转换工做带来诸多不便,更多的是根据提示的编码转换出来依然仍是乱码的问题,着实让人头疼。因而乎,为了获得一个通用可行的中文字符串编码转换方法,本人经过网络上上百万个网站测试,采集数据回来进行编码转换,终于总结出来了一套绝大部分都能顺利将网页中文字符串编码都转换成utf-8编码的方法。html
安装依赖包git
go get github.com/fesiong/goproject/convert
使用说明github
对外公开有3个函数,Request函数支持请求网络页面,并自动检测页面内容的编码,转换成utf-8,ToUtf8函数支持传入的字符串会自动检测编码,并转换成utf-8,Convert函数须要传入原始编码和输出编码,若是原始编码传入出错,则转换出来的文本会乱码golang
请求网络页面,并自动检测页面内容的编码,转换成utf-8shell
link := "http://www.youth.cn/" resp, err := Request(link) if err != nil { t.Error(err.Error()) }
传入的字符串会自动检测编码,并转换成utf-8windows
content := "中国青年网" content = ToUtf8(content)
传入原始编码和输出编码网络
content := "中国青年网" content = Convert(content, "utf-8", "utf-8")
github.com/fesiong/goproject函数
package convert import ( "github.com/axgle/mahonia" "github.com/parnurzeal/gorequest" "golang.org/x/net/html/charset" "net/http" "regexp" "strings" "time" ) type RequestData struct { Header http.Header Request *http.Request Body string Status string StatusCode int } /** * 请求网络页面,并自动检测页面内容的编码,转换成utf-8 */ func Request(urlPath string) (*RequestData, error) { resp, body, errs := gorequest.New().Timeout(90 * time.Second).Get(urlPath).End() if len(errs) > 0 { //若是是https,则尝试退回http请求 if strings.HasPrefix(urlPath, "https") { urlPath = strings.Replace(urlPath, "https://", "http://", 1) return Request(urlPath) } return nil, errs[0] } defer resp.Body.Close() contentType := strings.ToLower(resp.Header.Get("Content-Type")) body = toUtf8(body, contentType) requestData := RequestData{ Header: resp.Header, Request: resp.Request, Body: body, Status: resp.Status, StatusCode: resp.StatusCode, } return &requestData, nil } /** * 对外公开的编码转换接口,传入的字符串会自动检测编码,并转换成utf-8 */ func ToUtf8(content string) string { return toUtf8(content, "") } /** * 内部编码判断和转换,会自动判断传入的字符串编码,并将它转换成utf-8 */ func toUtf8(content string, contentType string) string { var htmlEncode string if strings.Contains(contentType, "gbk") || strings.Contains(contentType, "gb2312") || strings.Contains(contentType, "gb18030") || strings.Contains(contentType, "windows-1252") { htmlEncode = "gb18030" } else if strings.Contains(contentType, "big5") { htmlEncode = "big5" } else if strings.Contains(contentType, "utf-8") { htmlEncode = "utf-8" } if htmlEncode == "" { //先尝试读取charset reg := regexp.MustCompile(`(?is)<meta[^>]*charsets*=["']?s*([A-Za-z0-9-]+)`) match := reg.FindStringSubmatch(content) if len(match) > 1 { contentType = strings.ToLower(match[1]) if strings.Contains(contentType, "gbk") || strings.Contains(contentType, "gb2312") || strings.Contains(contentType, "gb18030") || strings.Contains(contentType, "windows-1252") { htmlEncode = "gb18030" } else if strings.Contains(contentType, "big5") { htmlEncode = "big5" } else if strings.Contains(contentType, "utf-8") { htmlEncode = "utf-8" } } if htmlEncode == "" { reg = regexp.MustCompile(`(?is)<title[^>]*>(.*?)</title>`) match = reg.FindStringSubmatch(content) if len(match) > 1 { aa := match[1] _, contentType, _ = charset.DetermineEncoding([]byte(aa), "") htmlEncode = strings.ToLower(htmlEncode) if strings.Contains(contentType, "gbk") || strings.Contains(contentType, "gb2312") || strings.Contains(contentType, "gb18030") || strings.Contains(contentType, "windows-1252") { htmlEncode = "gb18030" } else if strings.Contains(contentType, "big5") { htmlEncode = "big5" } else if strings.Contains(contentType, "utf-8") { htmlEncode = "utf-8" } } } } if htmlEncode != "" && htmlEncode != "utf-8" { content = Convert(content, htmlEncode, "utf-8") } return content } /** * 编码转换 * 须要传入原始编码和输出编码,若是原始编码传入出错,则转换出来的文本会乱码 */ func Convert(src string, srcCode string, tagCode string) string { srcCoder := mahonia.NewDecoder(srcCode) srcResult := srcCoder.ConvertString(src) tagCoder := mahonia.NewDecoder(tagCode) _, cdata, _ := tagCoder.Translate([]byte(srcResult), true) result := string(cdata) return result }