原理:
1、编写扩展通过debugger api调用cdp接口,实现Network监听,完成websocket消息获取(protubuf格式)。
2、编写本地web服务,接受wss数据,对protubuf数据解析,完成消息采集。
实现:
1、扩展部分参考:https://www.jianshu.com/p/ed982f8c05bf,稍微修改即可;
2、protubuf解析,采用aardio。核心部分是protubuf结构定义;
dyResponse.proto
message Response {
required int32 id = 1;
required int32 msgid = 2;
required int32 flag = 3;
required int32 nid = 4;
message Option {
required string key = 1;
required string value = 2;
}
repeated Option option = 5;
message Other {
optional int32 o1 = 1;
optional int32 o2 = 2;
optional int32 o3 = 3;
optional int32 o4 = 4;
optional int32 o5 = 5;
optional int32 o6 = 6;
optional int32 o7 = 7;
optional int32 o8 = 8;
optional int32 o9 = 9;
optional int32 o10 = 10;
optional int32 o11 = 11;
optional int32 o12 = 12;
optional int32 o13 = 13;
optional int32 o14 = 14;
}
required Other other = 6;
required string type = 7;
required bytes msg = 8;
}
MsgResponse.proto
message MsgResponse {
repeated Message messages = 1;
string cursor = 2;
int64 fetchInterval = 3;
int64 now = 4;
string internalExt = 5;
int32 fetchType = 6;
map < string, string > routeParams = 7;
int64 heartbeatDuration = 8;
bool needAck = 9;
string pushServer = 10;
}
message Message {
string method = 1;
bytes payload = 2;
int64 msgId = 3;
int32 msgType = 4;
int64 offset = 5;
}
message Contributor {
int64 score = 1;
User user = 2;
int64 rank = 3;
int64 delta = 4;
bool isHidden = 5;
string scoreDescription = 6;
string exactlyScore = 7;
}
message RoomUserSeqMessage {
Common common = 1;
repeated Contributor ranks = 2;
int64 total = 3;
string popStr = 4;
repeated Contributor seats = 5;
int64 popularity = 6;
int64 totalUser = 7;
string totalUserStr = 8;
string totalStr = 9;
string onlineUserForAnchor = 10;
string totalPvForAnchor = 11;
}
message Detail {
Text text = 1;
int32 textFontSize = 2;
Image background = 3;
int32 start = 4;
int32 duration = 5;
int32 x = 6;
int32 y = 7;
int32 width = 8;
int32 height = 9;
int32 shadowDx = 10;
int32 shadowDy = 11;
int32 shadowRadius = 12;
string shadowColor = 13;
string strokeColor = 14;
int32 strokeWidth = 15;
}
message TextEffect {
Detail portrait = 1;
Detail landscape = 2;
}
message GiftMessage {
Common common = 1;
int64 giftId = 2;
int64 fanTicketCount = 3;
int64 groupCount = 4;
int64 repeatCount = 5;
int64 comboCount = 6;
User user = 7;
User toUser = 8;
int32 repeatEnd = 9;
TextEffect textEffect = 10;
int64 groupId = 11;
int64 incomeTaskgifts = 12;
int64 roomFanTicketCount = 13;
GiftIMPriority priority = 14;
GiftStruct gift = 15;
string logId = 16;
int64 sendType = 17;
PublicAreaCommon publicAreaCommon = 18;
Text trayDisplayText = 19;
int64 bannedDisplayEffects = 20;
GiftTrayInfo trayInfo = 21;
AssetEffectMixInfo assetEffectMixInfo = 24;
}
message LikeMessage {
Common common = 1;
int64 count = 2;
int64 total = 3;
int64 color = 4;
User user = 5;
string icon = 6;
}
message ChatMessage {
Common common = 1;
User user = 2;
string content = 3;
bool visibleToSender = 4;
Image backgroundImage = 5;
string fullScreenTextColor = 6;
Image backgroundImageV2 = 7;
PublicAreaCommon publicAreaCommon = 9;
Image giftImage = 10;
}
message SocialMessage {
Common common = 1;
User user = 2;
int64 shareType = 3;
int64 action = 4;
string shareTarget = 5;
int64 followCount = 6;
PublicAreaCommon publicAreaCommon = 7;
}
message EffectConfig {
int64 type = 1;
Image icon = 2;
int64 avatarPos = 3;
Text text = 4;
Image textIcon = 5;
int32 stayTime = 6;
int64 animAssetId = 7;
Image badge = 8;
repeated int64 flexSettingArray = 9;
Image textIconOverlay = 10;
Image animatedBadge = 11;
bool hasSweepLight = 12;
repeated int64 textFlexSettingArray = 13;
int64 centerAnimAssetId = 14;
}
message MemberMessage {
Common common = 1;
User user = 2;
int64 memberCount = 3;
User operator = 4;
bool isSetToAdmin = 5;
bool isTopUser = 6;
int64 rankScore = 7;
int64 topUserNo = 8;
int64 enterType = 9;
int64 action = 10;
string actionDescription = 11;
int64 userId = 12;
EffectConfig effectConfig = 13;
string popStr = 14;
EffectConfig enterEffectConfig = 15;
Image backgroundImage = 16;
Image backgroundImageV2 = 17;
Text anchorDisplayText = 18;
PublicAreaCommon publicAreaCommon = 19;
}
message ControlMessage {
Common common = 1;
int32 status = 2;
}
message FansclubMessage {
Common commonInfo = 1;
// 升级是1,加入是2
int32 type = 2;
string content = 3;
User user = 4;
}
message CommonTextMessage {
Common common = 1;
User user = 2;
}
message Common {
string method = 1;
int64 msgId = 2;
int64 roomId = 3;
int64 createTime = 4;
int32 monitor = 5;
bool isShowMsg = 6;
string describe = 7;
Text displayText = 8;
int64 foldType = 9;
int64 anchorFoldType = 10;
int64 priorityScore = 11;
string logId = 12;
string msgProcessFilterK = 13;
string msgProcessFilterV = 14;
User user = 15;
Room room = 16;
int64 anchorFoldTypeV2 = 17;
int64 processAtSeiTimeMs = 18;
}
message Text {
string key = 1;
string defaultPattern = 2;
TextFormat defaultFormat = 3;
repeated TextPiece pieces = 4;
}
message Room {
int64 id = 1;
string idStr = 2;
int64 status = 3;
int64 ownerUserId = 4;
string title = 5;
int64 userCount = 6;
int64 createTime = 7;
int64 linkmicLayout = 8;
int64 finishTime = 9;
RoomExtra extra = 10;
string dynamicCoverUri = 11;
map < int64,
string > dynamicCoverDict = 12;
int64 lastPingTime = 13;
int64 liveId = 14;
int64 streamProvider = 15;
int64 osType = 16;
int64 clientVersion = 17;
bool withLinkmic = 18;
bool enableRoomPerspective = 19;
Image cover = 20;
Image dynamicCover = 21;
Image dynamicCoverLow = 22;
string shareUrl = 23;
string anchorShareText = 24;
string userShareText = 25;
int64 streamId = 26;
string streamIdStr = 27;
StreamUrl streamUrl = 28;
int64 mosaicStatus = 29;
string mosaicTip = 30;
int64 cellStyle = 31;
LinkMic linkMic = 32;
int64 luckymoneyNum = 33;
repeated Decoration decoList = 34;
repeated TopFan topFans = 35;
RoomStats stats = 36;
string sunDailyIconContent = 37;
string distance = 38;
string distanceCity = 39;
string location = 40;
string realDistance = 41;
Image feedRoomLabel = 42;
string commonLabelList = 43;
RoomUserAttr livingRoomAttrs = 44;
repeated int64 adminUserIds = 45;
User owner = 46;
string privateInfo = 47;
}
message RoomExtra {}
message RoomStats {}
message RoomUserAttr {}
message StreamUrl {}
message LinkMic {}
message Decoration {}
message TopFan {}
message UserAttr {}
message OwnRoom {}
message AnchorInfo {}
message FollowInfo {
int64 followingCount = 1;
int64 followerCount = 2;
int64 followStatus = 3;
int64 pushStatus = 4;
string remarkName = 5;
}
message UserBadge {
map < int32,Image > icons = 1;
string title = 2;
}
message FansClubData {
string clubName = 1;
int32 level = 2;
int32 userFansClubStatus = 3;
UserBadge badge = 4;
repeated int64 availableGiftIds = 5;
int64 anchorId = 6;
}
message FansClub {
FansClubData data = 1;
map < int32, FansClubData > preferData = 2;
}
message Border {}
message GradeBuffInfo {
int64 buffLevel = 1;
int32 status = 2;
int64 endTime = 3;
map < int64,
int64 > statsInfo = 4;
Image buffBadge = 5;
}
message GradeIcon {
Image icon = 1;
int64 iconDiamond = 2;
int64 level = 3;
string levelStr = 4;
}
message PayGrade {
int64 totalDiamondCount = 1;
Image diamondIcon = 2;
string name = 3;
Image icon = 4;
string nextName = 5;
int64 level = 6;
Image nextIcon = 7;
int64 nextDiamond = 8;
int64 nowDiamond = 9;
int64 thisGradeMinDiamond = 10;
int64 thisGradeMaxDiamond = 11;
int64 payDiamondBak = 12;
string gradeDescribe = 13;
repeated GradeIcon gradeIconList = 14;
int64 screenChatType = 15;
Image imIcon = 16;
Image imIconWithLevel = 17;
Image liveIcon = 18;
Image newImIconWithLevel = 19;
Image newLiveIcon = 20;
int64 upgradeNeedConsume = 21;
string nextPrivileges = 22;
Image background = 23;
Image backgroundBack = 24;
int64 score = 25;
GradeBuffInfo buffInfo = 26;
string gradeBanner = 1001;
Image profileDialogBg = 1002;
Image profileDialogBgBack = 1003;
}
message User {
int64 id = 1;
int64 shortId = 2;
string nickname = 3;
int32 gender = 4;
string signature = 5;
int32 level = 6;
int64 birthday = 7;
string telephone = 8;
Image avatarThumb = 9;
Image avatarMedium = 10;
Image avatarLarge = 11;
bool verified = 12;
int32 experience = 13;
string city = 14;
int32 status = 15;
int64 createTime = 16;
int64 modifyTime = 17;
int32 secret = 18;
string shareQrcodeUri = 19;
int32 incomeSharePercent = 20;
Image badgeImageList = 21;
FollowInfo followInfo = 22;
PayGrade payGrade = 23;
FansClub fansClub = 24;
Border border = 25;
string specialId = 26;
Image avatarBorder = 27;
Image medal = 28;
repeated Image realTimeIcons = 29;
repeated Image newRealTimeIcons = 30;
int64 topVipNo = 31;
UserAttr userAttr = 32;
OwnRoom ownRoom = 33;
int64 payScore = 34;
int64 ticketCount = 35;
AnchorInfo anchorInfo = 36;
int32 linkMicStats = 37;
string displayId = 38;
string f39 = 39;
string f40 = 40;
string f41 = 41;
string f42 = 42;
string f43 = 43;
string f44 = 44;
string f45 = 45;
string secUid = 46;
string f47 = 47;
string f48 = 48;
string f49 = 49;
string f50 = 50;
string f51 = 51;
string f52 = 52;
string f53 = 53;
int32 f54 = 54;
string f55 = 55;
string f56 = 56;
string f57 = 57;
string f58 = 58;
string f59 = 59;
string f60 = 60;
Image f61 = 61;
string f62 = 62;
string f63 = 63;
string f64 = 64;
string f65 = 65;
bool f66 = 66;
string f67 = 67;
string desc = 68;
string f69 = 69;
string f70 = 70;
string f71 = 71;
string f72 = 72;
string webCastSecUid = 73;
string f74 = 74;
string f75 = 75;
string f76 = 76;
string f77 = 77;
string f78 = 78;
string f79 = 79;
}
message TextFormat {
string color = 1;
bool bold = 2;
bool italic = 3;
int32 weight = 4;
int32 italicAngle = 5;
int32 fontSize = 6;
bool userHeightLightColor = 7;
bool useRemoteClor = 8;
}
message TextPiece {
int32 type = 1;
TextFormat format = 2;
string stringValue = 11;
TextPieceUser userValue = 21;
}
message Content {
string name = 1;
string fontColor = 2;
int64 level = 3;
string alternativeText = 4;
}
message Image {
repeated string urlList = 1;
string uri = 2;
int64 height = 3;
int64 width = 4;
string avgColor = 5;
int32 imageType = 6;
string openWebUrl = 7;
Content content = 8;
bool isAnimated = 9;
}
message TextPieceUser {
User user = 1;
bool withColon = 2;
}
message PublicAreaCommon {
Image userLabel = 1;
int64 userConsumeInRoom = 2;
int64 userSendGiftCntInRoom = 3;
}
message GiftIMPriority {
repeated int64 queueSizes = 1;
int64 selfQueuePriority = 2;
int64 priority = 3;
}
message GiftTrayInfo {
Text trayDisplayText = 1;
Image trayBaseImg = 2;
Image trayHeadImg = 3;
Image trayRightImg = 4;
int64 trayLevel = 5;
Image trayDynamicImg = 6;
}
message GiftStructFansClubInfo {
int32 minLevel = 1;
int32 insertPos = 2;
}
message GiftStruct {
Image image = 1;
string describe = 2;
bool notify = 3;
int64 duration = 4;
int64 id = 5;
GiftStructFansClubInfo fansclubInfo = 6;
bool forLinkmic = 7;
bool doodle = 8;
bool forFansclub = 9;
bool combo = 10;
int32 type = 11;
int32 diamondCount = 12;
int32 isDisplayedOnPanel = 13;
int64 primaryEffectId = 14;
Image giftLabelIcon = 15;
string name = 16;
string region = 17;
string manual = 18;
bool forCustom = 19;
map < string,
int64 > specialEffects = 20;
Image icon = 21;
int32 actionType = 22;
int32 watermelonSeeds = 23;
string goldEffect = 24;
repeated LuckyMoneyGiftMeta subs = 25;
int64 goldenBeans = 26;
int64 honorLevel = 27;
int32 itemType = 28;
string schemeUrl = 29;
GiftPanelOperation giftOperation = 30;
string eventName = 31;
int64 nobleLevel = 32;
string guideUrl = 33;
bool punishMedicine = 34;
bool forPortal = 35;
string businessText = 36;
bool cnyGift = 37;
int64 appId = 38;
int64 vipLevel = 39;
bool isGray = 40;
string graySchemeUrl = 41;
int64 giftScene = 42;
GiftBanner giftBanner = 43;
repeated string triggerWords = 44;
repeated GiftBuffInfo giftBuffInfos = 45;
bool forFirstRecharge = 46;
Image dynamicImgForSelected = 47;
int32 afterSendAction = 48;
int64 giftOfflineTime = 49;
string topBarText = 50;
Image topRightAvatar = 51;
string bannerSchemeUrl = 52;
bool isLocked = 53;
int64 reqExtraType = 54;
repeated int64 assetIds = 55;
GiftPreviewInfo giftPreviewInfo = 56;
GiftTip giftTip = 57;
int32 needSweepLightCount = 58;
repeated GiftGroupInfo groupInfo = 59;
}
message AssetEffectMixInfo {}
message LuckyMoneyGiftMeta {}
message GiftPanelOperation {}
message GiftBanner {}
message GiftBuffInfo {}
message GiftPreviewInfo {}
message GiftTip {}
message GiftGroupInfo {}
message EffectMixImageInfo {}
3、poto结构解析转bean代码
import protobuf.parser;
var par = protobuf.parser();
par.parseFile("/res/dyResponse.proto",,false);
par.parseFile("/res/MsgResponse.proto",,false);
4、wss数据解析
// 抖音直播 protobuf 解析
import console;
import protobuf.parser;
import zlib;
/*
var par = protobuf.parser();
par.parseFile("/res/dyResponse.proto",,false);
par.parseFile("/res/MsgResponse.proto",,false);
*/
import AnchorInfo;
import AssetEffectMixInfo;
import Border;
import ChatMessage;
import Common;
import config;
import Content;
import Contributor;
import ControlMessage;
import Decoration;
import Detail;
import EffectConfig;
import EffectMixImageInfo;
import FansClub;
import FansClubData;
import FansclubMessage;
import FollowInfo;
import GiftBanner;
import GiftBuffInfo;
import GiftGroupInfo;
import GiftIMPriority;
import GiftMessage;
import GiftPanelOperation;
import GiftPreviewInfo;
import GiftStruct;
import GiftStructFansClubInfo;
import GiftTip;
import GiftTrayInfo;
import GradeBuffInfo;
import GradeIcon;
import Image;
import LikeMessage;
import LinkMic;
import LuckyMoneyGiftMeta;
import MemberMessage;
import Message;
import MsgResponse;
import OwnRoom;
import PayGrade;
import PublicAreaCommon;
import Response;
import Room;
import RoomExtra;
import RoomStats;
import RoomUserAttr;
import RoomUserSeqMessage;
import CommonTextMessage;
import SocialMessage;
import StreamUrl;
import Text;
import TextEffect;
import TextFormat;
import TextPiece;
import TextPieceUser;
import TopFan;
import User;
import UserAttr;
import UserBadge;
import zlib;
import crypt.bin;
import table;
import DouyinDb;
namespace DouyinLive;
var db = ..DouyinDb.DouyinDb();
function saveDb(data){
//..console.dumpTable(data);
db.saveLive(data);
}
function readRsp(user,roomid){
u = null;
if(user["id"]){
u = {
uid = user["id"] ? ..string.format("%.0f",user.id) : "";
shortId = user["shortId"] ? ..string.format("%.0f",user.shortId) : "";
displayId = user["displayId"] ? tostring(user.displayId) : "";
secUid = user["secUid"] ? tostring(user.secUid) : "";
nickname = user["nickname"] ? user.nickname : "";
img = user["avatarThumb"] ? user.avatarThumb.urlList[1].value : "";
roomId = roomid;
}
//..console.dumpTable(u);
}
return u;
}
function parse(data,roomid){
data = ..crypt.bin.decodeBase64(data);
var res = ..Response();
res.parseFromString(data);
txt = ..zlib.gzUncompress(res.msg,"gzip");
if(txt == null or #txt == 0){
return {};
}
var msg = ..MsgResponse();
msg.parseFromString(txt);
var result = {};
var msgs = {};
for(k,v in msg.messages){
var msgObj = null;
select(v.method) {
case "WebcastRoomUserSeqMessage" {
msgObj = ..RoomUserSeqMessage();
}
case "WebcastGiftMessage" {
msgObj = ..GiftMessage();
}
case "WebcastLikeMessage" {
msgObj = ..LikeMessage();
}
case "WebcastChatMessage" {
msgObj = ..ChatMessage();
}
case "WebcastSocialMessage" {
msgObj = ..SocialMessage();
}
case "WebcastMemberMessage" {
msgObj = ..MemberMessage();
}
case "WebcastControlMessage" {
msgObj = ..ControlMessage();
}
case "WebcastFansclubMessage" {
msgObj = ..FansclubMessage();
}
case "WebcastCommonTextMessage" {
msgObj = ..CommonTextMessage();
}
else {
}
}
if(msgObj){
msgObj.parseFromString(v.payload);
var user = null;
var msg = null;
if(msgObj.common && msgObj.common.displayText){
if(msgObj.common.displayText.defaultPattern){
var defaultPattern = msgObj.common.displayText.defaultPattern;
for(k1,v1 in msgObj.common.displayText.pieces){
var str = null;
if(v1["userValue"]){
user = v1.userValue.user;
str = user.nickname;
}else {
str = (v1.stringValue == null) ? "" : v1.stringValue;
}
defaultPattern = ..string.replace(defaultPattern,"{" + (k1-1) + "\:[a-zA-Z]+}",str);
}
msg = ..string.replace(defaultPattern,"{\d+\:[a-zA-Z]+}","");
u = readRsp(user,roomid);
if(u){
..table.push(result,u);
..table.push(msgs,msg);
}
}
}elseif(msgObj.user){
user = msgObj.user;
if(msgObj["content"]){
msg = user.nickname + " : " + msgObj.content;
}
u = readRsp(user,roomid);
if(u){
..table.push(result,u);
..table.push(msgs,msg);
}
}elseif(msgObj["ranks"]){
/*
// 房间同步信息,先不要
for(k,v in msgObj.ranks){
user = v.user;
u = readRsp(user);
if(u){
table.push(result,u);
table.push(msgs,"房间信息同步");
}
} */
}
}
}
if(result && #result>0){
saveDb(result);
}
return msgs;
}
/**intellisense()
DouyinLive.parse(.(待解析数据) = 抖音数据解析。\n入参为抖音protobuf数据。
end intellisense**/
非成品代码,核心代码已贴。
网友评论