Skip to content

Instantly share code, notes, and snippets.

@julianshen
Created October 5, 2016 03:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save julianshen/137c3584ef805ae5cf74147ae737b697 to your computer and use it in GitHub Desktop.
Save julianshen/137c3584ef805ae5cf74147ae737b697 to your computer and use it in GitHub Desktop.
package main
import (
"crypto/md5"
"encoding/json"
"errors"
"fmt"
"io"
"log"
"regexp"
"sort"
"strings"
"github.com/PuerkitoBio/goquery"
"github.com/parnurzeal/gorequest"
)
type DocId struct {
CID string
AID string
}
const (
APP_KEY = "6f90a59ac58a4123"
APP_SEC = "0bfd84cc3940035173f35e6777508326"
BASE_URL = "https://interface.bilibili.com/playurl"
)
func signParam(param map[string]string) {
param["appkey"] = APP_KEY
keys := make([]string, len(param))
i := 0
for k, _ := range param {
keys[i] = k
i++
}
sort.Strings(keys)
data := ""
for _, v := range keys {
if data != "" {
data += "&"
}
data += v + "=" + param[v]
}
data += APP_SEC
param["sign"] = fmt.Sprintf("%x", md5.Sum([]byte(data)))
}
func parseId(id string) (*DocId, error) {
url := fmt.Sprintf("http://www.bilibili.com/video/av%s", id)
doc, err := goquery.NewDocument(url)
if err != nil {
return nil, err
}
sel := doc.Find(".scontent>script")
if sel != nil {
script := sel.Text()
regex := regexp.MustCompile("cid=(\\d+)&aid=(\\d+)&pre_ad=.*")
result := regex.FindStringSubmatch(script)
if result == nil {
return nil, errors.New("ID not found")
}
var id DocId
id.CID = result[1]
id.AID = result[2]
return &id, nil
} else {
return nil, errors.New("ID not found")
}
}
func GrabVideoUrl(aid string) (string, error) {
id, err := parseId(aid)
if err != nil {
return "", err
}
var param map[string]string = make(map[string]string)
param["cid"] = id.CID
param["otype"] = "json"
param["type"] = "mp4"
param["quality"] = "3"
signParam(param)
data := ""
for k, v := range param {
if data != "" {
data += "&"
}
data += k + "=" + v
}
url := fmt.Sprintf("%s?%s", BASE_URL, data)
request := gorequest.New()
_, body, errs := request.Get(url).End()
if errs != nil && len(errs) > 0 {
return "", errs[0]
}
//log.Println(body)
dec := json.NewDecoder(strings.NewReader(body))
video_url := ""
for {
t, err := dec.Token()
if err == io.EOF {
break
}
if err != nil {
return "", err
}
//fmt.Printf("%T: %v", t, t)
if t == "url" {
t, err := dec.Token()
if err != nil {
return "", err
}
video_url = fmt.Sprintf("%v", t)
}
//fmt.Printf("\n")
}
return video_url, nil
}
func main() {
//url := "http://www.bilibili.com/video/av6467776/"
url, _ := GrabVideoUrl("6467776")
log.Println(url)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment