SocialSisterYi / bilibili-API-collect

哔哩哔哩-API收集整理【不断更新中....】
https://socialsisteryi.github.io/bilibili-API-collect/
Other
14.93k stars 1.7k forks source link

这个直播弹幕获取不到是为什么呢? #499

Closed washimisukou closed 2 years ago

washimisukou commented 2 years ago

package main

import ( "bytes" "context" "encoding/binary" "encoding/json" "fmt" //"strings"

//"go/printer"
"io/ioutil"
"net"
"net/http"
"net/url"
"strconv"
"time"

"github.com/gobwas/ws"
"github.com/gobwas/ws/wsutil"

)

type tokin_json_struct struct { Code int json:"code,omitempty" Message string json:"message,omitempty" TTL int json:"ttl,omitempty" Data struct { //设定数据类型 Group string json:"group,omitempty" BusinessID int json:"business_id,omitempty" RefreshRowFactor float64 json:"refresh_row_factor,omitempty" RefreshRate int json:"refresh_rate,omitempty" MaxDelay int json:"max_delay,omitempty" Token string json:"token,omitempty" HostList []struct { //获取服务器地址 Host string json:"host,omitempty" //获取服务器通讯端口 Port int json:"port,omitempty" //获取服务器WS通讯端口 WssPort int json:"wss_port,omitempty" //获取服务器WS+TLS通讯端口 WsPort int json:"ws_port,omitempty" } json:"host_list,omitempty" } json:"data,omitempty" }

func main() { //tokin 认证密钥 roomid 房间ID //data 返回的数据

//roomid 目前为手写,后面将会改为UI设定导入
roomid := "5055636"
var auth_pack []byte
tokin, serlist := get_tokin(roomid)
//t1 := get_id(roomid)
//println(t1)
//fmt.Println("Token: " + tokin)
fmt.Println("Ser_Addr: " + serlist[0][0])
fmt.Println("Ser_Port: " + serlist[0][1] + "  Ser_WsPort: " + serlist[0][2] + "  Ser_WssPort: " + serlist[0][3])
fmt.Println("Ser_Addr: " + serlist[1][0])
fmt.Println("Ser_Port: " + serlist[1][1] + "  Ser_WsPort: " + serlist[1][2] + "  Ser_WssPort: " + serlist[1][3])
fmt.Println("Ser_Addr: " + serlist[2][0])
fmt.Println("Ser_Port: " + serlist[2][1] + "  Ser_WsPort: " + serlist[2][2] + "  Ser_WssPort: " + serlist[2][3])
fmt.Println("Ser_Addr: " + serlist[3][0])
fmt.Println("Ser_Port: " + serlist[3][1] + "  Ser_WsPort: " + serlist[3][2] + "  Ser_WssPort: " + serlist[3][3])
Ws_url_addr := url.URL{Scheme: "ws", Opaque: "", User: nil, Host: serlist[2][0] + ":" + serlist[2][2], Path: "/sub", RawPath: "", OmitHost: false, ForceQuery: false, RawQuery: "", Fragment: "", RawFragment: ""}
auth_pack, _ = build_pack(tokin,roomid, 1, 0)
fmt.Println(auth_pack, 1)
fmt.Println("Connet...")
fmt.Println("Address:" + Ws_url_addr.String())
ws_class := build_ws_class(Ws_url_addr.String())
if tx_ws(ws_class, auth_pack) == 0 {
    for {
        data, data_type := rx_ws(ws_class)
        if data_type == 0 {
            fmt.Println("Auth Success")
            go TickerforHeart(ws_class, tokin,roomid)
        } else if data_type == 1 {
            fmt.Println(data) //人气值回包
        } else if data_type == 2 {
            fmt.Println(data) //其他数据回包
        }
    }
}

}

// 获取服务器列表及端口 以及tokin func get_tokin(rid string) (string, [][4]string) { response, err := http.Get("https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuInfo?id=" + rid+"&type=0") if err != nil { panic(err) } //defer response.Body.Close() b_body, err2 := ioutil.ReadAll(response.Body) if err2 != nil { panic(err2) } var tokin_json tokin_json_struct err3 := json.Unmarshal(b_body, &tokin_json) if err3 != nil { panic(err3) } host_list_arry := make([][4]string, 4) for i := 0; i < len(tokin_json.Data.HostList); i++ { host_list_arry[i][0] = tokin_json.Data.HostList[i].Host host_list_arry[i][1] = strconv.Itoa(tokin_json.Data.HostList[i].Port) host_list_arry[i][2] = strconv.Itoa(tokin_json.Data.HostList[i].WsPort) host_list_arry[i][3] = strconv.Itoa(tokin_json.Data.HostList[i].WssPort) } return (tokin_json.Data.Token), (host_list_arry) }

func get_id(rid string) string { response, err := http.Get("https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuInfo?id=" + rid+"&type=0") if err != nil { panic(err) } //defer response.Body.Close() b_body, err2 := ioutil.ReadAll(response.Body) if err2 != nil { panic(err2) }

return (string(b_body[:]))

} // int64 转 []byte func Int16ToBytes(i int16) []byte { var buf = make([]byte, 2) binary.BigEndian.PutUint16(buf, uint16(i)) return buf }

// int32 转 []byte func Int32ToBytes(i int32) []byte { var buf = make([]byte, 4) binary.BigEndian.PutUint32(buf, uint32(i)) return buf }

// 构建数据包 opt=0 认证包 opt=1 心跳包 func build_pack(tok string,rid string, seq int, opt int) ([]byte, int) { //打包数据 var tx_pack_buff bytes.Buffer var data, sequence, oper_code, rx_pack_full_size, tx_pack []byte //包头大小 head_size := []byte(Int16ToBytes(int16(16))) //协议版本 agr_ver := []byte(Int16ToBytes(int16(1))) //seq sequence = []byte(Int32ToBytes(int32(1))) if opt == 0 { //认证包内容 data = []byte(string("\"uid\":26895052,\"roomid\":" + rid + ",\"protover\":3,\"platform\":\"web\",\"type\":2,\"key\":\""+ tok +"\"}")) //认证包SEQ //sequence = Int32ToBytes(int32(1)) //认证包操作码 oper_code = Int32ToBytes(int32(7)) } else if opt == 1 { //心跳包内容 data = []byte("{\"heart\":0}") //心跳包SEQ //sequence = Int32ToBytes(int32(seq+1)) //心跳包操作码 oper_code = Int32ToBytes(int32(2)) } //数据包总大小 rx_pack_full_size = Int32ToBytes(int32(len(data) + 16)) //组合包 tx_pack_buff.Write(rx_pack_full_size) tx_pack_buff.Write(head_size) tx_pack_buff.Write(agr_ver) tx_pack_buff.Write(oper_code) tx_pack_buff.Write(sequence) tx_pack_buff.Write(data) //组合完成体 tx_pack = tx_pack_buff.Bytes() if opt == 0 { return tx_pack, 1 } else if opt == 1 { return tx_pack, (seq + 1) } else { return []byte(""), 0 } }

// 构建webcocket 类 func build_wsclass(url string) net.Conn { ctx := context.Background() conn, , _, err4 := ws.Dial(ctx, url) //fmt.Println(Ws_seraddr) //conn, , _, err4 := ws.Dial(ctx,Ws_ser_addr) if err4 != nil { panic(err4) } return conn }

// 发包 func tx_ws(conn net.Conn, rx_pack []byte) int { //WebSocket认证包发送 err5 := wsutil.WriteClientMessage(conn, ws.OpBinary, rx_pack) if err5 != nil { panic(err5) } return 0 }

// 收包 0 认证回包 1 心跳包 2 普通包 func rxws(conn net.Conn) (string, int) { msg, , err6 := wsutil.ReadServerData(conn) if err6 != nil { panic(err6) } json_data := string(msg[16:]) json_data2 := string(msg[20:]) //fmt.Println("人气值(POP):" + string(msg[14:15]) + " Back_pack:" + json_data) if json_data == "{\"code\":0}" { return json_data, 0 } else if json_data2 == "{\"hea" { fmt.Println("Get_heart_Success") return "{\"pop\":" + string(msg[14:15]) + "}", 1 } else { return json_data, 2 } }

func TickerforHeart(conn net.Conn, tok string,rid string) int { var b_seq int seq := 1 var heart_pack []byte heart := time.NewTicker(15 * time.Second) defer heart.Stop() for range heart.C { heart_pack, b_seq = build_pack(tok,rid, seq, 1) //构建心跳包 if tx_ws(conn, heart_pack) == 0 { seq = b_seq //发送心跳包 fmt.Println("Send_heart_Success Seq:"+ strconv.Itoa(seq))

    }
}
return 0

}

//发送认证包->接收认证包回应->接收普通包&(每30秒发送心跳包->接收心跳回应)

washimisukou commented 2 years ago

这个程序目前只能抓取到 STOP_LIVE_ROOM_LIST和NOTICE_MSG