mirror of
https://github.com/imgyh/tiktok.git
synced 2025-04-27 05:16:34 +08:00
fix(tiktok): 修复失效API,增加X-Bogus
暂时使用https://github.com/Johnserf-Seed/TikTokDownload提供的API来获取X-Bogus
This commit is contained in:
parent
9a6749bffc
commit
53d3b5875e
377
TikTok.py
377
TikTok.py
@ -9,7 +9,7 @@
|
|||||||
@Github :https://github.com/imgyh
|
@Github :https://github.com/imgyh
|
||||||
@Mail :admin@imgyh.com
|
@Mail :admin@imgyh.com
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
Change Log :
|
Change Log : 2023/02/11 修改接口
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@ -20,206 +20,23 @@ import time
|
|||||||
import os
|
import os
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
import TikTokUtils
|
from TikTokUtils import Utils
|
||||||
|
from TikTokUrls import Urls
|
||||||
|
from TikTokResult import Result
|
||||||
|
|
||||||
'''
|
|
||||||
作品详情
|
|
||||||
https://www.iesdouyin.com/aweme/v1/web/aweme/detail/?aweme_id=%s&aid=1128&version_name=23.5.0&device_platform=android&os_version=2333
|
|
||||||
1080p视频
|
|
||||||
https://aweme.snssdk.com/aweme/v1/play/?video_id=%s&ratio=1080p&line=0
|
|
||||||
主页作品
|
|
||||||
https://www.iesdouyin.com/aweme/v1/web/aweme/post/?sec_user_id=%s&count=%s&max_cursor=%s&aid=1128&version_name=23.5.0&device_platform=android&os_version=2333
|
|
||||||
主页喜欢
|
|
||||||
https://www.iesdouyin.com/web/api/v2/aweme/like/?sec_uid=%s&count=%s&max_cursor=%s&aid=1128&version_name=23.5.0&device_platform=android&os_version=2333
|
|
||||||
'''
|
|
||||||
|
|
||||||
class TikTok(object):
|
class TikTok(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
self.urls = Urls()
|
||||||
|
self.utils = Utils()
|
||||||
|
self.result = Result()
|
||||||
self.headers = {
|
self.headers = {
|
||||||
'user-agent': 'Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Mobile Safari/537.36 Edg/87.0.664.66',
|
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36',
|
||||||
'Cookie': 'msToken=%s' % TikTokUtils.generate_random_str(107)
|
'referer':'https://www.douyin.com/',
|
||||||
|
'Cookie': 'msToken=%s;odin_tt=324fb4ea4a89c0c05827e18a1ed9cf9bf8a17f7705fcc793fec935b637867e2a5a9b8168c885554d029919117a18ba69;' % self.utils.generate_random_str(107)
|
||||||
}
|
}
|
||||||
|
|
||||||
# 作者信息
|
|
||||||
self.authorDict = {
|
|
||||||
"avatar_thumb": {
|
|
||||||
"height": "",
|
|
||||||
"uri": "",
|
|
||||||
"url_list": [],
|
|
||||||
"width": ""
|
|
||||||
},
|
|
||||||
"avatar": {
|
|
||||||
"height": "",
|
|
||||||
"uri": "",
|
|
||||||
"url_list": [],
|
|
||||||
"width": ""
|
|
||||||
},
|
|
||||||
"cover_url": {
|
|
||||||
"height": "",
|
|
||||||
"uri": "",
|
|
||||||
"url_list": [],
|
|
||||||
"width": ""
|
|
||||||
},
|
|
||||||
# 喜欢的作品数
|
|
||||||
"favoriting_count": "",
|
|
||||||
# 粉丝数
|
|
||||||
"follower_count": "",
|
|
||||||
# 关注数
|
|
||||||
"following_count": "",
|
|
||||||
# 昵称
|
|
||||||
"nickname": "",
|
|
||||||
# 是否允许下载
|
|
||||||
"prevent_download": "",
|
|
||||||
# 用户 url id
|
|
||||||
"sec_uid": "",
|
|
||||||
# 是否私密账号
|
|
||||||
"secret": "",
|
|
||||||
# 短id
|
|
||||||
"short_id": "",
|
|
||||||
# 签名
|
|
||||||
"signature": "",
|
|
||||||
# 总获赞数
|
|
||||||
"total_favorited": "",
|
|
||||||
# 用户id
|
|
||||||
"uid": "",
|
|
||||||
# 用户自定义唯一id 抖音号
|
|
||||||
"unique_id": "",
|
|
||||||
# 年龄
|
|
||||||
"user_age": "",
|
|
||||||
|
|
||||||
}
|
|
||||||
# 图片信息
|
|
||||||
self.picDict = {
|
|
||||||
"height": "",
|
|
||||||
"mask_url_list": "",
|
|
||||||
"uri": "",
|
|
||||||
"url_list": [],
|
|
||||||
"width": ""
|
|
||||||
}
|
|
||||||
# 音乐信息
|
|
||||||
self.musicDict = {
|
|
||||||
"cover_hd": {
|
|
||||||
"height": "",
|
|
||||||
"uri": "",
|
|
||||||
"url_list": [],
|
|
||||||
"width": ""
|
|
||||||
},
|
|
||||||
"cover_large": {
|
|
||||||
"height": "",
|
|
||||||
"uri": "",
|
|
||||||
"url_list": [],
|
|
||||||
"width": ""
|
|
||||||
},
|
|
||||||
"cover_medium": {
|
|
||||||
"height": "",
|
|
||||||
"uri": "",
|
|
||||||
"url_list": [],
|
|
||||||
"width": ""
|
|
||||||
},
|
|
||||||
"cover_thumb": {
|
|
||||||
"height": "",
|
|
||||||
"uri": "",
|
|
||||||
"url_list": [],
|
|
||||||
"width": ""
|
|
||||||
},
|
|
||||||
# 音乐作者抖音号
|
|
||||||
"owner_handle": "",
|
|
||||||
# 音乐作者id
|
|
||||||
"owner_id": "",
|
|
||||||
# 音乐作者昵称
|
|
||||||
"owner_nickname": "",
|
|
||||||
"play_url": {
|
|
||||||
"height": "",
|
|
||||||
"uri": "",
|
|
||||||
"url_key": "",
|
|
||||||
"url_list": [],
|
|
||||||
"width": ""
|
|
||||||
},
|
|
||||||
# 音乐名字
|
|
||||||
"title": "",
|
|
||||||
}
|
|
||||||
# 视频信息
|
|
||||||
self.videoDict = {
|
|
||||||
"play_addr": {
|
|
||||||
"uri": "",
|
|
||||||
"url_list": "",
|
|
||||||
},
|
|
||||||
"cover_original_scale": {
|
|
||||||
"height": "",
|
|
||||||
"uri": "",
|
|
||||||
"url_list": [],
|
|
||||||
"width": ""
|
|
||||||
},
|
|
||||||
"dynamic_cover": {
|
|
||||||
"height": "",
|
|
||||||
"uri": "",
|
|
||||||
"url_list": [],
|
|
||||||
"width": ""
|
|
||||||
},
|
|
||||||
"origin_cover": {
|
|
||||||
"height": "",
|
|
||||||
"uri": "",
|
|
||||||
"url_list": [],
|
|
||||||
"width": ""
|
|
||||||
},
|
|
||||||
"cover": {
|
|
||||||
"height": "",
|
|
||||||
"uri": "",
|
|
||||||
"url_list": [],
|
|
||||||
"width": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
# 作品信息
|
|
||||||
self.awemeDict = {
|
|
||||||
# 作品创建时间
|
|
||||||
"create_time":"",
|
|
||||||
# awemeType=0 视频, awemeType=1 图集
|
|
||||||
"awemeType": "",
|
|
||||||
# 作品 id
|
|
||||||
"aweme_id": "",
|
|
||||||
# 作者信息
|
|
||||||
"author": self.authorDict,
|
|
||||||
# 作品描述
|
|
||||||
"desc": "",
|
|
||||||
# 图片
|
|
||||||
"images": [],
|
|
||||||
# 音乐
|
|
||||||
"music": self.musicDict,
|
|
||||||
# 视频
|
|
||||||
"video": self.videoDict,
|
|
||||||
# 作品信息统计
|
|
||||||
"statistics": {
|
|
||||||
"admire_count": "",
|
|
||||||
"collect_count": "",
|
|
||||||
"comment_count": "",
|
|
||||||
"digg_count": "",
|
|
||||||
"play_count": "",
|
|
||||||
"share_count": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
# 用户作品信息
|
|
||||||
self.awemeList = []
|
|
||||||
# 直播信息
|
|
||||||
self.liveDict = {
|
|
||||||
# 是否在播
|
|
||||||
"status": "",
|
|
||||||
# 直播标题
|
|
||||||
"title": "",
|
|
||||||
# 观看人数
|
|
||||||
"user_count": "",
|
|
||||||
# 昵称
|
|
||||||
"nickname": "",
|
|
||||||
# sec_uid
|
|
||||||
"sec_uid": "",
|
|
||||||
# 直播间观看状态
|
|
||||||
"display_long": "",
|
|
||||||
# 推流
|
|
||||||
"flv_pull_url": "",
|
|
||||||
# 分区
|
|
||||||
"partition": "",
|
|
||||||
"sub_partition": ""
|
|
||||||
}
|
|
||||||
|
|
||||||
# 从分享链接中提取网址
|
# 从分享链接中提取网址
|
||||||
def getShareLink(self, string):
|
def getShareLink(self, string):
|
||||||
@ -269,97 +86,25 @@ class TikTok(object):
|
|||||||
|
|
||||||
return key_type, key
|
return key_type, key
|
||||||
|
|
||||||
# 将得到的json数据(dataRaw)精简成自己定义的数据(dataNew)
|
|
||||||
# 转换得到的数据
|
|
||||||
def dataConvert(self, awemeType, dataNew, dataRaw):
|
|
||||||
for item in dataNew:
|
|
||||||
try:
|
|
||||||
# 作品创建时间
|
|
||||||
if item == "create_time":
|
|
||||||
dataNew['create_time'] = time.strftime(
|
|
||||||
"%Y-%m-%d %H.%M.%S", time.localtime(dataRaw['create_time']))
|
|
||||||
continue
|
|
||||||
# 设置 awemeType
|
|
||||||
if item == "awemeType":
|
|
||||||
dataNew["awemeType"] = awemeType
|
|
||||||
continue
|
|
||||||
# 当 解析的链接 是图片时
|
|
||||||
if item == "images":
|
|
||||||
if awemeType == 1:
|
|
||||||
for image in dataRaw[item]:
|
|
||||||
for i in image:
|
|
||||||
self.picDict[i] = image[i]
|
|
||||||
# 字典要深拷贝
|
|
||||||
self.awemeDict["images"].append(copy.deepcopy(self.picDict))
|
|
||||||
continue
|
|
||||||
# 当 解析的链接 是视频时
|
|
||||||
if item == "video":
|
|
||||||
if awemeType == 0:
|
|
||||||
self.dataConvert(awemeType, dataNew[item], dataRaw[item])
|
|
||||||
continue
|
|
||||||
# 将小头像放大
|
|
||||||
if item == "avatar":
|
|
||||||
for i in dataNew[item]:
|
|
||||||
if i == "url_list":
|
|
||||||
for j in self.awemeDict["author"]["avatar_thumb"]["url_list"]:
|
|
||||||
dataNew[item][i].append(j.replace("100x100", "1080x1080"))
|
|
||||||
elif i == "uri":
|
|
||||||
dataNew[item][i] = self.awemeDict["author"]["avatar_thumb"][i].replace("100x100",
|
|
||||||
"1080x1080")
|
|
||||||
else:
|
|
||||||
dataNew[item][i] = self.awemeDict["author"]["avatar_thumb"][i]
|
|
||||||
continue
|
|
||||||
|
|
||||||
# 原来的json是[{}] 而我们的是 {}
|
|
||||||
if item == "cover_url":
|
|
||||||
self.dataConvert(awemeType, dataNew[item], dataRaw[item][0])
|
|
||||||
continue
|
|
||||||
|
|
||||||
# 根据 uri 获取 1080p 视频
|
|
||||||
if item == "play_addr":
|
|
||||||
dataNew[item]["uri"] = dataRaw["bit_rate"][0]["play_addr"]["uri"]
|
|
||||||
# 使用 这个api 可以获得1080p
|
|
||||||
dataNew[item]["url_list"] = "https://aweme.snssdk.com/aweme/v1/play/?video_id=%s&ratio=1080p&line=0" \
|
|
||||||
% dataNew[item]["uri"]
|
|
||||||
continue
|
|
||||||
|
|
||||||
# 常规 递归遍历 字典
|
|
||||||
if isinstance(dataNew[item], dict):
|
|
||||||
self.dataConvert(awemeType, dataNew[item], dataRaw[item])
|
|
||||||
else:
|
|
||||||
# 赋值
|
|
||||||
dataNew[item] = dataRaw[item]
|
|
||||||
except Exception as e:
|
|
||||||
print("[ 警告 ]:转换数据时在接口中未找到 %s\r" % (item))
|
|
||||||
|
|
||||||
def clearDict(self, data):
|
|
||||||
for item in data:
|
|
||||||
# 常规 递归遍历 字典
|
|
||||||
if isinstance(data[item], dict):
|
|
||||||
self.clearDict(data[item])
|
|
||||||
elif isinstance(data[item], list):
|
|
||||||
data[item] = []
|
|
||||||
else:
|
|
||||||
data[item] = ""
|
|
||||||
|
|
||||||
# 传入 aweme_id
|
# 传入 aweme_id
|
||||||
# 返回 数据 字典
|
# 返回 数据 字典
|
||||||
def getAwemeInfo(self, aweme_id):
|
def getAwemeInfo(self, aweme_id):
|
||||||
if aweme_id is None:
|
if aweme_id is None:
|
||||||
return None
|
return None
|
||||||
# 官方接口
|
|
||||||
# 旧接口22/12/23失效
|
|
||||||
# jx_url = f'https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids={self.aweme_id[i]}'
|
|
||||||
# 23/01/11
|
|
||||||
# 此ies domian暂时不需要xg参数
|
|
||||||
# 单作品接口返回 'aweme_detail'
|
# 单作品接口返回 'aweme_detail'
|
||||||
# 主页作品接口返回 'aweme_list'->['aweme_detail']
|
# 主页作品接口返回 'aweme_list'->['aweme_detail']
|
||||||
jx_url = f'https://www.iesdouyin.com/aweme/v1/web/aweme/detail/?aweme_id={aweme_id}&aid=1128&version_name=23.5.0&device_platform=android&os_version=2333'
|
jx_url = self.urls.POST_DETAIL + self.utils.getXbogus(
|
||||||
|
url=f'aweme_id={aweme_id}&aid=1128&version_name=23.5.0&device_platform=android&os_version=2333')
|
||||||
|
try:
|
||||||
raw = requests.get(url=jx_url, headers=self.headers).text
|
raw = requests.get(url=jx_url, headers=self.headers).text
|
||||||
datadict = json.loads(raw)
|
datadict = json.loads(raw)
|
||||||
|
except Exception as e:
|
||||||
|
print("[ 错误 ]:接口未返回数据, 请检查后重新运行!\r")
|
||||||
|
return None
|
||||||
|
|
||||||
# 清空self.awemeDict
|
# 清空self.awemeDict
|
||||||
self.clearDict(self.awemeDict)
|
self.result.clearDict(self.result.awemeDict)
|
||||||
|
|
||||||
if datadict['aweme_detail'] is None:
|
if datadict['aweme_detail'] is None:
|
||||||
print('[ 错误 ]:作品不存在, 请检查后重新运行!\r')
|
print('[ 错误 ]:作品不存在, 请检查后重新运行!\r')
|
||||||
@ -374,20 +119,16 @@ class TikTok(object):
|
|||||||
print("[ 警告 ]:接口中未找到 images\r")
|
print("[ 警告 ]:接口中未找到 images\r")
|
||||||
|
|
||||||
# 转换成我们自己的格式
|
# 转换成我们自己的格式
|
||||||
self.dataConvert(awemeType, self.awemeDict, datadict['aweme_detail'])
|
self.result.dataConvert(awemeType, self.result.awemeDict, datadict['aweme_detail'])
|
||||||
|
|
||||||
return self.awemeDict
|
return self.result.awemeDict, datadict
|
||||||
|
|
||||||
# 传入 url 支持 https://www.iesdouyin.com 与 https://v.douyin.com
|
# 传入 url 支持 https://www.iesdouyin.com 与 https://v.douyin.com
|
||||||
# mode : post | like 模式选择 like为用户点赞 post为用户发布
|
# mode : post | like 模式选择 like为用户点赞 post为用户发布
|
||||||
def getUserInfo(self, sec_uid, mode="post", count=35):
|
def getUserInfo(self, sec_uid, mode="post", count=35):
|
||||||
if sec_uid is None:
|
if sec_uid is None:
|
||||||
return None
|
return None
|
||||||
# 旧接口于22/12/23失效
|
|
||||||
# post_url = 'https://www.iesdouyin.com/web/api/v2/aweme/post/?sec_uid=%s&count=35&max_cursor=0&aid=1128&_signature=PDHVOQAAXMfFyj02QEpGaDwx1S&dytk=' % (
|
|
||||||
# self.sec)
|
|
||||||
# 23/1/11
|
|
||||||
# 暂时使用不需要xg的接口
|
|
||||||
max_cursor = 0
|
max_cursor = 0
|
||||||
self.awemeList = []
|
self.awemeList = []
|
||||||
|
|
||||||
@ -395,28 +136,32 @@ class TikTok(object):
|
|||||||
|
|
||||||
while True:
|
while True:
|
||||||
if mode == "post":
|
if mode == "post":
|
||||||
post_url = 'https://www.iesdouyin.com/aweme/v1/web/aweme/post/?sec_user_id=%s&count=%s&max_cursor=%s&aid=1128&version_name=23.5.0&device_platform=android&os_version=2333' % (
|
url = self.urls.USER_POST + self.utils.getXbogus(
|
||||||
sec_uid, count, max_cursor)
|
url=f'sec_user_id={sec_uid}&count={count}&max_cursor={max_cursor}&aid=1128&version_name=23.5.0&device_platform=android&os_version=2333')
|
||||||
elif mode == "like":
|
elif mode == "like":
|
||||||
post_url = 'https://www.iesdouyin.com/web/api/v2/aweme/like/?sec_uid=%s&count=%s&max_cursor=%s&aid=1128&version_name=23.5.0&device_platform=android&os_version=2333' % (
|
url = self.urls.USER_FAVORITE_A + self.utils.getXbogus(
|
||||||
sec_uid, count, max_cursor)
|
url=f'sec_user_id={sec_uid}&count={count}&max_cursor={max_cursor}&aid=1128&version_name=23.5.0&device_platform=android&os_version=2333')
|
||||||
else:
|
else:
|
||||||
print("[ 错误 ]:模式选择错误, 仅支持post和like, 请检查后重新运行!\r")
|
print("[ 错误 ]:模式选择错误, 仅支持post和like, 请检查后重新运行!\r")
|
||||||
return None
|
return None
|
||||||
res = requests.get(url=post_url, headers=self.headers)
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
res = requests.get(url=url, headers=self.headers)
|
||||||
datadict = json.loads(res.text)
|
datadict = json.loads(res.text)
|
||||||
|
except Exception as e:
|
||||||
|
print("[ 错误 ]:接口未返回数据, 请检查后重新运行!\r")
|
||||||
|
return None
|
||||||
|
|
||||||
if not datadict["aweme_list"]:
|
if not datadict["aweme_list"]:
|
||||||
print("[ 错误 ]:未找到数据, 请检查后重新运行!\r")
|
print("[ 错误 ]:未找到数据, 请检查后重新运行!\r")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
for aweme in datadict["aweme_list"]:
|
for aweme in datadict["aweme_list"]:
|
||||||
# 获取 aweme_id 使用这个接口 https://www.iesdouyin.com/aweme/v1/web/aweme/detail/
|
# 获取 aweme_id
|
||||||
aweme_id = aweme["aweme_id"]
|
aweme_id = aweme["aweme_id"]
|
||||||
# 深拷贝 dict 不然list里面全是同样的数据
|
# 深拷贝 dict 不然list里面全是同样的数据
|
||||||
self.awemeList.append(copy.deepcopy(self.getAwemeInfo(aweme_id)))
|
datanew, dataraw = self.getAwemeInfo(aweme_id)
|
||||||
|
self.awemeList.append(copy.deepcopy(datanew))
|
||||||
# time.sleep(0.5)
|
|
||||||
|
|
||||||
# 更新 max_cursor
|
# 更新 max_cursor
|
||||||
max_cursor = datadict["max_cursor"]
|
max_cursor = datadict["max_cursor"]
|
||||||
@ -431,76 +176,79 @@ class TikTok(object):
|
|||||||
|
|
||||||
# web_rid = live_url.replace('https://live.douyin.com/', '')
|
# web_rid = live_url.replace('https://live.douyin.com/', '')
|
||||||
|
|
||||||
live_api = 'https://live.douyin.com/webcast/web/enter/?aid=6383&web_rid=%s' % (web_rid)
|
live_api = 'https://live.douyin.com/webcast/room/web/enter/?aid=6383&device_platform=web&web_rid=%s' % (web_rid)
|
||||||
|
|
||||||
# 必须用这个 headers
|
# 必须用这个 headers
|
||||||
headers = {
|
headers = {
|
||||||
'Cookie': 'msToken=tsQyL2_m4XgtIij2GZfyu8XNXBfTGELdreF1jeIJTyktxMqf5MMIna8m1bv7zYz4pGLinNP2TvISbrzvFubLR8khwmAVLfImoWo3Ecnl_956MgOK9kOBdwM=; odin_tt=6db0a7d68fd2147ddaf4db0b911551e472d698d7b84a64a24cf07c49bdc5594b2fb7a42fd125332977218dd517a36ec3c658f84cebc6f806032eff34b36909607d5452f0f9d898810c369cd75fd5fb15; ttwid=1%7CfhiqLOzu_UksmD8_muF_TNvFyV909d0cw8CSRsmnbr0%7C1662368529%7C048a4e969ec3570e84a5faa3518aa7e16332cfc7fbcb789780135d33a34d94d2'
|
'Cookie': 'msToken=tsQyL2_m4XgtIij2GZfyu8XNXBfTGELdreF1jeIJTyktxMqf5MMIna8m1bv7zYz4pGLinNP2TvISbrzvFubLR8khwmAVLfImoWo3Ecnl_956MgOK9kOBdwM=; odin_tt=6db0a7d68fd2147ddaf4db0b911551e472d698d7b84a64a24cf07c49bdc5594b2fb7a42fd125332977218dd517a36ec3c658f84cebc6f806032eff34b36909607d5452f0f9d898810c369cd75fd5fb15; ttwid=1%7CfhiqLOzu_UksmD8_muF_TNvFyV909d0cw8CSRsmnbr0%7C1662368529%7C048a4e969ec3570e84a5faa3518aa7e16332cfc7fbcb789780135d33a34d94d2'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
response = requests.get(live_api, headers=headers)
|
response = requests.get(live_api, headers=headers)
|
||||||
|
|
||||||
live_json = json.loads(response.text)
|
live_json = json.loads(response.text)
|
||||||
|
except Exception as e:
|
||||||
|
print("[ 错误 ]:接口未返回数据, 请检查后重新运行!\r")
|
||||||
|
return None
|
||||||
|
|
||||||
if live_json == {} or live_json['status_code'] != 0:
|
if live_json == {} or live_json['status_code'] != 0:
|
||||||
print("[ 警告 ]:接口未返回信息\r")
|
print("[ 警告 ]:接口未返回信息\r")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# 清空字典
|
# 清空字典
|
||||||
self.clearDict(self.liveDict)
|
self.result.clearDict(self.result.liveDict)
|
||||||
|
|
||||||
# 是否在播
|
# 是否在播
|
||||||
self.liveDict["status"] = live_json['data']['data'][0]['status']
|
self.result.liveDict["status"] = live_json['data']['data'][0]['status']
|
||||||
|
|
||||||
if self.liveDict["status"] == 4:
|
if self.result.liveDict["status"] == 4:
|
||||||
print('[ 📺 ]:当前直播已结束,正在退出')
|
print('[ 📺 ]:当前直播已结束,正在退出')
|
||||||
return self.liveDict
|
return self.result.liveDict
|
||||||
|
|
||||||
# 直播标题
|
# 直播标题
|
||||||
self.liveDict["title"] = live_json['data']['data'][0]['title']
|
self.result.liveDict["title"] = live_json['data']['data'][0]['title']
|
||||||
|
|
||||||
# 观看人数
|
# 观看人数
|
||||||
self.liveDict["user_count"] = live_json['data']['data'][0]['user_count_str']
|
self.result.liveDict["user_count"] = live_json['data']['data'][0]['user_count_str']
|
||||||
|
|
||||||
# 昵称
|
# 昵称
|
||||||
self.liveDict["nickname"] = live_json['data']['data'][0]['owner']['nickname']
|
self.result.liveDict["nickname"] = live_json['data']['data'][0]['owner']['nickname']
|
||||||
|
|
||||||
# sec_uid
|
# sec_uid
|
||||||
self.liveDict["sec_uid"] = live_json['data']['data'][0]['owner']['sec_uid']
|
self.result.liveDict["sec_uid"] = live_json['data']['data'][0]['owner']['sec_uid']
|
||||||
|
|
||||||
# 直播间观看状态
|
# 直播间观看状态
|
||||||
self.liveDict["display_long"] = live_json['data']['data'][0]['room_view_stats']['display_long']
|
self.result.liveDict["display_long"] = live_json['data']['data'][0]['room_view_stats']['display_long']
|
||||||
|
|
||||||
# 推流
|
# 推流
|
||||||
self.liveDict["flv_pull_url"] = live_json['data']['data'][0]['stream_url']['flv_pull_url']
|
self.result.liveDict["flv_pull_url"] = live_json['data']['data'][0]['stream_url']['flv_pull_url']
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 分区
|
# 分区
|
||||||
self.liveDict["partition"] = live_json['data']['partition_road_map']['partition']['title']
|
self.result.liveDict["partition"] = live_json['data']['partition_road_map']['partition']['title']
|
||||||
self.liveDict["sub_partition"] = live_json['data']['partition_road_map']['sub_partition']['partition'][
|
self.result.liveDict["sub_partition"] = live_json['data']['partition_road_map']['sub_partition']['partition'][
|
||||||
'title']
|
'title']
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.liveDict["partition"] = '无'
|
self.result.liveDict["partition"] = '无'
|
||||||
self.liveDict["sub_partition"] = '无'
|
self.result.liveDict["sub_partition"] = '无'
|
||||||
|
|
||||||
info = '[ 💻 ]:直播间:%s 当前%s 主播:%s 分区:%s-%s\r' % (
|
info = '[ 💻 ]:直播间:%s 当前%s 主播:%s 分区:%s-%s\r' % (
|
||||||
self.liveDict["title"], self.liveDict["display_long"], self.liveDict["nickname"],
|
self.result.liveDict["title"], self.result.liveDict["display_long"], self.result.liveDict["nickname"],
|
||||||
self.liveDict["partition"], self.liveDict["sub_partition"])
|
self.result.liveDict["partition"], self.result.liveDict["sub_partition"])
|
||||||
print(info)
|
print(info)
|
||||||
|
|
||||||
flv = []
|
flv = []
|
||||||
print('[ 🎦 ]:直播间清晰度')
|
print('[ 🎦 ]:直播间清晰度')
|
||||||
for i, f in enumerate(self.liveDict["flv_pull_url"].keys()):
|
for i, f in enumerate(self.result.liveDict["flv_pull_url"].keys()):
|
||||||
print('[ %s ]: %s' % (i, f))
|
print('[ %s ]: %s' % (i, f))
|
||||||
flv.append(f)
|
flv.append(f)
|
||||||
|
|
||||||
rate = int(input('[ 🎬 ]输入数字选择推流清晰度:'))
|
rate = int(input('[ 🎬 ]输入数字选择推流清晰度:'))
|
||||||
|
|
||||||
# 显示清晰度列表
|
# 显示清晰度列表
|
||||||
print('[ %s ]:%s' % (flv[rate], self.liveDict["flv_pull_url"][flv[rate]]))
|
print('[ %s ]:%s' % (flv[rate], self.result.liveDict["flv_pull_url"][flv[rate]]))
|
||||||
|
|
||||||
print('[ 📺 ]:复制链接使用下载工具下载')
|
print('[ 📺 ]:复制链接使用下载工具下载')
|
||||||
return self.liveDict
|
return self.result.liveDict
|
||||||
|
|
||||||
# 来自 https://blog.csdn.net/weixin_43347550/article/details/105248223
|
# 来自 https://blog.csdn.net/weixin_43347550/article/details/105248223
|
||||||
def progressBarDownload(self, url, filepath):
|
def progressBarDownload(self, url, filepath):
|
||||||
@ -531,9 +279,12 @@ class TikTok(object):
|
|||||||
def awemeDownload(self, awemeDict: dict, music=True, cover=True, avatar=True, savePath=os.getcwd()):
|
def awemeDownload(self, awemeDict: dict, music=True, cover=True, avatar=True, savePath=os.getcwd()):
|
||||||
if awemeDict is None:
|
if awemeDict is None:
|
||||||
return
|
return
|
||||||
|
if not os.path.exists(savePath):
|
||||||
|
os.mkdir(savePath)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 使用作品 创建时间+描述 当文件夹
|
# 使用作品 创建时间+描述 当文件夹
|
||||||
file_name = TikTokUtils.replaceStr(awemeDict["create_time"] + awemeDict["desc"])
|
file_name = self.utils.replaceStr(awemeDict["create_time"] + awemeDict["desc"])
|
||||||
aweme_path = os.path.join(savePath, file_name)
|
aweme_path = os.path.join(savePath, file_name)
|
||||||
if not os.path.exists(aweme_path):
|
if not os.path.exists(aweme_path):
|
||||||
os.mkdir(aweme_path)
|
os.mkdir(aweme_path)
|
||||||
@ -577,7 +328,7 @@ class TikTok(object):
|
|||||||
# 下载 音乐
|
# 下载 音乐
|
||||||
if music:
|
if music:
|
||||||
print("[ 提示 ]:正在下载音乐...\r")
|
print("[ 提示 ]:正在下载音乐...\r")
|
||||||
music_name = TikTokUtils.replaceStr(awemeDict["music"]["title"])
|
music_name = self.utils.replaceStr(awemeDict["music"]["title"])
|
||||||
music_path = os.path.join(aweme_path, music_name + ".mp3")
|
music_path = os.path.join(aweme_path, music_name + ".mp3")
|
||||||
|
|
||||||
if os.path.exists(music_path):
|
if os.path.exists(music_path):
|
||||||
@ -632,7 +383,7 @@ class TikTok(object):
|
|||||||
% (aweme["author"]["nickname"], str(ind + 1), len(awemeList)))
|
% (aweme["author"]["nickname"], str(ind + 1), len(awemeList)))
|
||||||
|
|
||||||
self.awemeDownload(aweme, music, cover, avatar, savePath)
|
self.awemeDownload(aweme, music, cover, avatar, savePath)
|
||||||
time.sleep(0.5)
|
# time.sleep(0.5)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -52,8 +52,8 @@ def main():
|
|||||||
tk.userDownload(awemeList=datalist, music=args.music, cover=args.cover, avatar=args.avatar,
|
tk.userDownload(awemeList=datalist, music=args.music, cover=args.cover, avatar=args.avatar,
|
||||||
savePath=args.path)
|
savePath=args.path)
|
||||||
elif key_type == "aweme":
|
elif key_type == "aweme":
|
||||||
datadict = tk.getAwemeInfo(key)
|
datanew, dataraw = tk.getAwemeInfo(key)
|
||||||
tk.awemeDownload(awemeDict=datadict, music=args.music, cover=args.cover, avatar=args.avatar,
|
tk.awemeDownload(awemeDict=datanew, music=args.music, cover=args.cover, avatar=args.avatar,
|
||||||
savePath=args.path)
|
savePath=args.path)
|
||||||
elif key_type == "live":
|
elif key_type == "live":
|
||||||
live_json = tk.getLiveInfo(key)
|
live_json = tk.getLiveInfo(key)
|
||||||
|
272
TikTokResult.py
Normal file
272
TikTokResult.py
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
'''
|
||||||
|
@Description:TikTok.py
|
||||||
|
@Date :2023/02/11 13:06:23
|
||||||
|
@Author :imgyh
|
||||||
|
@version :1.0
|
||||||
|
@Github :https://github.com/imgyh
|
||||||
|
@Mail :admin@imgyh.com
|
||||||
|
-------------------------------------------------
|
||||||
|
Change Log :
|
||||||
|
-------------------------------------------------
|
||||||
|
'''
|
||||||
|
|
||||||
|
import time
|
||||||
|
import copy
|
||||||
|
|
||||||
|
class Result(object):
|
||||||
|
def __init__(self):
|
||||||
|
# 作者信息
|
||||||
|
self.authorDict = {
|
||||||
|
"avatar_thumb": {
|
||||||
|
"height": "",
|
||||||
|
"uri": "",
|
||||||
|
"url_list": [],
|
||||||
|
"width": ""
|
||||||
|
},
|
||||||
|
"avatar": {
|
||||||
|
"height": "",
|
||||||
|
"uri": "",
|
||||||
|
"url_list": [],
|
||||||
|
"width": ""
|
||||||
|
},
|
||||||
|
"cover_url": {
|
||||||
|
"height": "",
|
||||||
|
"uri": "",
|
||||||
|
"url_list": [],
|
||||||
|
"width": ""
|
||||||
|
},
|
||||||
|
# 喜欢的作品数
|
||||||
|
"favoriting_count": "",
|
||||||
|
# 粉丝数
|
||||||
|
"follower_count": "",
|
||||||
|
# 关注数
|
||||||
|
"following_count": "",
|
||||||
|
# 昵称
|
||||||
|
"nickname": "",
|
||||||
|
# 是否允许下载
|
||||||
|
"prevent_download": "",
|
||||||
|
# 用户 url id
|
||||||
|
"sec_uid": "",
|
||||||
|
# 是否私密账号
|
||||||
|
"secret": "",
|
||||||
|
# 短id
|
||||||
|
"short_id": "",
|
||||||
|
# 签名
|
||||||
|
"signature": "",
|
||||||
|
# 总获赞数
|
||||||
|
"total_favorited": "",
|
||||||
|
# 用户id
|
||||||
|
"uid": "",
|
||||||
|
# 用户自定义唯一id 抖音号
|
||||||
|
"unique_id": "",
|
||||||
|
# 年龄
|
||||||
|
"user_age": "",
|
||||||
|
|
||||||
|
}
|
||||||
|
# 图片信息
|
||||||
|
self.picDict = {
|
||||||
|
"height": "",
|
||||||
|
"mask_url_list": "",
|
||||||
|
"uri": "",
|
||||||
|
"url_list": [],
|
||||||
|
"width": ""
|
||||||
|
}
|
||||||
|
# 音乐信息
|
||||||
|
self.musicDict = {
|
||||||
|
"cover_hd": {
|
||||||
|
"height": "",
|
||||||
|
"uri": "",
|
||||||
|
"url_list": [],
|
||||||
|
"width": ""
|
||||||
|
},
|
||||||
|
"cover_large": {
|
||||||
|
"height": "",
|
||||||
|
"uri": "",
|
||||||
|
"url_list": [],
|
||||||
|
"width": ""
|
||||||
|
},
|
||||||
|
"cover_medium": {
|
||||||
|
"height": "",
|
||||||
|
"uri": "",
|
||||||
|
"url_list": [],
|
||||||
|
"width": ""
|
||||||
|
},
|
||||||
|
"cover_thumb": {
|
||||||
|
"height": "",
|
||||||
|
"uri": "",
|
||||||
|
"url_list": [],
|
||||||
|
"width": ""
|
||||||
|
},
|
||||||
|
# 音乐作者抖音号
|
||||||
|
"owner_handle": "",
|
||||||
|
# 音乐作者id
|
||||||
|
"owner_id": "",
|
||||||
|
# 音乐作者昵称
|
||||||
|
"owner_nickname": "",
|
||||||
|
"play_url": {
|
||||||
|
"height": "",
|
||||||
|
"uri": "",
|
||||||
|
"url_key": "",
|
||||||
|
"url_list": [],
|
||||||
|
"width": ""
|
||||||
|
},
|
||||||
|
# 音乐名字
|
||||||
|
"title": "",
|
||||||
|
}
|
||||||
|
# 视频信息
|
||||||
|
self.videoDict = {
|
||||||
|
"play_addr": {
|
||||||
|
"uri": "",
|
||||||
|
"url_list": "",
|
||||||
|
},
|
||||||
|
"cover_original_scale": {
|
||||||
|
"height": "",
|
||||||
|
"uri": "",
|
||||||
|
"url_list": [],
|
||||||
|
"width": ""
|
||||||
|
},
|
||||||
|
"dynamic_cover": {
|
||||||
|
"height": "",
|
||||||
|
"uri": "",
|
||||||
|
"url_list": [],
|
||||||
|
"width": ""
|
||||||
|
},
|
||||||
|
"origin_cover": {
|
||||||
|
"height": "",
|
||||||
|
"uri": "",
|
||||||
|
"url_list": [],
|
||||||
|
"width": ""
|
||||||
|
},
|
||||||
|
"cover": {
|
||||||
|
"height": "",
|
||||||
|
"uri": "",
|
||||||
|
"url_list": [],
|
||||||
|
"width": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# 作品信息
|
||||||
|
self.awemeDict = {
|
||||||
|
# 作品创建时间
|
||||||
|
"create_time": "",
|
||||||
|
# awemeType=0 视频, awemeType=1 图集
|
||||||
|
"awemeType": "",
|
||||||
|
# 作品 id
|
||||||
|
"aweme_id": "",
|
||||||
|
# 作者信息
|
||||||
|
"author": self.authorDict,
|
||||||
|
# 作品描述
|
||||||
|
"desc": "",
|
||||||
|
# 图片
|
||||||
|
"images": [],
|
||||||
|
# 音乐
|
||||||
|
"music": self.musicDict,
|
||||||
|
# 视频
|
||||||
|
"video": self.videoDict,
|
||||||
|
# 作品信息统计
|
||||||
|
"statistics": {
|
||||||
|
"admire_count": "",
|
||||||
|
"collect_count": "",
|
||||||
|
"comment_count": "",
|
||||||
|
"digg_count": "",
|
||||||
|
"play_count": "",
|
||||||
|
"share_count": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# 用户作品信息
|
||||||
|
self.awemeList = []
|
||||||
|
# 直播信息
|
||||||
|
self.liveDict = {
|
||||||
|
# 是否在播
|
||||||
|
"status": "",
|
||||||
|
# 直播标题
|
||||||
|
"title": "",
|
||||||
|
# 观看人数
|
||||||
|
"user_count": "",
|
||||||
|
# 昵称
|
||||||
|
"nickname": "",
|
||||||
|
# sec_uid
|
||||||
|
"sec_uid": "",
|
||||||
|
# 直播间观看状态
|
||||||
|
"display_long": "",
|
||||||
|
# 推流
|
||||||
|
"flv_pull_url": "",
|
||||||
|
# 分区
|
||||||
|
"partition": "",
|
||||||
|
"sub_partition": ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# 将得到的json数据(dataRaw)精简成自己定义的数据(dataNew)
|
||||||
|
# 转换得到的数据
|
||||||
|
def dataConvert(self, awemeType, dataNew, dataRaw):
|
||||||
|
for item in dataNew:
|
||||||
|
try:
|
||||||
|
# 作品创建时间
|
||||||
|
if item == "create_time":
|
||||||
|
dataNew['create_time'] = time.strftime(
|
||||||
|
"%Y-%m-%d %H.%M.%S", time.localtime(dataRaw['create_time']))
|
||||||
|
continue
|
||||||
|
# 设置 awemeType
|
||||||
|
if item == "awemeType":
|
||||||
|
dataNew["awemeType"] = awemeType
|
||||||
|
continue
|
||||||
|
# 当 解析的链接 是图片时
|
||||||
|
if item == "images":
|
||||||
|
if awemeType == 1:
|
||||||
|
for image in dataRaw[item]:
|
||||||
|
for i in image:
|
||||||
|
self.picDict[i] = image[i]
|
||||||
|
# 字典要深拷贝
|
||||||
|
self.awemeDict["images"].append(copy.deepcopy(self.picDict))
|
||||||
|
continue
|
||||||
|
# 当 解析的链接 是视频时
|
||||||
|
if item == "video":
|
||||||
|
if awemeType == 0:
|
||||||
|
self.dataConvert(awemeType, dataNew[item], dataRaw[item])
|
||||||
|
continue
|
||||||
|
# 将小头像放大
|
||||||
|
if item == "avatar":
|
||||||
|
for i in dataNew[item]:
|
||||||
|
if i == "url_list":
|
||||||
|
for j in self.awemeDict["author"]["avatar_thumb"]["url_list"]:
|
||||||
|
dataNew[item][i].append(j.replace("100x100", "1080x1080"))
|
||||||
|
elif i == "uri":
|
||||||
|
dataNew[item][i] = self.awemeDict["author"]["avatar_thumb"][i].replace("100x100",
|
||||||
|
"1080x1080")
|
||||||
|
else:
|
||||||
|
dataNew[item][i] = self.awemeDict["author"]["avatar_thumb"][i]
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 原来的json是[{}] 而我们的是 {}
|
||||||
|
if item == "cover_url":
|
||||||
|
self.dataConvert(awemeType, dataNew[item], dataRaw[item][0])
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 根据 uri 获取 1080p 视频
|
||||||
|
if item == "play_addr":
|
||||||
|
dataNew[item]["uri"] = dataRaw["bit_rate"][0]["play_addr"]["uri"]
|
||||||
|
# 使用 这个api 可以获得1080p
|
||||||
|
dataNew[item]["url_list"] = "https://aweme.snssdk.com/aweme/v1/play/?video_id=%s&ratio=1080p&line=0" \
|
||||||
|
% dataNew[item]["uri"]
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 常规 递归遍历 字典
|
||||||
|
if isinstance(dataNew[item], dict):
|
||||||
|
self.dataConvert(awemeType, dataNew[item], dataRaw[item])
|
||||||
|
else:
|
||||||
|
# 赋值
|
||||||
|
dataNew[item] = dataRaw[item]
|
||||||
|
except Exception as e:
|
||||||
|
print("[ 警告 ]:转换数据时在接口中未找到 %s\r" % (item))
|
||||||
|
|
||||||
|
def clearDict(self, data):
|
||||||
|
for item in data:
|
||||||
|
# 常规 递归遍历 字典
|
||||||
|
if isinstance(data[item], dict):
|
||||||
|
self.clearDict(data[item])
|
||||||
|
elif isinstance(data[item], list):
|
||||||
|
data[item] = []
|
||||||
|
else:
|
||||||
|
data[item] = ""
|
59
TikTokTest.py
Normal file
59
TikTokTest.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
'''
|
||||||
|
@Description:TikTok.py
|
||||||
|
@Date :2023/02/11 13:06:23
|
||||||
|
@Author :imgyh
|
||||||
|
@version :1.0
|
||||||
|
@Github :https://github.com/imgyh
|
||||||
|
@Mail :admin@imgyh.com
|
||||||
|
-------------------------------------------------
|
||||||
|
Change Log :
|
||||||
|
-------------------------------------------------
|
||||||
|
'''
|
||||||
|
|
||||||
|
from TikTok import TikTok
|
||||||
|
|
||||||
|
def getAwemeInfo():
|
||||||
|
share_link_video = "3.56 uSy:/ 复制打开抖音,看看【小透明的作品】没有女朋友就用我的吧哈哈哈哈 # 表情包锁屏 https://v.douyin.com/BugmVVD/"
|
||||||
|
share_link_pic = "8.20 MJI:/ 复制打开抖音,看看【舍溪的图文作品】我又来放图集啦~还有你们要的小可爱大图也放啦~# ... https://v.douyin.com/BugrFTN/"
|
||||||
|
tk = TikTok()
|
||||||
|
|
||||||
|
url = tk.getShareLink(share_link_pic)
|
||||||
|
key_type, key = tk.getKey(url)
|
||||||
|
datanew, dataraw = tk.getAwemeInfo(key)
|
||||||
|
print(datanew)
|
||||||
|
|
||||||
|
def getUserInfo():
|
||||||
|
share_link_post = "1- 长按复制此条消息,打开抖音搜索,查看TA的更多作品。 https://v.douyin.com/BupCppt/"
|
||||||
|
share_link_like = "2- 长按复制此条消息,打开抖音搜索,查看TA的更多作品。 https://v.douyin.com/BusJrfr/"
|
||||||
|
tk = TikTok()
|
||||||
|
|
||||||
|
url = tk.getShareLink(share_link_like)
|
||||||
|
key_type, key = tk.getKey(url)
|
||||||
|
awemeList = tk.getUserInfo(key, mode="like", count=35)
|
||||||
|
print(awemeList)
|
||||||
|
|
||||||
|
def getLiveInfo():
|
||||||
|
live_link = "https://live.douyin.com/40768897856"
|
||||||
|
tk = TikTok()
|
||||||
|
|
||||||
|
url = tk.getShareLink(live_link)
|
||||||
|
key_type, key = tk.getKey(url)
|
||||||
|
live_json = tk.getLiveInfo(key)
|
||||||
|
print(live_json)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# getAwemeInfo()
|
||||||
|
# getUserInfo()
|
||||||
|
getLiveInfo()
|
||||||
|
pass
|
||||||
|
# 视频
|
||||||
|
# python TikTokCommand.py -l https://v.douyin.com/BugmVVD/ -p /mnt/c/project/test1
|
||||||
|
# 图集
|
||||||
|
# python TikTokCommand.py -l https://v.douyin.com/BugrFTN/ -p /mnt/c/project/test2
|
||||||
|
# 主页作品
|
||||||
|
# python TikTokCommand.py -l https://v.douyin.com/BupCppt/ -p /mnt/c/project/test3
|
||||||
|
# 主页喜欢
|
||||||
|
# python TikTokCommand.py -l https://v.douyin.com/BusJrfr/ -p /mnt/c/project/test4 -M like
|
80
TikTokUrls.py
Normal file
80
TikTokUrls.py
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
'''
|
||||||
|
@Description:TikTok.py
|
||||||
|
@Date :2023/02/11 13:06:23
|
||||||
|
@Author :imgyh
|
||||||
|
@version :1.0
|
||||||
|
@Github :https://github.com/imgyh
|
||||||
|
@Mail :admin@imgyh.com
|
||||||
|
-------------------------------------------------
|
||||||
|
Change Log :
|
||||||
|
-------------------------------------------------
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
class Urls(object):
|
||||||
|
def __init__(self):
|
||||||
|
# https://langyue.cc/APIdocV1.0.html
|
||||||
|
######################################### WEB #########################################
|
||||||
|
# 首页推荐
|
||||||
|
self.TAB_FEED = 'https://www.douyin.com/aweme/v1/web/tab/feed/?'
|
||||||
|
|
||||||
|
# 用户短信息(给多少个用户secid就返回多少的用户信息)
|
||||||
|
self.USER_SHORT_INFO = 'https://www.douyin.com/aweme/v1/web/im/user/info/?'
|
||||||
|
|
||||||
|
# 用户详细信息
|
||||||
|
self.USER_DETAIL = 'https://www.douyin.com/aweme/v1/web/user/profile/other/?'
|
||||||
|
|
||||||
|
# 用户作品
|
||||||
|
self.USER_POST = 'https://www.douyin.com/aweme/v1/web/aweme/post/?'
|
||||||
|
|
||||||
|
# 作品信息
|
||||||
|
self.POST_DETAIL = 'https://www.douyin.com/aweme/v1/web/aweme/detail/?'
|
||||||
|
|
||||||
|
# 用户喜欢A
|
||||||
|
self.USER_FAVORITE_A = 'https://www.douyin.com/aweme/v1/web/aweme/favorite/?'
|
||||||
|
|
||||||
|
# 用户喜欢B
|
||||||
|
self.USER_FAVORITE_B = 'https://www.iesdouyin.com/web/api/v2/aweme/like/?'
|
||||||
|
|
||||||
|
# 用户历史
|
||||||
|
self.USER_HISTORY = 'https://www.douyin.com/aweme/v1/web/history/read/?'
|
||||||
|
|
||||||
|
# 用户收藏
|
||||||
|
self.USER_COLLECTION = 'https://www.douyin.com/aweme/v1/web/aweme/listcollection/?'
|
||||||
|
|
||||||
|
# 用户评论
|
||||||
|
self.COMMENT = 'https://www.douyin.com/aweme/v1/web/comment/list/?'
|
||||||
|
|
||||||
|
# 首页朋友作品
|
||||||
|
self.FRIEND_FEED = 'https://www.douyin.com/aweme/v1/web/familiar/feed/?'
|
||||||
|
|
||||||
|
# 关注用户作品
|
||||||
|
self.FOLLOW_FEED = 'https://www.douyin.com/aweme/v1/web/follow/feed/?'
|
||||||
|
|
||||||
|
# X-Bogus Path
|
||||||
|
self.GET_XB_PATH = 'http://47.115.200.238/xg/path?url='
|
||||||
|
|
||||||
|
# X-Bogus Dict
|
||||||
|
self.GET_XB_DICT = 'http://47.115.200.238/xg/dict/?params='
|
||||||
|
|
||||||
|
# X-Bogus Login
|
||||||
|
self.GET_XB_LOGIN = 'http://47.115.200.238/login'
|
||||||
|
|
||||||
|
# X-Bogus Register
|
||||||
|
self.GET_XB_REGISTER = 'http://47.115.200.238/register'
|
||||||
|
|
||||||
|
# X-Bogus Token
|
||||||
|
self.GET_XB_TOKEN = 'http://47.115.200.238/token'
|
||||||
|
#######################################################################################
|
||||||
|
|
||||||
|
######################################### APP #########################################
|
||||||
|
# X-Gorgon Path
|
||||||
|
self.GET_XG_LOGIN = 'http://47.115.200.238/xog/path?url='
|
||||||
|
|
||||||
|
#######################################################################################
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
Urls()
|
@ -15,9 +15,17 @@ Change Log :
|
|||||||
|
|
||||||
import random
|
import random
|
||||||
import re
|
import re
|
||||||
|
from urllib.parse import urlencode, unquote
|
||||||
|
import json
|
||||||
|
import requests
|
||||||
|
from TikTokUrls import Urls
|
||||||
|
|
||||||
|
|
||||||
def generate_random_str(randomlength=16):
|
class Utils(object):
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def generate_random_str(self, randomlength=16):
|
||||||
"""
|
"""
|
||||||
根据传入长度产生随机字符串
|
根据传入长度产生随机字符串
|
||||||
"""
|
"""
|
||||||
@ -28,8 +36,7 @@ def generate_random_str(randomlength=16):
|
|||||||
random_str += base_str[random.randint(0, length)]
|
random_str += base_str[random.randint(0, length)]
|
||||||
return random_str
|
return random_str
|
||||||
|
|
||||||
|
def replaceStr(self, filenamestr: str):
|
||||||
def replaceStr(filenamestr: str):
|
|
||||||
"""
|
"""
|
||||||
替换非法字符,缩短字符长度,使其能成为文件名
|
替换非法字符,缩短字符长度,使其能成为文件名
|
||||||
"""
|
"""
|
||||||
@ -44,6 +51,35 @@ def replaceStr(filenamestr: str):
|
|||||||
# 去除前后空格
|
# 去除前后空格
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def getXbogus(self, url, cookie=None, referer="https://www.douyin.com/"):
|
||||||
|
urls = Urls()
|
||||||
|
headers = {
|
||||||
|
"cookie": cookie,
|
||||||
|
"referer": referer,
|
||||||
|
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36"
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
if isinstance(url, dict):
|
||||||
|
params = eval(unquote(url, 'utf-8'))
|
||||||
|
url = urlencode(params, safe="=")
|
||||||
|
response = json.loads(requests.post(
|
||||||
|
urls.GET_XB_DICT + url,
|
||||||
|
headers=headers).text)
|
||||||
|
if isinstance(url, str):
|
||||||
|
url = url.replace('&', '%26')
|
||||||
|
response = json.loads(requests.post(
|
||||||
|
urls.GET_XB_PATH + url,
|
||||||
|
headers=headers).text)
|
||||||
|
else:
|
||||||
|
print('[ 提示 ]:传入的参数有误')
|
||||||
|
except Exception as e:
|
||||||
|
print('[ 错误 ]:%s' % e)
|
||||||
|
|
||||||
|
params = response["result"][0]["paramsencode"]
|
||||||
|
xb = response["result"][0]["X-Bogus"]["0"]
|
||||||
|
# print('[ 调试 ]:%s' % self.params)
|
||||||
|
return params #, xb
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
pass
|
pass
|
||||||
|
@ -22,8 +22,8 @@ def work(share_link):
|
|||||||
|
|
||||||
url = tk.getShareLink(share_link)
|
url = tk.getShareLink(share_link)
|
||||||
key_type, key = tk.getKey(url)
|
key_type, key = tk.getKey(url)
|
||||||
datadict = tk.getAwemeInfo(key)
|
datanew, dataraw = tk.getAwemeInfo(key)
|
||||||
return datadict
|
return datanew
|
||||||
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user