Add kuaishou live record

This commit is contained in:
ihmily 2023-08-04 06:57:26 +08:00
parent 0acb7a5562
commit e3d4e95f36
5 changed files with 137 additions and 123 deletions

View File

@ -25,13 +25,15 @@
- 运行主文件main.py启动程序
- 在config文件夹内的配置文件中对录制进行配置以及添加录制直播间地址
- 录制需要使用到PC端直播间页面的Cookie请先在config.ini配置文件中添加后再进行录制
- 注意事项① 录制使用到了ffmpeg如果没有则无法进行录制
- 注意事项① 录制使用到了ffmpeg如果没有则无法进行录制请将ffmpeg.exe放置运行文件同个文件夹
- 注意事项② 录制Tiktok时需要使用vpn代理请先在配置文件中设置开启代理并添加proxy_addr
- 注意事项③ 如果电脑开启了全局或者规则代理可不用添加proxy_addr参数值但仍需在config.ini配置文件中设置开启代理
- 抖音app端直播间分享地址和网页端长地址都能正常进行录制尽量用长链接避免因短链接转换失效导致不能正常录制Tiktok直播间地址目前只支持一种
- 注意事项④不知道是不是ffmpeg的原因测试时在Pycharm中运行进行直播录制录制出来的视频无法正常播放而在命令控制台DOS界面运行代码录制出来的视频可正常播放这点请注意别误认为不能录制。
 
抖音app端直播间分享地址和网页端长地址都能正常进行录制尽量用长链接避免因短链接转换失效导致不能正常录制Tiktok和快手直播间地址目前只支持一种。
抖音直播间链接示例:
```
@ -55,16 +57,25 @@ https://www.tiktok.com/@bougiebulliesandbirds/live
请求示例https://hmily.vip/api/dy/live/?url=https://live.douyin.com/573716250978
(只支持抖音Tiktok的没写)
短地址转换长地址https://hmily.vip/api/dy/live/convert?url=https://v.douyin.com/iQLgKSj/
本测试API只写了抖音的
 
## ❤️贡献者
   [![Hmily](https://github.com/ihmily.png?size=50)](https://github.com/ihmily)
 
## 提交日志
 
- 20230804
- 新增了快手直播录制,优化了部分代码
- 20230803
- 通宵更新 一直熬夜一直爽
- 通宵更新
- 新增了国际版抖音Tiktok的直播录制去除冗余 简化了部分代码
- 20230724
@ -73,6 +84,6 @@ https://www.tiktok.com/@bougiebulliesandbirds/live
 
## 有问题可以提issue 或 参与pr后续我会在这里不断更新其他直播平台的录制 欢迎给个star
## 有问题可以提issue 或 参与pr后续我会在这里不断更新其他直播平台的录制 欢迎给个Star
####

View File

@ -1,3 +1,2 @@
https://live.douyin.com/326500301367
https://live.douyin.com/466747346712
https://live.douyin.com/973349577278
https://live.kuaishou.com/u/yall1102

View File

@ -15,7 +15,5 @@ ts录制完成后自动增加生成mp4格式 = 否
ts录制完成后自动增加生成m4a格式 =
追加格式后删除原文件 =
生成时间文件 =
是否显示浏览器 =
仅用浏览器录制 =
cookies不可为空 = ttwid=1%7CB1qls3GdnZhUov9o2NxOMxxYS2ff6OSvEWbv0ytbES4%7C1680522049%7C280d802d6d478e3e78d0c807f7c487e7ffec0ae4e5fdd6a0fe74c3c6af149511; my_rd=1; passport_csrf_token=3ab34460fa656183fccfb904b16ff742; passport_csrf_token_default=3ab34460fa656183fccfb904b16ff742; d_ticket=9f562383ac0547d0b561904513229d76c9c21; n_mh=hvnJEQ4Q5eiH74-84kTFUyv4VK8xtSrpRZG1AhCeFNI; store-region=cn-fj; store-region-src=uid; LOGIN_STATUS=1; __security_server_data_status=1; FORCE_LOGIN=%7B%22videoConsumedRemainSeconds%22%3A180%7D; pwa2=%223%7C0%7C3%7C0%22; download_guide=%223%2F20230729%2F0%22; volume_info=%7B%22isUserMute%22%3Afalse%2C%22isMute%22%3Afalse%2C%22volume%22%3A0.6%7D; strategyABtestKey=%221690824679.923%22; stream_recommend_feed_params=%22%7B%5C%22cookie_enabled%5C%22%3Atrue%2C%5C%22screen_width%5C%22%3A1536%2C%5C%22screen_height%5C%22%3A864%2C%5C%22browser_online%5C%22%3Atrue%2C%5C%22cpu_core_num%5C%22%3A8%2C%5C%22device_memory%5C%22%3A8%2C%5C%22downlink%5C%22%3A10%2C%5C%22effective_type%5C%22%3A%5C%224g%5C%22%2C%5C%22round_trip_time%5C%22%3A150%7D%22; VIDEO_FILTER_MEMO_SELECT=%7B%22expireTime%22%3A1691443863751%2C%22type%22%3Anull%7D; home_can_add_dy_2_desktop=%221%22; __live_version__=%221.1.1.2169%22; device_web_cpu_core=8; device_web_memory_size=8; xgplayer_user_id=346045893336; csrf_session_id=2e00356b5cd8544d17a0e66484946f28; odin_tt=724eb4dd23bc6ffaed9a1571ac4c757ef597768a70c75fef695b95845b7ffcd8b1524278c2ac31c2587996d058e03414595f0a4e856c53bd0d5e5f56dc6d82e24004dc77773e6b83ced6f80f1bb70627; __ac_nonce=064caded4009deafd8b89; __ac_signature=_02B4Z6wo00f01HLUuwwAAIDBh6tRkVLvBQBy9L-AAHiHf7; ttcid=2e9619ebbb8449eaa3d5a42d8ce88ec835; webcast_leading_last_show_time=1691016922379; webcast_leading_total_show_times=1; webcast_local_quality=sd; live_can_add_dy_2_desktop=%221%22; msToken=1JDHnVPw_9yTvzIrwb7cQj8dCMNOoesXbA_IooV8cezcOdpe4pzusZE7NB7tZn9TBXPr0ylxmv-KMs5rqbNUBHP4P7VBFUu0ZAht_BEylqrLpzgt3y5ne_38hXDOX8o=; msToken=jV_yeN1IQKUd9PlNtpL7k5vthGKcHo0dEh_QPUQhr8G3cuYv-Jbb4NnIxGDmhVOkZOCSihNpA2kvYtHiTW25XNNX_yrsv5FN8O6zm3qmCIXcEe0LywLn7oBO2gITEeg=; tt_scid=mYfqpfbDjqXrIGJuQ7q-DlQJfUSG51qG.KUdzztuGP83OjuVLXnQHjsz-BRHRJu4e986

186
main.py
View File

@ -4,9 +4,9 @@
Author: Hmily
Github: https://github.com/ihmily
Date: 2023-07-17 23:52:05
Update: 2023-08-03 08:06:43
Update: 2023-08-04 06:30:00
Copyright (c) 2023 by Hmily, All Rights Reserved.
Function: Record douyin and titok live stream.
Function: Record live stream video.
"""
import random
@ -55,8 +55,9 @@ name_list = []
firstRunOtherLine = True
live_list = []
not_record_list = []
start5 = datetime.datetime.now()
start5_time = datetime.datetime.now()
global_proxy = False
recording_time_list={}
headers = {
'User-Agent': 'Mozilla/5.0 (Linux; Android 11; SAMSUNG SM-G973U) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/14.2 Chrome/87.0.4280.141 Mobile Safari/537.36'
}
@ -66,13 +67,15 @@ backup_dir = './backup_config'
encoding = 'utf-8-sig'
rstr = r"[\/\\\:\*\?\"\<\>\|&u]"
ffmpeg_path = "ffmpeg" # ffmpeg文件路径
default_path = os.getcwd()
# --------------------------用到的函数-------------------------------------
def display_info():
# TODO: 显示当前录制配置信息
global start5
global start5_time
global recording_time_list
time.sleep(5)
while True:
try:
@ -85,25 +88,22 @@ def display_info():
print("配置文件里,直播保存路径并不存在,请重新输入一个正确的路径.或留空表示当前目录,按回车退出")
input("程序结束")
os._exit(0)
if use_proxy:
is_use_proxy=''
else:
print("视频保存路径: " + video_save_path, end=" | ")
pass
else:
print("视频保存路径: 当前目录", end=" | ")
is_use_proxy = ''
print(f"是否开启代理录制: {is_use_proxy}", end=" | ")
if Splitvideobysize:
print("TS录制分段开启录制分段大小为 %d M" % Splitsize, end=" | ")
if only_browser:
print("浏览器检测录制", end=" | ")
else:
print("Cookies录制", end=" | ")
print("录制视频质量为: " + str(video_quality), end=" | ")
print("录制视频格式为: " + str(video_save_type), end=" | ")
print("目前瞬时错误数为: " + str(warning_count), end=" | ")
nowdate = time.strftime("%H:%M:%S", time.localtime())
print(nowdate)
print(f"当前时间: {nowdate}")
if len(recording) == 0 and len(unrecording) == 0:
time.sleep(5)
@ -111,17 +111,19 @@ def display_info():
print("")
continue
else:
now_time = datetime.datetime.now()
if len(recording) > 0:
print("x" * 60)
NoRepeatrecording = list(set(recording))
print("正在录制{}个直播: ".format(str(len(NoRepeatrecording))))
print(f"正在录制{len(NoRepeatrecording)}个直播: ")
for recording_live in NoRepeatrecording:
print(recording_live + " 正在录制中")
end = datetime.datetime.now()
print('总共录制时间: ' + str(end - start5))
have_record_time=now_time-recording_time_list[recording_live]
print(f"{recording_live} 正在录制中 "+str(have_record_time).split('.')[0])
# print('\n本软件已运行'+str(now_time - start5_time).split('.')[0])
print("x" * 60)
else:
start5 = datetime.datetime.now()
start5_time = now_time
except Exception as e:
print("错误信息644:" + str(e) + "\r\n发生错误的行数: "+str(e.__traceback__.tb_lineno))
logger.warning("错误信息: " + str(e) + " 发生错误的行数: " + str(e.__traceback__.tb_lineno))
@ -245,13 +247,14 @@ def get_douyin_stream_url(json_data):
roomInfo = roomStore['roomInfo']
anchor_name = roomInfo['anchor']['nickname']
data.append(anchor_name)
status=4
# 获取直播间状态
if 'room' in roomInfo:
status = roomInfo["room"]["status"] # 直播状态2是正在直播.4是未开播
if status == 4:
data = [anchor_name, status, '', '']
data = [anchor_name, False, '', '']
else:
is_login = json_data['app']['odin']['user_is_login']
stream_url = roomInfo['room']['stream_url']
# flv视频流链接
flv_url_list = stream_url['flv_pull_url']
@ -272,7 +275,7 @@ def get_douyin_stream_url(json_data):
m3u8_url = m3u8_url_list["SD2"]
flv_url = flv_url_list["SD2"]
data = [anchor_name, status, m3u8_url, flv_url]
data = [anchor_name, True, m3u8_url, flv_url]
return data
def get_tiktok_stream_url(json_data):
@ -286,7 +289,7 @@ def get_tiktok_stream_url(json_data):
status = LiveRoom['user']["status"] # 直播状态2是正在直播.4是未开播
if status == 4:
data = [anchor_name, status, '', '']
data = [anchor_name, False, '', '']
else:
# 画质从高到低origin>uhd>sd>sd>ld
# {origin:'原画质或蓝光',uhd:'1080P或720P',sd:'540P或480P',ld:'360P标清'}
@ -308,16 +311,43 @@ def get_tiktok_stream_url(json_data):
# 注意这里要将链接改为http协议否则无法使用ffmpeg录制原因是代理大都是http
m3u8_url = re.sub("https", "http", m3u8_url)
flv_url = re.sub("https", "http", flv_url)
data = [anchor_name, status, m3u8_url, flv_url]
data = [anchor_name, True, m3u8_url, flv_url]
return data
def get_kuaishou_stream_url(json_data):
# TODO: 获取快手直播源地址
data = [] # 定义一个返回数据列表
liveroom = json_data['liveroom']
anchor_name = liveroom['author']['name']
data.append(anchor_name)
# 获取直播间状态
status = liveroom['isLiving'] # 直播状态True是正在直播.False是未开播
if not status:
data = [anchor_name, False, '', '']
else:
stream_data = liveroom['liveStream']['playUrls'][0]['adaptationSet']['representation']
# stream_data数组中索引从小到大分别是高清、超清、蓝光4M、蓝光8M (每个直播间不一样)
if video_quality == "原画" or video_quality == "蓝光":
flv_url = stream_data[-1]['url']
elif video_quality == "超清":
flv_url = stream_data[-2]['url']
elif video_quality == "高清":
flv_url = stream_data[1]['url']
elif video_quality == "标清":
flv_url = stream_data[0]['url']
data = [anchor_name, True, flv_url, flv_url] # 快手只有flv视频流
return data
def start_record(line, count_variable=-1):
global warning_count
global video_save_path
global live_list
global not_record_list
global need_proxy_url_list
global recording_time_list
while True:
try:
record_finished = False
@ -358,6 +388,11 @@ def start_record(line, count_variable=-1):
json_data = get_tiktok_stream_data(record_url,proxy_addr)
port_info = get_tiktok_stream_url(json_data)
elif record_url.find("https://live.kuaishou.com/") > -1:
with semaphore:
json_data = get_kuaishou_stream_data(record_url)
port_info = get_kuaishou_stream_url(json_data)
# print("端口信息:" + str(port_info))
# port_info=['主播名','状态码','m3u8地址','flv地址']
if len(port_info) != 4:
@ -380,7 +415,7 @@ def start_record(line, count_variable=-1):
Runonce = True
# 判断状态码 如果是2则正在直播如果是4则未在直播
if port_info[1] != 2:
if not port_info[1]:
print(f"序号{count_variable} {port_info[0]} 等待直播... ")
anchor_name = port_info[0]
else:
@ -402,11 +437,13 @@ def start_record(line, count_variable=-1):
live_list.append(anchor_name)
now = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime(time.time()))
try:
full_path = f'{default_path}/{anchor_name}'
if len(video_save_path) > 0:
if video_save_path[-1] != "/":
video_save_path = video_save_path + "/"
if not os.path.exists(video_save_path + anchor_name):
os.makedirs(video_save_path + anchor_name)
full_path = f'{video_save_path}/{anchor_name}'
if not os.path.exists(full_path):
os.makedirs(full_path)
else:
if not os.path.exists(anchor_name):
os.makedirs('./' + anchor_name)
@ -415,10 +452,9 @@ def start_record(line, count_variable=-1):
print("路径错误信息708: " + str(e) + " 发生错误的行数: " + str(e.__traceback__.tb_lineno))
logger.warning("错误信息: " + str(e) + " 发生错误的行数: " + str(e.__traceback__.tb_lineno))
if not os.path.exists(video_save_path + anchor_name):
if not os.path.exists(full_path):
print("保存路径不存在,不能生成录制.请避免把本程序放在c盘,桌面,下载文件夹,qq默认传输目录.请重新检查设置")
video_save_path = ""
default_path = os.getcwd()
print(f"因为配置文件的路径错误,本次录制在程序目录 {default_path}")
@ -452,27 +488,23 @@ def start_record(line, count_variable=-1):
]
# 添加代理参数
if 'douyin' not in real_url:
if 'tiktok' in real_url:
if use_proxy and proxy_addr != '':
# os.environ["http_proxy"] = proxy_addr
ffmpeg_command.insert(1, "-http_proxy")
ffmpeg_command.insert(2, proxy_addr)
recording.add(f'序号{count_variable} ' + anchor_name)
record_name=f'序号{count_variable} ' + anchor_name
recording.add(record_name)
start_record_time = datetime.datetime.now()
recording_time_list[record_name] = start_record_time
rec_info=f"\r{anchor_name} 录制视频中: {full_path}"
filename_short = full_path + '/' + anchor_name + '_' + now
if video_save_type == "FLV":
filename = anchor_name + '_' + now + '.flv'
if len(video_save_path) == 0:
print(
"\r" + anchor_name + " 录制视频中: " + os.getcwd() + "/" + anchor_name + '/' + filename)
else:
print(
"\r" + anchor_name + " 录制视频中: " + video_save_path + anchor_name + '/' + filename)
filename_short = video_save_path + anchor_name + '/' + anchor_name + '_' + now
print(f'{rec_info}/{filename}')
if create_time_file:
filename_gruop = [anchor_name, filename_short]
@ -484,7 +516,7 @@ def start_record(line, count_variable=-1):
try:
# “port_info[3]”对应的是flv地址使用老方法下载直接请求下载flv只能是下载flv流的。
real_url = port_info[3]
_filepath, _ = urllib.request.urlretrieve(real_url,video_save_path + anchor_name + '/' + filename)
_filepath, _ = urllib.request.urlretrieve(real_url,full_path + '/' + filename)
record_finished = True
record_finished_2 = True
count_time = time.time()
@ -500,14 +532,8 @@ def start_record(line, count_variable=-1):
elif video_save_type == "MKV":
filename = anchor_name + '_' + now + ".mkv"
if len(video_save_path) == 0:
print("\r" + anchor_name + " 录制视频中: " + os.getcwd() + "/" + anchor_name + '/' + filename)
else:
print("\r" + anchor_name + " 录制视频中: " + video_save_path + anchor_name + '/' + filename)
file = video_save_path + anchor_name + '/' + filename
filename_short = video_save_path + anchor_name + '/' + anchor_name + '_' + now
print(f'{rec_info}/{filename}')
file = full_path + '/' + filename
if create_time_file:
filename_gruop = [anchor_name, filename_short]
create_var[str(filename_short)] = threading.Thread(target=create_ass_file,
@ -540,17 +566,10 @@ def start_record(line, count_variable=-1):
unrecording.add(anchor_name)
elif video_save_type == "MP4":
filename = anchor_name + '_' + now + ".mp4"
if len(video_save_path) == 0:
print(
"\r" + anchor_name + " 录制视频中: " + os.getcwd() + "/" + anchor_name + '/' + filename)
else:
print(
"\r" + anchor_name + " 录制视频中: " + video_save_path + anchor_name + '/' + filename)
file = video_save_path + anchor_name + '/' + filename
filename_short = video_save_path + anchor_name + '/' + anchor_name + '_' + now
print(f'{rec_info}/{filename}')
file = full_path + '/' + filename
if create_time_file:
filename_gruop = [anchor_name, filename_short]
@ -589,14 +608,9 @@ def start_record(line, count_variable=-1):
elif video_save_type == "MKV音频":
filename = anchor_name + '_' + now + ".mkv"
if len(video_save_path) == 0:
print(
"\r" + anchor_name + " 录制MKV音频中: " + os.getcwd() + "/" + anchor_name + '/' + filename)
else:
print(
"\r" + anchor_name + " 录制MKV音频中: " + video_save_path + anchor_name + '/' + filename)
print(f'{rec_info}/{filename}')
file = full_path + '/' + filename
file = video_save_path + anchor_name + '/' + filename
try:
command = [
"-map", "0:a", # 不同点
@ -624,14 +638,9 @@ def start_record(line, count_variable=-1):
elif video_save_type == "TS音频":
filename = anchor_name + '_' + now + ".ts"
if len(video_save_path) == 0:
print(
"\r" + anchor_name + " 录制TS音频中: " + os.getcwd() + "/" + anchor_name + '/' + filename)
else:
print(
"\r" + anchor_name + " 录制TS音频中: " + video_save_path + anchor_name + '/' + filename)
print(f'{rec_info}/{filename}')
file = full_path + '/' + filename
file = video_save_path + anchor_name + '/' + filename
try:
command = [
"-map", "0:a", # 不同点
@ -663,15 +672,8 @@ def start_record(line, count_variable=-1):
while True:
now = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime(time.time()))
filename = anchor_name + '_' + now + ".ts"
if len(video_save_path) == 0:
print(
"\r" + anchor_name + " 分段录制视频中: " + os.getcwd() + "/" + anchor_name + '/' + filename + " 每录满: %d M 存一个视频" % Splitsize)
else:
print(
"\r" + anchor_name + " 分段录制视频中: " + video_save_path + anchor_name + '/' + filename + " 每录满: %d M 存一个视频" % Splitsize)
file = video_save_path + anchor_name + '/' + filename
filename_short = video_save_path + anchor_name + '/' + anchor_name + '_' + now
print(f'{rec_info}/{filename}')
file = full_path + '/' + filename
if create_time_file:
filename_gruop = [anchor_name, filename_short]
@ -718,15 +720,9 @@ def start_record(line, count_variable=-1):
else:
filename = anchor_name + '_' + now + ".ts"
if len(video_save_path) == 0:
print(
"\r" + anchor_name + " 录制视频中: " + os.getcwd() + "/" + anchor_name + '/' + filename)
else:
print(
"\r" + anchor_name + " 录制视频中: " + video_save_path + anchor_name + '/' + filename)
file = video_save_path + anchor_name + '/' + filename
filename_short = video_save_path + anchor_name + '/' + anchor_name + '_' + now
print(f'{rec_info}/{filename}')
file = full_path + '/' + filename
if create_time_file:
filename_gruop = [anchor_name, filename_short]
@ -955,8 +951,6 @@ while True:
tsconvert_to_m4a = read_config_value(config, '1', 'TS录制完成后自动增加生成m4a格式', "")
delFilebeforeconversion = read_config_value(config, '1', '追加格式后删除原文件', "")
create_time_file = read_config_value(config, '1', '生成时间文件', "")
display_chrome = read_config_value(config, '1', '是否显示浏览器', "")
only_browser = read_config_value(config, '1', '仅用浏览器录制', "")
cookies_set = read_config_value(config, '1', 'cookies不可为空', '')
if len(video_save_type) > 0:
@ -1005,14 +999,11 @@ while True:
loop_time = options.get(loop_time, False) # 是否显示循环秒数
Splitvideobysize = options.get(Splitvideobysize, False) # 这里是控制TS是否分段
create_time_file = options.get(create_time_file, False) # 这里控制是否生成时间文件
display_chrome = options.get(display_chrome, False) # 这里控制是否生显示浏览器
only_browser = options.get(only_browser, False) # 这里是控制采用浏览器录制
delFilebeforeconversion = options.get(delFilebeforeconversion, False) # 追加格式后,是否删除原文件
tsconvert_to_m4a = options.get(tsconvert_to_m4a, False) # 这里是控制TS是否追加m4a格式
tsconvert_to_mp4 = options.get(tsconvert_to_mp4, False) # 这里是控制TS是否追加mp4格式
# 读取url_config.ini文件
try:
with open(url_config_file, "r", encoding=encoding) as file:
@ -1027,7 +1018,7 @@ while True:
split_line = [line, '']
url = split_line[0]
url_host=url.split('/')[2]
host_list=['live.douyin.com','v.douyin.com','www.tiktok.com']
host_list=['live.douyin.com','v.douyin.com','www.tiktok.com','live.kuaishou.com']
if url_host in host_list:
new_line = (url, split_line[1])
url_tuples_list.append(new_line)
@ -1058,7 +1049,6 @@ while True:
create_var['thread' + str(Monitoring)].daemon = True
create_var['thread' + str(Monitoring)].start()
runing_list.append(url_tuple[0])
# print("\r"+str(local_delay_default)+" 秒后读取下一个地址(如果存在) ")
time.sleep(local_delay_default)
url_tuples_list = []
first_start = False

View File

@ -4,9 +4,9 @@
Author: Hmily
Github:https://github.com/ihmily
Date: 2023-07-15 23:15:00
Update: 2023-08-03 08:06:43
Update: 2023-08-04 06:30:00
Copyright (c) 2023 by Hmily, All Rights Reserved.
Function: Get douyin and titok live stream.
Function: Get live stream data.
"""
import urllib
import urllib.parse
@ -14,14 +14,13 @@ import requests
import re
import json
# 直接选择从网页HTML中获取直播间数据
def get_douyin_stream_data(url,cookies):
# 直接选择从网页HTML中获取直播间数据
def get_douyin_stream_data(url, cookies):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Referer': 'https://live.douyin.com/',
# 'Cookie':'ttwid=1^%^7CIkooT8SJQrpeYtHlSALuhz9BdcHpaaf9tHQRKHuDaYE^%^7C1687785070^%^7C6690250483b63b6482128174d0f93bd879614d76f1b6e03ca52e032cf7fbaafd; passport_csrf_token=52bece134ac246c81163cc93b72f86a6; passport_csrf_token_default=52bece134ac246c81163cc93b72f86a6; d_ticket=2b9e3eb3626216c0122f0d980f867deb7b414; odin_tt=36dcfa4bd95b1edf0e6445dc9584a7371b4b90a2a8c390292b9be44af8161e06d10e34e6e575bf43c45c0a5871229533; passport_assist_user=CjxqZLHwcDmhxMjoh8u0-Jz4Zmhcq9VzKQqpAjK3P9Ve87i4njjbsai_u6NAI6MebG4KH4QXtbfNRbRFWRgaSAo8oBvHC_eXhqSGSo1uWPz4KBGu9uo-UdwM-5ynbDuDQRybofj0pQlPexcYmVoryiYqpC7yMdKO4rSVclgNEJbxtA0Yia_WVCIBA78Lg84^%^3D; n_mh=hvnJEQ4Q5eiH74-84kTFUyv4VK8xtSrpRZG1AhCeFNI; passport_auth_status=a74f300f376940d65914eb148d55ca96^%^2C9ca487aea255972120d502f736c5dd7b; passport_auth_status_ss=a74f300f376940d65914eb148d55ca96^%^2C9ca487aea255972120d502f736c5dd7b; sso_auth_status=52ecac30d95890cc7896c880366aa21a; sso_auth_status_ss=52ecac30d95890cc7896c880366aa21a; sso_uid_tt=a71f659bc416b890eb13929ee82a4340; sso_uid_tt_ss=a71f659bc416b890eb13929ee82a4340; toutiao_sso_user=da6c1f563492114cf1ad2dac7617e3f4; toutiao_sso_user_ss=da6c1f563492114cf1ad2dac7617e3f4; sid_ucp_sso_v1=1.0.0-KDNhOTk2NzYzZjkzMGZkZDdlNDU4ODE3YjczNGE3MGExYTBhOGQ0OGIKHQjRpfzk8AEQn6LmpAYY7zEgDDCRxffLBTgCQPEHGgJsZiIgZGE2YzFmNTYzNDkyMTE0Y2YxYWQyZGFjNzYxN2UzZjQ; ssid_ucp_sso_v1=1.0.0-KDNhOTk2NzYzZjkzMGZkZDdlNDU4ODE3YjczNGE3MGExYTBhOGQ0OGIKHQjRpfzk8AEQn6LmpAYY7zEgDDCRxffLBTgCQPEHGgJsZiIgZGE2YzFmNTYzNDkyMTE0Y2YxYWQyZGFjNzYxN2UzZjQ; sid_guard=219f9f2d8838724307589f32debd7d62^%^7C1687785774^%^7C5183988^%^7CFri^%^2C+25-Aug-2023+13^%^3A22^%^3A42+GMT; uid_tt=9f33ebaf781ad75909d6d4edb0b46b86; uid_tt_ss=9f33ebaf781ad75909d6d4edb0b46b86; sid_tt=219f9f2d8838724307589f32debd7d62; sessionid=219f9f2d8838724307589f32debd7d62; sessionid_ss=219f9f2d8838724307589f32debd7d62; sid_ucp_v1=1.0.0-KGZkMzE1MGRhMTZiOTI4M2ZkOTkzMjIwNjQ5NmJhMjhjMzlhZmFmMGYKGQjRpfzk8AEQrqLmpAYY7zEgDDgCQPEHSAQaAmxmIiAyMTlmOWYyZDg4Mzg3MjQzMDc1ODlmMzJkZWJkN2Q2Mg; ssid_ucp_v1=1.0.0-KGZkMzE1MGRhMTZiOTI4M2ZkOTkzMjIwNjQ5NmJhMjhjMzlhZmFmMGYKGQjRpfzk8AEQrqLmpAYY7zEgDDgCQPEHSAQaAmxmIiAyMTlmOWYyZDg4Mzg3MjQzMDc1ODlmMzJkZWJkN2Q2Mg; LOGIN_STATUS=1; store-region=cn-fj; store-region-src=uid; __security_server_data_status=1; __live_version__=^%^221.1.1.1250^%^22; live_can_add_dy_2_desktop=^%^220^%^22; xgplayer_user_id=528819598596; publish_badge_show_info=^%^220^%^2C0^%^2C0^%^2C1689195658062^%^22; msToken=OqErXe8WFLs1OjcJCNX2pNWTvnMSJIKjUXQRa74H4uQo8Ea5hpI8L3zlpK2eq5GUyrHcnTbQ-Kw4UgEntfb9dXu4Ijfowp_LSMxN6AISaoDf-OZCFv2IFS1P4UY2DHYG; ttcid=b8ea42abb1954fd2a913086620d2447f25; download_guide=^%^223^%^2F20230713^%^2F0^%^22; home_can_add_dy_2_desktop=^%^220^%^22; strategyABtestKey=^%^221689299939.836^%^22; FOLLOW_LIVE_POINT_INFO=^%^22MS4wLjABAAAAf6aekfyBsc4u8jMkeYbgnkFa0ksIWKWpGOywuyHXyo4^%^2F1689350400000^%^2F0^%^2F1689299940112^%^2F0^%^22; VIDEO_FILTER_MEMO_SELECT=^%^7B^%^22expireTime^%^22^%^3A1689904741009^%^2C^%^22type^%^22^%^3Anull^%^7D; device_web_cpu_core=8; device_web_memory_size=-1; webcast_local_quality=origin; csrf_session_id=ce1e9bc7ba69feec32889636027ce79a; passport_fe_beating_status=false; webcast_leading_last_show_time=1689300023141; webcast_leading_total_show_times=1; tt_scid=PgQO8z6aK2zeofuxFGselkNp2kSbPFCuPmOMwU9ih.SXbBp8iA7l2EiqrurdBuMWf204; msToken=T5-gdGi61ytJtas2VgUQAogURSJT2pQDWT5E_TPGT9paO9OtCuHOGAl72YAxHhrkKJdNhx6O1JgGn0uzdkfHw_a_MWJS-OJlgroduiLAcJzzSCmib6GfWqIgWT8m2qA3; __ac_nonce=064b0be450072f85a1215; __ac_signature=_02B4Z6wo00f01eL3lWgAAIDA.rQr1mcyUx3ixpHAABwPwM4wuxfDlht-h5js2proCQ84O246NPRhh7I6Pv0tJwHeCCotGZpibWazzH51O7kDcl18lUJy6o8VYLGIG..jFlP-zEpspGjM6AZO34; __ac_referer=https://live.douyin.com/',
'Cookie': cookies
}
@ -38,12 +37,12 @@ def get_douyin_stream_data(url,cookies):
return json_data
def get_tiktok_stream_data(url,proxy_addr):
def get_tiktok_stream_data(url, proxy_addr):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.79'
}
if proxy_addr !='':
if proxy_addr != '':
# 设置代理
proxies = {
'http': proxy_addr,
@ -67,10 +66,27 @@ def get_tiktok_stream_data(url,proxy_addr):
return json_data
def get_kuaishou_stream_data(url):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
}
request = urllib.request.Request(url, headers=headers)
response = urllib.request.urlopen(request, timeout=10)
html_str = response.read().decode('utf-8')
json_str = re.findall('__INITIAL_STATE__=(.*?);\(function', html_str)[0]
# print(json_str)
json_data = json.loads(json_str)
return json_data
if __name__ == '__main__':
Cookie='ttwid=1%7CB1qls3GdnZhUov9o2NxOMxxYS2ff6OSvEWbv0ytbES4%7C1680522049%7C280d802d6d478e3e78d0c807f7c487e7ffec0ae4e5fdd6a0fe74c3c6af149511; my_rd=1; passport_csrf_token=3ab34460fa656183fccfb904b16ff742; passport_csrf_token_default=3ab34460fa656183fccfb904b16ff742; d_ticket=9f562383ac0547d0b561904513229d76c9c21; n_mh=hvnJEQ4Q5eiH74-84kTFUyv4VK8xtSrpRZG1AhCeFNI; store-region=cn-fj; store-region-src=uid; LOGIN_STATUS=1; __security_server_data_status=1; FORCE_LOGIN=%7B%22videoConsumedRemainSeconds%22%3A180%7D; pwa2=%223%7C0%7C3%7C0%22; download_guide=%223%2F20230729%2F0%22; volume_info=%7B%22isUserMute%22%3Afalse%2C%22isMute%22%3Afalse%2C%22volume%22%3A0.6%7D; strategyABtestKey=%221690824679.923%22; stream_recommend_feed_params=%22%7B%5C%22cookie_enabled%5C%22%3Atrue%2C%5C%22screen_width%5C%22%3A1536%2C%5C%22screen_height%5C%22%3A864%2C%5C%22browser_online%5C%22%3Atrue%2C%5C%22cpu_core_num%5C%22%3A8%2C%5C%22device_memory%5C%22%3A8%2C%5C%22downlink%5C%22%3A10%2C%5C%22effective_type%5C%22%3A%5C%224g%5C%22%2C%5C%22round_trip_time%5C%22%3A150%7D%22; VIDEO_FILTER_MEMO_SELECT=%7B%22expireTime%22%3A1691443863751%2C%22type%22%3Anull%7D; home_can_add_dy_2_desktop=%221%22; __live_version__=%221.1.1.2169%22; device_web_cpu_core=8; device_web_memory_size=8; xgplayer_user_id=346045893336; csrf_session_id=2e00356b5cd8544d17a0e66484946f28; odin_tt=724eb4dd23bc6ffaed9a1571ac4c757ef597768a70c75fef695b95845b7ffcd8b1524278c2ac31c2587996d058e03414595f0a4e856c53bd0d5e5f56dc6d82e24004dc77773e6b83ced6f80f1bb70627; __ac_nonce=064caded4009deafd8b89; __ac_signature=_02B4Z6wo00f01HLUuwwAAIDBh6tRkVLvBQBy9L-AAHiHf7; ttcid=2e9619ebbb8449eaa3d5a42d8ce88ec835; webcast_leading_last_show_time=1691016922379; webcast_leading_total_show_times=1; webcast_local_quality=sd; live_can_add_dy_2_desktop=%221%22; msToken=1JDHnVPw_9yTvzIrwb7cQj8dCMNOoesXbA_IooV8cezcOdpe4pzusZE7NB7tZn9TBXPr0ylxmv-KMs5rqbNUBHP4P7VBFUu0ZAht_BEylqrLpzgt3y5ne_38hXDOX8o=; msToken=jV_yeN1IQKUd9PlNtpL7k5vthGKcHo0dEh_QPUQhr8G3cuYv-Jbb4NnIxGDmhVOkZOCSihNpA2kvYtHiTW25XNNX_yrsv5FN8O6zm3qmCIXcEe0LywLn7oBO2gITEeg=; tt_scid=mYfqpfbDjqXrIGJuQ7q-DlQJfUSG51qG.KUdzztuGP83OjuVLXnQHjsz-BRHRJu4e986'
url="https://live.douyin.com/803023607352" # douyin live
url="https://live.douyin.com/745964462470" # douyin live
# url = "https://www.tiktok.com/@pearlgaga88/live" # tiktok live
print(get_douyin_stream_data(url,Cookie))
# 抖音直播间页面的cookie
Cookie = 'ttwid=1%7CB1qls3GdnZhUov9o2NxOMxxYS2ff6OSvEWbv0ytbES4%7C1680522049%7C280d802d6d478e3e78d0c807f7c487e7ffec0ae4e5fdd6a0fe74c3c6af149511; my_rd=1; passport_csrf_token=3ab34460fa656183fccfb904b16ff742; passport_csrf_token_default=3ab34460fa656183fccfb904b16ff742; d_ticket=9f562383ac0547d0b561904513229d76c9c21; n_mh=hvnJEQ4Q5eiH74-84kTFUyv4VK8xtSrpRZG1AhCeFNI; store-region=cn-fj; store-region-src=uid; LOGIN_STATUS=1; __security_server_data_status=1; FORCE_LOGIN=%7B%22videoConsumedRemainSeconds%22%3A180%7D; pwa2=%223%7C0%7C3%7C0%22; download_guide=%223%2F20230729%2F0%22; volume_info=%7B%22isUserMute%22%3Afalse%2C%22isMute%22%3Afalse%2C%22volume%22%3A0.6%7D; strategyABtestKey=%221690824679.923%22; stream_recommend_feed_params=%22%7B%5C%22cookie_enabled%5C%22%3Atrue%2C%5C%22screen_width%5C%22%3A1536%2C%5C%22screen_height%5C%22%3A864%2C%5C%22browser_online%5C%22%3Atrue%2C%5C%22cpu_core_num%5C%22%3A8%2C%5C%22device_memory%5C%22%3A8%2C%5C%22downlink%5C%22%3A10%2C%5C%22effective_type%5C%22%3A%5C%224g%5C%22%2C%5C%22round_trip_time%5C%22%3A150%7D%22; VIDEO_FILTER_MEMO_SELECT=%7B%22expireTime%22%3A1691443863751%2C%22type%22%3Anull%7D; home_can_add_dy_2_desktop=%221%22; __live_version__=%221.1.1.2169%22; device_web_cpu_core=8; device_web_memory_size=8; xgplayer_user_id=346045893336; csrf_session_id=2e00356b5cd8544d17a0e66484946f28; odin_tt=724eb4dd23bc6ffaed9a1571ac4c757ef597768a70c75fef695b95845b7ffcd8b1524278c2ac31c2587996d058e03414595f0a4e856c53bd0d5e5f56dc6d82e24004dc77773e6b83ced6f80f1bb70627; __ac_nonce=064caded4009deafd8b89; __ac_signature=_02B4Z6wo00f01HLUuwwAAIDBh6tRkVLvBQBy9L-AAHiHf7; ttcid=2e9619ebbb8449eaa3d5a42d8ce88ec835; webcast_leading_last_show_time=1691016922379; webcast_leading_total_show_times=1; webcast_local_quality=sd; live_can_add_dy_2_desktop=%221%22; msToken=1JDHnVPw_9yTvzIrwb7cQj8dCMNOoesXbA_IooV8cezcOdpe4pzusZE7NB7tZn9TBXPr0ylxmv-KMs5rqbNUBHP4P7VBFUu0ZAht_BEylqrLpzgt3y5ne_38hXDOX8o=; msToken=jV_yeN1IQKUd9PlNtpL7k5vthGKcHo0dEh_QPUQhr8G3cuYv-Jbb4NnIxGDmhVOkZOCSihNpA2kvYtHiTW25XNNX_yrsv5FN8O6zm3qmCIXcEe0LywLn7oBO2gITEeg=; tt_scid=mYfqpfbDjqXrIGJuQ7q-DlQJfUSG51qG.KUdzztuGP83OjuVLXnQHjsz-BRHRJu4e986'
url = "https://live.douyin.com/745964462470" # 抖音直播
# url = "https://www.tiktok.com/@pearlgaga88/live" # Tiktok 直播
# url = "https://live.kuaishou.com/u/yall1102" # 快手直播
# print(get_douyin_stream_data(url,Cookie))
# print(get_tiktok_stream_data(url,''))
# print(get_kuaishou_stream_data(url))