dy网页版弹幕数据抓取

dy弹幕数据抓取

侵权或涉及相关利益请联系作者:QQ邮箱

环境:

  • MacOS
  • golang 1.21+
  • protoc版本:libprotoc 25.1

抓取样例:

[进场][435837529504884][男] 肖靖远 进入直播间
[进场][64624951415][男] 建华.@.@ 进入直播间
[点赞][1327816996293822][女] 舍;得! 点赞 * 13 
[点赞][131584125580622][女] 🌺万里晴空🌸 点赞 * 25 
[关注][2379758914007816][女] abdisj 关注了主播
[进场][3526844532921287][男] 1314 进入直播间
[进场][4459243776260376][女] 用户7952123796342 进入直播间
[关注][2379758914007816][女] abdisj 关注了主播
[进场][83547928564][女] 小何 进入直播间
[进场][1626894999224967][男] 苦尽甘来 进入直播间
[进场][60771789788][男] Huang yong 进入直播间
[点赞][131584125580622][女] 🌺万里晴空🌸 点赞 * 19 
[进场][1275022271335976][女] Judy 进入直播间
[进场][97136425247][男] 简单人生 进入直播间
[进场][109513351102][女] 五月 进入直播间
[关注][1538943795083519][男] 若  生 关注了主播

详细代码:

package main

import (
	"bytes"
	"compress/gzip"
	"io"
	"log"
	"net/http"
	"regexp"
	"strings"
	"sync"
	"time"

	"github.com/golang/protobuf/proto"
	"github.com/gorilla/websocket"
	douyin "github.com/wgx0307/DouyinLiveComments/protobuf"
)

type Live struct {
	Url       string
	Ttwid     string
	RoomStore string
	RoomId    string
	RoomTitle string
	wsConn    *websocket.Conn
}

func main() {
	live, err := run("https://live.douyin.com/592737552981")
	if err != nil {
		panic(err)
	}
	live.Connect()
	var wg sync.WaitGroup
	wg.Add(1)
	wg.Wait()
}

func run(u string) (*Live, error) {
	h := map[string]string{
		"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36",
		"cookie":     "__ac_nonce=0638733a400869171be51",
	}
	req, err := http.NewRequest("GET", u, nil)
	if err != nil {
		log.Println(err)
		return nil, err
	}
	for k, v := range h {
		req.Header.Set(k, v)
	}
	client := &http.Client{}
	res, err := client.Do(req)
	if err != nil {
		log.Println(err)
		return nil, err
	}
	defer res.Body.Close()
	data := res.Cookies()
	var ttwid string
	for _, c := range data {
		if c.Name == "ttwid" {
			ttwid = c.Value
			break
		}
	}
	body, err := io.ReadAll(res.Body)
	if err != nil {
		log.Println(err)
		return nil, err
	}
	resText := string(body)
	re := regexp.MustCompile(`roomId\\":\\"(\d+)\\"`)
	match := re.FindStringSubmatch(resText)
	if match == nil || len(match) < 2 {
		log.Println("No match found")
		return nil, err
	}
	liveRoomId := match[1]
	return &Live{
		Url:    u,
		Ttwid:  ttwid,
		RoomId: liveRoomId,
	}, nil
}

func (live *Live) Connect() error {
	wsUrl := "wss://webcast3-ws-web-lq.douyin.com/webcast/im/push/v2/?" +
		"app_name=douyin_web&version_code=180800&webcast_sdk_version=1.3.0&update_version_code=1.3.0&compress=gzip&" +
		"internal_ext=internal_src:dim|wss_push_room_id:%s|wss_push_did:%s|dim_log_id:202302171547011A160A7BAA76660E13ED|fetch_time:1676620021641|seq:1|wss_info:0-1676620021641-0-0|wrds_kvs:WebcastRoomStatsMessage-1676620020691146024_WebcastRoomRankMessage-1676619972726895075_AudienceGiftSyncData-1676619980834317696_HighlightContainerSyncData-2&cursor=t-1676620021641_r-1_d-1_u-1_h-1&host=https://live.douyin.com&aid=6383&live_id=1&did_rule=3&debug=false&endpoint=live_pc&support_wrds=1&im_path=/webcast/im/fetch/&user_unique_id=%s&device_platform=web&cookie_enabled=true&screen_width=1440&screen_height=900&browser_language=zh&browser_platform=MacIntel&browser_name=Mozilla&browser_version=5.0%20(Macintosh;%20Intel%20Mac%20OS%20X%2010_15_7)%20AppleWebKit/537.36%20(KHTML,%20like%20Gecko)%20Chrome/110.0.0.0%20Safari/537.36&browser_online=true&tz_name=Asia/Shanghai&identity=audience&room_id=%s&heartbeatDuration=0&signature=00000000"
	wsUrl = strings.Replace(wsUrl, "%s", live.RoomId, -1)
	h := http.Header{}
	h.Set("cookie", "ttwid="+live.Ttwid)
	h.Set("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36")

	wsConn, _, err := websocket.DefaultDialer.Dial(wsUrl, h)
	if err != nil {
		return err
	}
	live.wsConn = wsConn
	go live.onMessage()
	go live.onHeartbeat()
	return nil
}

func (live *Live) onMessage() {
	for {
		_, data, err := live.wsConn.ReadMessage()
		if err != nil {
			panic(err.Error())
		}
		var msgPack douyin.PushFrame
		_ = proto.Unmarshal(data, &msgPack)
		decompressed, _ := degzip(msgPack.Payload)
		var payloadPackage douyin.Response
		_ = proto.Unmarshal(decompressed, &payloadPackage)
		if payloadPackage.NeedAck {
			live.sendAck(msgPack.LogId, payloadPackage.InternalExt)
		}
		for _, msg := range payloadPackage.MessagesList {
			switch msg.Method {
			case "WebcastChatMessage":
				parseChatMsg(msg.Payload)
			case "WebcastGiftMessage":
				parseGiftMsg(msg.Payload)
			case "WebcastLikeMessage":
				parseLikeMsg(msg.Payload)
			case "WebcastMemberMessage":
				parseEnterMsg(msg.Payload)
			case "WebcastSocialMessage":
				parseSocialMsg(msg.Payload)
			case "parseRoomUserSeqMsg":
				parseRoomUserSMsg(msg.Payload)
			}
		}
	}
}

func (live *Live) onHeartbeat() {
	for {
		pingPack := &douyin.PushFrame{
			PayloadType: "bh",
		}
		data, _ := proto.Marshal(pingPack)
		err := live.wsConn.WriteMessage(websocket.BinaryMessage, data)
		if err != nil {
			panic(err.Error())
		}
		time.Sleep(time.Second * 10)
	}
}

func (live *Live) sendAck(logId uint64, iExt string) {
	ackPack := &douyin.PushFrame{
		LogId:       logId,
		PayloadType: iExt,
	}
	data, _ := proto.Marshal(ackPack)
	err := live.wsConn.WriteMessage(websocket.BinaryMessage, data)
	if err != nil {
		panic(err.Error())
	}
	// log.Println("发送 ack 包")
}

func degzip(data []byte) ([]byte, error) {
	b := bytes.NewReader(data)
	var out bytes.Buffer
	r, err := gzip.NewReader(b)
	if err != nil {
		return nil, err
	}
	_, err = io.Copy(&out, r)
	if err != nil {
		return nil, err
	}
	return out.Bytes(), nil
}

func parseChatMsg(msg []byte) {
	var Message douyin.ChatMessage
	_ = proto.Unmarshal(msg, &Message)
	log.Printf("[弹幕][%d][%s] %s : %s\n", Message.User.Id, getGender(Message.User.Gender), Message.User.NickName, Message.Content)
}

func parseGiftMsg(msg []byte) {
	var Message douyin.GiftMessage
	_ = proto.Unmarshal(msg, &Message)
	log.Printf("[礼物][%d][%s] %s : %s * %d \n", Message.User.Id, getGender(Message.User.Gender), Message.User.NickName, Message.Gift.Name, Message.ComboCount)
}

func parseLikeMsg(msg []byte) {
	var Message douyin.LikeMessage
	_ = proto.Unmarshal(msg, &Message)
	log.Printf("[点赞][%d][%s] %s 点赞 * %d \n", Message.User.Id, getGender(Message.User.Gender), Message.User.NickName, Message.Count)
}

func parseEnterMsg(msg []byte) {
	var Message douyin.MemberMessage
	_ = proto.Unmarshal(msg, &Message)
	log.Printf("[进场][%d][%s] %s 进入直播间\n", Message.User.Id, getGender(Message.User.Gender), Message.User.NickName)
}

func parseSocialMsg(msg []byte) {
	var Message douyin.SocialMessage
	_ = proto.Unmarshal(msg, &Message)
	log.Printf("[关注][%d][%s] %s 关注了主播\n", Message.User.Id, getGender(Message.User.Gender), Message.User.NickName)
}

func parseRoomUserSMsg(msg []byte) {
	var Message douyin.RoomUserSeqMessage
	_ = proto.Unmarshal(msg, &Message)
	log.Printf("[统计] 当前观看人数: %d, 累计观看人数: %d \n", Message.Total, Message.TotalPvForAnchor)
}

func getGender(gender uint32) string {
	var sex = "女"
	if gender == 1 {
		sex = "男"
	}
	return sex
}

  • 35
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
蛋白质是生物体中普遍存在的一类重要生物大分子,由天然氨基酸通过肽键连接而成。它具有复杂的分子结构和特定的生物功能,是表达生物遗传性状的一类主要物质。 蛋白质的结构可分为四级:一级结构是组成蛋白质多肽链的线性氨基酸序列;二级结构是依靠不同氨基酸之间的C=O和N-H基团间的氢键形成的稳定结构,主要为α螺旋和β折叠;三级结构是通过多个二级结构元素在三维空间的排列所形成的一个蛋白质分子的三维结构;四级结构用于描述由不同多肽链(亚基)间相互作用形成具有功能的蛋白质复合物分子。 蛋白质在生物体内具有多种功能,包括提供能量、维持电解质平衡、信息交流、构成人的身体以及免疫等。例如,蛋白质分解可以为人体提供能量,每克蛋白质能产生4千卡的热能;血液里的蛋白质能帮助维持体内的酸碱平衡和血液的渗透压;蛋白质是组成人体器官组织的重要物质,可以修复受损的器官功能,以及维持细胞的生长和更新;蛋白质也是构成多种生理活性的物质,如免疫球蛋白,具有维持机体正常免疫功能的作用。 蛋白质的合成是指生物按照从脱氧核糖核酸(DNA)转录得到的信使核糖核酸(mRNA)上的遗传信息合成蛋白质的过程。这个过程包括氨基酸的活化、多肽链合成的起始、肽链的延长、肽链的终止和释放以及蛋白质合成后的加工修饰等步骤。 蛋白质降解是指食物中的蛋白质经过蛋白质降解酶的作用降解为多肽和氨基酸然后被人体吸收的过程。这个过程在细胞的生理活动中发挥着极其重要的作用,例如将蛋白质降解后成为小分子的氨基酸,并被循环利用;处理错误折叠的蛋白质以及多余组分,使之降解,以防机体产生错误应答。 总的来说,蛋白质是生物体内不可或缺的一类重要物质,对于维持生物体的正常生理功能具有至关重要的作用。
您可以使用Python的requests库向斗鱼API发送POST请求来发送弹幕。首先,您需要使用与斗鱼API提供的HTTP头以及您的斗鱼账号和房间号码进行身份验证。然后,您需要构建一个JSON对象,其中包含您要发送的消息和房间号码。最后,您需要将此JSON对象作为数据发送到API的弹幕发送端点。下面是一个简单的示例代码: ``` import requests import time # 身份验证信息 username = "您的斗鱼账号" password = "您的斗鱼密码" room_id = "要发送弹幕的房间号" # 获取登录token login_url = "https://passport.douyu.com/lapi/passport/loginByPassport" login_data = { "username": username, "password": password, "type": "normal" } login_response = requests.post(login_url, json=login_data).json() token = login_response["data"]["token"] # 发送弹幕 send_url = "https://www.douyu.com/betard/{room_id}/sendmsg".format(room_id=room_id) headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3", "Cookie": "acf_did=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;acf_uid=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;dy_did=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;dy_uid=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;smidV2=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;wan_auth37wan=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;acf_auth=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;acf_username=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;acf_userpwd=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;auth-time=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "Referer": "https://www.douyu.com/{room_id}".format(room_id=room_id), "content-type": "application/json", "token": token, } while True: # 发送弹幕内容 msg = "Hello, world!" data = { "msg": msg, "roomid": int(room_id), "cid": int(time.time()*1000), "ct": 0, "type": "chatmsg" } response = requests.post(send_url, json=data, headers=headers) time.sleep(10) # 10秒发送一次弹幕 ``` 请将上面代码中的xxxxxx替换成您的实际信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

极简网络科技

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值