最近用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 }