使用 golang 解析腾讯视频真实链接

本文最后由 森林生灵 于 2020/05/01 18:22:37 编辑

文章目录 (?) [+]

    package main
    
    import (
        "fmt"
        "io/ioutil"
        "net/http"
        "regexp"
        "strings"
    )
    
    func main() {
        // 仅对非会员视频链接有效
        url := "https://v.qq.com/x/page/b0945ug7vzo.html"
        // 先确定 .html 的最早出现的位置,以排除之后 callback 的链接中可能携带的 .html
        b := strings.Index(url, ".html")
        // 从确定的 .html 向前找最后一个 / 出现的位置
        a := strings.LastIndex(url[:b], "/")
        // 获取视频 id
        vid := url[a+1 : b]
    
        // 获取视频 json 信息
        url = "https://vv.video.qq.com/getinfo?vids=" + vid + "&platform=101001&charge=0&otype=json"
        resp, err := http.Get(url)
        if err != nil {
            fmt.Println(err)
    
            return
        }
        defer resp.Body.Close()
    
        body, err := ioutil.ReadAll(resp.Body)
        if err != nil {
            fmt.Println(err)
    
            return
        }
    
        // 正则出 json
        re, err := regexp.Compile("^QZOutputJson=(.*?);$")
        if err != nil {
            fmt.Println(err)
    
            return
        }
    
        ret := re.FindSubmatch(body)
        if len(ret) < 2 {
            fmt.Println("cannot get video info")
    
            return
        }
    
        // 获取 fn 与 fvkey
        // 每次获取的 fn 固定不变 fvkey 会变
        var fn, fvkey string
    
        // 方法一:查找关键字
        // str := string(ret[1])
        // ftfn := "\"fn\":\""
        // ftfvkey := "\"fvkey\":\""
        //
        // a = strings.LastIndex(str, ftfn)
        // if a > 0 {
        //     b = strings.Index(str[a+len(ftfn):], "\"")
        //     if b > 0 && len(str) >= a+b {
        //         // a+ 1因为下标为0开始,-1是因为计算长度时将第一位也计算在内,与当前位置重复
        //         fn = str[a+1+len(ftfn)-1 : a+len(ftfn)+b]
        //
        //     }
        //     fmt.Println("string()", a, b, len(str), len("\"fn\":\""), fn)
        // }
        //
        // a = strings.LastIndex(str, ftfvkey)
        // if a > 0 {
        //     b = strings.Index(str[a+len(ftfvkey):], "\"")
        //     if b > 0 && len(str) >= a+b {
        //         // a+ 1因为下标为0开始,-1是因为计算长度时将第一位也计算在内,与当前位置重复
        //         fvkey = str[a+1+len(ftfvkey)-1 : a+len(ftfvkey)+b]
        //
        //     }
        //     fmt.Println("string()", a, b, len(str), len("\"fvkey\":\""), fvkey)
        // }
    
        // 方法二:正则匹配
        re, err = regexp.Compile(`"fn":"(.*?)"`)
        if err != nil {
            fmt.Println(err)
    
            return
        }
    
        retfn := re.FindSubmatch(ret[1])
        if len(retfn) < 2 {
            fmt.Println("cannot get the key")
    
            return
        }
        fn = string(retfn[1])
    
        re, err = regexp.Compile(`"fvkey":"(.*?)"`)
        if err != nil {
            fmt.Println(err)
    
            return
        }
    
        retfvkey := re.FindSubmatch(ret[1])
        if len(retfvkey) < 2 {
            fmt.Println("cannot get the key")
    
            return
        }
        fvkey = string(retfvkey[1])
    
        // 方法三:json 解码 emmm...
        // var info map[string]interface{}
        // dec := json.NewDecoder(bytes.NewBuffer(ret[1]))
        // err = dec.Decode(&info)
        // if err != nil {
        //     fmt.Println(err)
        // }
        //
        // if m, exist := info["vl"]; exist {
        //     if m, ok := m.(map[string]interface{}); ok {
        //         if m, exist := m["vi"]; exist {
        //             // fmt.Printf("%T\n", m)
        //             if m, ok := m.([]interface{}); ok {
        //                 if len(m) > 0 {
        //                     if m, ok := m[0].(map[string]interface{}); ok {
        //                         if m, exist := m["fn"]; exist {
        //                             if m, ok := m.(string); ok {
        //                                 fn = m
        //                             }
        //                         }
        //
        //                         if m, exist := m["fvkey"]; exist {
        //                             if m, ok := m.(string); ok {
        //                                 fvkey = m
        //                             }
        //                         }
        //                     }
        //                 }
        //             }
        //         }
        //     }
        // }
    
        if fn != "" && fvkey != "" {
            src := "https://ugcws.video.gtimg.com/" + fn + "?vkey=" + fvkey
            fmt.Println(src)
    
            return
        }
    
        fmt.Println("cannot get the key")
    }


    本文标题:使用 golang 解析腾讯视频真实链接
    本文链接:https://lanseyujie.com/post/using-golang-to-analyze-the-real-link-of-tencent-video.html
    版权声明:本文使用「署名-非商业性使用-相同方式共享」创作共享协议,转载或使用请遵守署名协议。
    点赞 0 分享 0