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")
}
来源:oschina
链接:https://my.oschina.net/lanseyujie/blog/4285639