美文网首页
golang 抓取网页并将其他编码(gbk,gb2312,big

golang 抓取网页并将其他编码(gbk,gb2312,big

作者: Fesion | 来源:发表于2020-09-21 17:39 被阅读0次

    最近用golang采集网页中遇到了各种不能识别的的乱码字符串,他们大多编码是gbk、gb2312、big5、windows-1252 等编码。有时候,网页上并没有声明编码,却使用上面这种编码的网页也有,也有网页声明的编码和实际使用的编码不同的网页,导致网页编码转换工作带来诸多不便,更多的是根据提示的编码转换出来依然还是乱码的问题,着实让人头疼。于是乎,为了得到一个通用可行的中文字符串编码转换方法,本人通过网络上上百万个网站测试,采集数据回来进行编码转换,终于总结出来了一套绝大部分都能顺利将网页中文字符串编码都转换成utf-8编码的方法。

    golang项目直接引用

    安装依赖包

    go get github.com/fesiong/goproject/convert
    

    使用说明
    对外公开有3个函数,Request函数支持请求网络页面,并自动检测页面内容的编码,转换成utf-8,ToUtf8函数支持传入的字符串会自动检测编码,并转换成utf-8,Convert函数需要传入原始编码和输出编码,如果原始编码传入出错,则转换出来的文本会乱码

    请求网络页面,并自动检测页面内容的编码,转换成utf-8

        link := "http://www.youth.cn/"
        resp, err := Request(link)
        if err != nil {
            t.Error(err.Error())
        }
    

    传入的字符串会自动检测编码,并转换成utf-8

        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[^>]*charset\s*=["']?\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
    }
    
    

    相关文章

      网友评论

          本文标题:golang 抓取网页并将其他编码(gbk,gb2312,big

          本文链接:https://www.haomeiwen.com/subject/zetbyktx.html