本案例是基于douyin web直播数据的protobuf协议解析。
本文只是protobuf的解析和还原,和signature无关。
文章内容仅供参考学习,如有侵权请联系作者进行删除
逻辑梳理
protobuf 之前有说过,就不再重复了。
查看 common-utils-message.979d96f7.js 中的方法
var d = (new Map).
set("WebcastDiggMessage", "DiggMessage").
set("WebcastFansclubMessage", "FansclubMessage").
set("WebcastScreenChatMessage", "ScreenChatMessage").
set("WebcastControlMessage", "ControlMessage").
set("WebcastSocialMessage", "SocialMessage").
set("WebcastRoomMessage", "RoomMessage").
set("WebcastFansclubStatisticsMessage", "FansclubStatisticsMessage"
set("WebcastRoomVerifyMessage", "RoomVerifyMessage").
set("WebcastNoticeMessage", "NoticeMessage").
set("WebcastNobleUpgradeMessage", "NobleUpgradeMessage").
set("WebcastImDeleteMessage", "ImDeleteMessage").
set("WebcastSunDailyRegionRankMessage","SunDailyRankMessage").
set("WebcastSunDailyRankMessage", "SunDailyRankMessage").
set("WebcastRoomUserSeqMessage", "RoomUserSeqMessage").
set("WebcastVerificationCodeMessage", "VerificationCodeMessage").
set("WebcastLinkMicMethod", "LinkMicMethod").
set("WebcastLinkMicBattleMethod", "LinkMicBattle")
.set("WebcastLinkMicBattleFinishMethod", "LinkMicBattleFinish").
set("WebcastRoomNotifyMessage", "NotifyMessage").
set("WebcastLinkMicSignalingMethod", "LinkMicSignalingMethod").
set("WebcastLotteryEventMessage", "LotteryEventMessage").
set("WebcastUploadCoverMessage", "UploadCoverMessage").
set("WebcastCategoryChangeMessage", "CategoryChangeMessage").
set("WebcastRoomChallengeMessage", "RoomChallengeMessage").
set("WebcastLikeMessage", "LikeMessage").
set("WebcastLinkMicArmiesMethod", "LinkMicArmies").
set("WebcastGameInviteMessage", "GameInviteMessage").
set("WebcastQuizStartMessage", "QuizStartMessage").
set("WebcastQuizResultMessage", "QuizResultMessage").
set("WebcastQuizChangeMessage", "QuizChangeMessage").
set("WebcastQuizBeginMessage", "QuizBeginMessage").
set("WebcastOChannelAnchorMessage", "OChannelAnchorMessage").
set("WebcastOChannelModifyMessage", "OChannelModifyMessage").
set("WebcastLinkMicOChannelKickOutMsg", "LinkMicOChannelKickOutMsg").
set("WebcastLinkMicOChannelNotifyMsg", "LinkMicOChannelNotifyMsg").
set("WebcastRoomIntroMessage", "RoomIntroMessage").
set("WebcastGroupShowUserUpdateMessage", "GroupShowUserUpdateMessage");
根据Js中的代码,定义proto文件
定义.proto文件很简单:为要序列化的每个数据结构添加条message,然后为message中的每个字段指定一个名称和类型。
则proto文件内容如下
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;
}
再比如这个 GiftMessage
则proto文件内容如下
message GiftMessage{
repeated Common common=1;
uint64 giftId=2;
uint64 fanTicketCount=3;
uint64 groupCount=4;
uint64 repeatCount=5;
uint64 comboCount=6;
repeated User user=7;
repeated User toUser=8;
int32 repeatEnd = 9;
TextEffect textEffect = 10;
int64 groupId = 11;
int64 incomeTaskgifts = 12;
int64 roomFanTicketCount = 13;
}
所以你想找哪个方法,就按着Js上面改。
定义proto文件
syntax = "proto3";
message test{
repeated Message message =1;
string cursor =2;
uint64 fetchInterval=3;
uint64 now=4;
string internalExt=5;
int32 fetchType=6;
}
message Message{
string method=1;
bytes payload=2;
uint64 msgId=3;
int32 msgType=4;
uint64 offset=5;
int64 rankScore = 7;
int64 topUserNo = 8;
int64 enterType = 9;
int64 action = 10;
string actionDescription = 11;
int64 userId = 12;
string popStr = 14;
}
message WebcastMemberMessage{
repeated Common common=1;
repeated User user=2;
uint64 memberCount=3;
repeated User operator=4;
bool isSetToAdmin=5;
bool isTopUser=6;
}
message WebcastLikeMessage{
repeated Common common=1;
uint64 count=2;
uint64 total=3;
uint64 color=4;
repeated User user=5;
string icon=6;
}
message WebcastChatMessage{
repeated Common common=1;
repeated User user=2;
string content=3;
bool visibleToSender = 4;
string fullScreenTextColor = 6;
}
message WebcastGiftMessage{
repeated Common common=1;
uint64 giftId=2;
uint64 fanTicketCount=3;
uint64 groupCount=4;
uint64 repeatCount=5;
uint64 comboCount=6;
repeated User user=7;
repeated User toUser=8;
}
message WebcastNoticeMessage{
Common common = 1;
string content = 2;
int64 noticeType = 3;
string style = 4;
Text title = 5;
Text violationReason = 6;
Text displayText = 7;
Text tipsTitle = 8;
string tipsUrl = 9;
Text noticeTitle = 10;
Text noticeContent = 11;
int64 noticeTime = 12;
string limitNoticeKey = 13;
}
message Common{
string method=1;
uint64 msgId=2;
uint64 roomId=3;
uint64 createTime=4;
int32 monitor=5;
bool isShowMsg=6;
string describe=7;
repeated DisplayText displayText=8;
uint64 foldType=9;
}
message Text{
string key = 1;
string defaultPattern = 2;
TextFormat defaultFormat = 3;
repeated TextPiece pieces = 4;
}
message TextPiece{
int32 type = 1;
TextFormat format = 2;
string stringValue = 11;
}
message TextFormat{
string color = 1;
bool bold = 2;
bool italic = 3;
int32 weight = 4;
int32 italicAngle = 5;
int32 fontSize = 6;
bool useHeighLightColor = 7;
bool useRemoteClor = 8;
}
message TextPieceUser{
User user = 1;
bool withColon = 2;
}
message DisplayText{
string key=1;
string defaultPattern=2;
}
message User{
message OwnRoom{
repeated int64 roomIds = 1;
repeated string roomIdsStr = 2;
}
message FansGroupInfo{
string listFansGroupUrl = 1;
}
message FansClub{
message FansClubData{
string clubName = 1;
int32 level = 2;
int32 userFansClubStatus = 3;
repeated int64 availableGiftIds = 5;
int64 anchorId = 6;
}
FansClubData data = 1;
map<int32, FansClubData> preferData = 2;
}
message BrotherhoodInfo{
string name = 1;
int64 level = 2;
string fontColor = 4;
}
message UserStats{
int64 id = 1;
string idStr = 2;
int64 followingCount = 3;
int64 followerCount = 4;
int64 recordCount = 5;
int64 totalDuration = 6;
int64 dailyFanTicketCount = 7;
int64 dailyIncome = 8;
int64 itemCount = 9;
int64 favoriteItemCount = 10;
int64 diamondCount = 11;
int64 diamondConsumedCount = 12;
int64 tuwenItemCount = 13;
}
message PoiInfo{
bool isPoiEnabled = 1;
int64 poiId = 2;
string poiName = 3;
string poiIdStr = 4;
}
message AuthenticationInfo{
message AccountTypeInfo{
map<int64, bool> accountTypeMap = 1;
}
string customVerify = 1;
string enterpriseVerifyReason = 2;
repeated int32 levelList = 4;
AccountTypeInfo accountTypeInfo = 10;
}
message XiguaParams{
message UserExtendInfo{
message RocketSchema{
string rSchema = 1;
string rToken = 2;
string downloadUrl = 3;
}
string shareUrl = 1;
string rSchemaUrl = 2;
RocketSchema rocketSchemaInfo = 3;
}
string userAuthInfo = 1;
int64 ugcPublishMediaId = 2;
int64 mediaId = 3;
string authorDesc = 4;
string description = 5;
bool userVerified = 6;
UserExtendInfo userExtendInfo = 7;
}
message AuthorStats{
int64 videoTotalCount = 1;
int64 videoTotalPlayCount = 2;
int64 videoTotalShareCount = 3;
int64 videoTotalSeriesCount = 4;
int64 varietyShowPlayCount = 5;
int64 videoTotalFavoriteCount = 6;
}
message AnchorLevel{
int64 level = 1;
int64 experience = 2;
int64 lowestExperienceThisLevel = 3;
int64 highestExperienceThisLevel = 4;
int64 taskStartExperience = 5;
int64 taskStartTime = 6;
int64 taskDecreaseExperience = 7;
int64 taskTargetExperience = 8;
int64 taskEndTime = 9;
}
message NobleLevelInfo{
int64 nobleLevel = 2;
string nobleName = 4;
int64 expireTime = 5;
repeated string nobleBackgroundColor = 9;
}
message AnchorInfo{
int64 level = 1;
}
message Border {
int64 level = 2;
}
message UserAttr{
bool isMuted = 1;
bool isAdmin = 2;
bool isSuperAdmin = 3;
repeated int32 adminPrivileges = 4;
}
message PayGrade{
message GradeIcon {
int64 iconDiamond = 2;
int64 level = 3;
string levelStr = 4;
}
int64 totalDiamondCount = 1;
string name = 3;
string nextName = 5;
int64 level = 6;
int64 nextDiamond = 8;
int64 nowDiamond = 9;
int64 thisGradeMinDiamond = 10;
int64 thisGradeMaxDiamond = 11;
int64 payDiamondBak = 12;
string gradeDescribe = 13;
int64 screenChatType = 15;
int64 upgradeNeedConsume = 21;
string nextPrivileges = 22;
int64 score = 25;
string gradeBanner = 1001;
}
message FollowInfo{
int64 followingCount = 1;
int64 followerCount = 2;
int64 followStatus = 3;
int64 pushStatus = 4;
}
int64 id = 1;
int64 shortId = 2;
string nickname = 3;
int32 gender = 4;
string signature = 5;
int32 level = 6;
int64 birthday = 7;
string telephone = 8;
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;
FollowInfo followInfo = 22;
PayGrade payGrade = 23;
FansClub fansClub = 24;
Border border = 25;
string specialId = 26;
int64 topVipNo = 31;
UserAttr userAttr = 32;
OwnRoom ownRoom = 33;
int64 payScore = 34;
int64 ticketCount = 35;
AnchorInfo anchorInfo = 36;
int32 linkMicStats = 37;
string displayId = 38;
bool withCommercePermission = 39;
bool withFusionShopEntry = 40;
int64 totalRechargeDiamondCount = 41;
AnchorLevel webcastAnchorLevel = 42;
string verifiedContent = 43;
AuthorStats authorStats = 44;
repeated User topFans = 45;
string secUid = 46;
int32 userRole = 47;
int32 authorizationInfo = 54;
int32 adversaryAuthorizationInfo = 55;
int32 adversaryUserStatus = 58;
string locationCity = 63;
bool allowBeLocated = 1001;
bool allowFindByContacts = 1002;
bool allowOthersDownloadVideo = 1003;
bool allowOthersDownloadWhenSharingVideo = 1004;
bool allowShareShowProfile = 1005;
bool allowShowInGossip = 1006;
bool allowShowMyAction = 1007;
bool allowStrangeComment = 1008;
bool allowUnfollowerComment = 1009;
bool allowUseLinkmic = 1010;
string bgImgUrl = 1013;
string birthdayDescription = 1014;
bool birthdayValid = 1015;
int32 blockStatus = 1016;
int32 commentRestrict = 1017;
string constellation = 1018;
int32 disableIchat = 1019;
int64 enableIchatImg = 1020;
int32 exp = 1021;
int64 fanTicketCount = 1022;
bool foldStrangerChat = 1023;
int64 followStatus = 1024;
bool hotsoonVerified = 1025;
string hotsoonVerifiedReason = 1026;
int32 ichatRestrictType = 1027;
string idStr = 1028;
bool isFollower = 1029;
bool isFollowing = 1030;
bool needProfileGuide = 1031;
int64 payScores = 1032;
bool pushCommentStatus = 1033;
bool pushDigg = 1034;
bool pushFollow = 1035;
bool pushFriendAction = 1036;
bool pushIchat = 1037;
bool pushStatus = 1038;
bool pushVideoPost = 1039;
bool pushVideoRecommend = 1040;
UserStats stats = 1041;
bool verifiedMobile = 1042;
string verifiedReason = 1043;
bool withCarManagementPermission = 1044;
}
python调用
python中想引用xx.proto文件的话,就需要使用protoc.exe把xx.proto文件编译为 xx_pb2.py
.\protoc.exe --python_out=. ./test.proto
编译后的文件为 test_pb2.py
调用示例:
from google.protobuf.json_format import MessageToDict
from test_pb2 import *
import base64
def on_message(data):
danmu_resp = test()
danmu_resp.ParseFromString(data)
Message = MessageToDict(danmu_resp, preserving_proto_field_name=True)
for message in Message["message"]:
method = message["method"]
payload = bytes(base64.b64decode(message["payload"].encode()))
if method == "WebcastMemberMessage":
menber_message = WebcastMemberMessage()
menber_message.ParseFromString(payload)
obj1 = MessageToDict(menber_message, preserving_proto_field_name=True)
print(obj1)
解析和采集源码下载
【温馨提示:此处隐藏内容需要付费订阅后才能查看!】
代码仅供参考学习,切勿用于商业用途,出现问题作者概不负责!