抖音APP 接口分析
1、安装「夜神模拟器」,并安装「抖音短视频」
2、安装「Charles」,配置并开启 SSL Proxy
Charles 免费激活码:https://zhile.io/2017/07/07/charles-proxy-usage-and-license.html
3、配置「夜神模拟器」网络代理
4、测试「Charles」抓包
打开「抖音短视频」,登录个人账号,访问其他用户,「Charles」会记录相关请求
如图所示,请求 Headers 中包含如下信息:
- Accept-Encoding: 固定值「gzip」
- X-SS-REQ-TICKET: 当前时间戳
- sdk-version: 固定值「1」
- Cookie: 个人登录信息,有效期很长
- x-tt-token: 个人登录信息,固定值
- X-Gorgon: 动态生成
- X-Khronos: 动态生成
- Host: 固定值
- Connection:固定值「Keep-Alive」
- User-Agent: 固定值「okhttp/3.10.0.1」
至此,基本的抓包流程走通。
X-Gorgon、X-Khronos 计算
1、反编译「抖音短视频」APK
反编译成功后,用关键词「X-Khronos」搜索全局代码,找到生成 「X-Khronos」的 Package Name、Method Name 和 Args。
2、逆向分析函数
使用相关逆向工具,动态代理签名函数,添加相关参数的日志打印逻辑。经分析,函数输入参数有两个:
- URL:整个 API 请求地址
- Headers:包含
cookie
,accept-encoding
,sdk-version
,user-agent
,x-tt-token
,x-ss-req-ticket
3、编写测试代码
import sys
import time
import requests
from douyin_app.signature import sign
cookie = "***********"
accept_encoding = "gzip"
sdk_version = "1"
user_agent = "okhttp/3.10.0.1"
token = "************"
def get_user_info():
"""
获取用户信息
:return:
"""
ts = str(int(time.time()))
ticket = str(int(round(time.time() * 1000)))
# 用户信息 sec_uid
sec_user_id = 'MS4wLjABAAAAFS6CPjIHAim7TdTQjzevZX7LwfKCIi37PTVmqCpzdU0'
# API 地址
api = 'https://aweme-lq.snssdk.com/aweme/v1/user/?sec_user_id={}&address_book_access=1&retry_type=no_retry&iid=103707347463&device_id=70793717943&ac=wifi&channel=wandoujia_aweme2&aid=1128&app_name=aweme&version_code=790&version_name=7.9.0&device_platform=android&ssmix=a&device_type=R831T&device_brand=OPPO&language=zh&os_api=19&os_version=4.4.2&uuid=864394010882332&openudid=88E9FE8804850000&manifest_version_code=790&resolution=720*1280&dpi=240&update_version_code=7902&_rticket={}&mcc_mnc=46007&ts={}&app_type=normal'.format(sec_user_id, ticket, ts)
headers = {
"cookie": cookie,
"accept-encoding": accept_encoding,
"sdk-version": sdk_version,
"user-agent": user_agent,
"x-tt-token": token,
"x-ss-req-ticket": ticket
}
x_gorgon, x_khronos = sign(api, headers)
headers['X-Gorgon'] = x_gorgon
headers['X-Khronos'] = x_khronos
response = requests.get(api, headers=headers).json()
return response
if __name__ == '__main__':
get_user_info()
获取用户个人信息
至此,X-Gorgon
、X-Khronos
计算流程跑通。
4、验证其他接口
def get_user_post():
"""
获取用户视频列表
:return:
"""
ts = str(int(time.time()))
ticket = str(int(round(time.time() * 1000)))
# 用户 ID
sec_user_id = 'MS4wLjABAAAAFS6CPjIHAim7TdTQjzevZX7LwfKCIi37PTVmqCpzdU0'
# 分页索引,每页20,第二页输入 20
cursor = 0
# API 地址
api = 'https://aweme-lq.snssdk.com/aweme/v1/aweme/post/?max_cursor={}&sec_user_id={}&count=20&retry_type=no_retry&iid=103707347463&device_id=70793717943&ac=wifi&channel=wandoujia_aweme2&aid=1128&app_name=aweme&version_code=790&version_name=7.9.0&device_platform=android&ssmix=a&device_type=R831T&device_brand=OPPO&language=zh&os_api=19&os_version=4.4.2&uuid=864394010882332&openudid=88E9FE8804850000&manifest_version_code=790&resolution=720*1280&dpi=240&update_version_code=7902&_rticket={}&mcc_mnc=46007&ts={}&app_type=normal'.format(str(cursor), sec_user_id, ticket, ts)
headers = {
"cookie": cookie,
"accept-encoding": accept_encoding,
"sdk-version": sdk_version,
"user-agent": user_agent,
"x-tt-token": token,
"x-ss-req-ticket": ticket
}
x_gorgon, x_khronos = sign(api, headers)
headers['X-Gorgon'] = x_gorgon
headers['X-Khronos'] = x_khronos
response = requests.get(api, headers=headers).json()
return response
获取用户视频列表
def get_feed_list():
"""
获取评论列表
:return:
"""
ts = str(int(time.time()))
ticket = str(int(round(time.time() * 1000)))
# 视频ID
aweme_id = '6794011070555098380'
# 分页索引,每页20,第二页输入 20
cursor = 0
# API 地址
api = 'https://aweme-lq.snssdk.com/aweme/v2/comment/list/?aweme_id={}&cursor={}&count=20&insert_ids&address_book_access=1&gps_access=1&forward_page_type=1&openudid=88E9FE8804850000&version_name=7.9.0&ts={}&device_type=R831T&ssmix=a&iid=103707347463&app_type=normal&os_api=19&mcc_mnc=46007&device_id=70793717943&resolution=720*1280&device_brand=OPPO&aid=1128&manifest_version_code=790&app_name=aweme&_rticket={}&os_version=4.4.2&device_platform=android&version_code=790&update_version_code=7902&ac=wifi&dpi=240&uuid=864394010882332&language=zh&channel=wandoujia_aweme2'.format(aweme_id, str(cursor), ts, ticket)
headers = {
"cookie": cookie,
"accept-encoding": accept_encoding,
"sdk-version": sdk_version,
"user-agent": user_agent,
"x-tt-token": token,
"x-ss-req-ticket": ticket
}
x_gorgon, x_khronos = sign(api, headers)
headers['X-Gorgon'] = x_gorgon
headers['X-Khronos'] = x_khronos
response = requests.get(api, headers=headers).json()
return response
获取视频评论列表
网友评论