mirror of
https://github.com/ihmily/DouyinLiveRecorder.git
synced 2026-03-22 07:28:24 +08:00
feat: add liuxing live record and fix huya live
This commit is contained in:
21
README.md
21
README.md
@@ -40,6 +40,7 @@
|
||||
- [x] TwitchTV
|
||||
- [x] LiveMe
|
||||
- [x] 花椒直播
|
||||
- [x] 流星直播
|
||||
- [ ] 更多平台正在更新中
|
||||
|
||||
</div>
|
||||
@@ -173,19 +174,16 @@ https://www.liveme.com/zh/v/17141543493018047815/index.html
|
||||
|
||||
花椒直播:
|
||||
https://www.huajiao.com/user/223184650
|
||||
|
||||
流星直播:
|
||||
https://www.7u66.com/100960
|
||||
```
|
||||
|
||||
直播间分享地址和网页端长地址都能正常进行录制(抖音尽量用长链接,避免因短链接转换失效导致不能正常录制,而且需要有nodejs环境,否则无法转换)。
|
||||
|
||||
 
|
||||
|
||||
解析接口:
|
||||
|
||||
该解析接口 ~~仅供演示~~(演示接口暂时停止,后续再开放),并且只包含抖音、快手、虎牙直播的解析,其他平台如有需要请自行添加,源码在这里 [DouyinLiveRecorder/api](https://github.com/ihmily/DouyinLiveRecorder/tree/main/api)
|
||||
|
||||
|
||||
|
||||
在线播放m3u8和flv视频网站:[M3U8 在线视频播放器 ](https://jx.hmily.vip/play/),源码是 [index.html](https://github.com/ihmily/DouyinLiveRecorder/blob/main/index.html)
|
||||
在线播放m3u8和flv视频网站:[M3U8 在线视频播放器 ](https://jx.hmily.vip/play/)
|
||||
|
||||
 
|
||||
|
||||
@@ -305,9 +303,16 @@ docker-compose stop
|
||||
|
||||
## ⏳提交日志
|
||||
|
||||
- 20240506
|
||||
- 修复抖音录制画质解析bug
|
||||
|
||||
- 修复虎牙录制 60帧最高画质问题
|
||||
|
||||
- 新增流星直播录制
|
||||
|
||||
- 20240427
|
||||
- 新增LiveMe、花椒直播录制
|
||||
|
||||
|
||||
- 20240425
|
||||
- 新增TwitchTV直播录制
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
直播保存路径(不填则默认) =
|
||||
保存文件夹是否以作者区分 = 是
|
||||
视频保存格式ts|mkv|flv|mp4|ts音频|mkv音频 = ts
|
||||
原画|超清|高清|标清 = 原画
|
||||
原画|超清|高清|标清|流畅 = 原画
|
||||
是否使用代理ip(是/否) = 是
|
||||
代理地址 =
|
||||
同一时间访问网络的线程数 = 3
|
||||
|
||||
111
main.py
111
main.py
@@ -4,7 +4,7 @@
|
||||
Author: Hmily
|
||||
GitHub: https://github.com/ihmily
|
||||
Date: 2023-07-17 23:52:05
|
||||
Update: 2024-05-06 12:45:21
|
||||
Update: 2024-05-06 22:45:21
|
||||
Copyright (c) 2023-2024 by Hmily, All Rights Reserved.
|
||||
Function: Record live stream video.
|
||||
"""
|
||||
@@ -25,7 +25,7 @@ import hashlib
|
||||
import urllib.parse
|
||||
import urllib.request
|
||||
from urllib.error import URLError, HTTPError
|
||||
from typing import Any, Union
|
||||
from typing import Any, Union, Dict
|
||||
import configparser
|
||||
|
||||
from spider import (
|
||||
@@ -55,7 +55,8 @@ from spider import (
|
||||
get_kugou_stream_url,
|
||||
get_twitchtv_stream_data,
|
||||
get_liveme_stream_url,
|
||||
get_huajiao_stream_url
|
||||
get_huajiao_stream_url,
|
||||
get_liuxing_stream_url
|
||||
)
|
||||
|
||||
from web_rid import (
|
||||
@@ -68,11 +69,11 @@ from utils import (
|
||||
)
|
||||
from msg_push import dingtalk, xizhi, tg_bot
|
||||
|
||||
version = "v3.0.3"
|
||||
platforms = "\n国内站点:抖音|快手|虎牙|斗鱼|YY|B站|小红书|bigo|blued|网易CC|千度热播|猫耳FM|Look|TwitCasting|百度|微博|酷狗|LiveMe|花椒直播" \
|
||||
version = "v3.0.4"
|
||||
platforms = "\n国内站点:抖音|快手|虎牙|斗鱼|YY|B站|小红书|bigo|blued|网易CC|千度热播|猫耳FM|Look|TwitCasting|百度|微博|酷狗|LiveMe|花椒|流星" \
|
||||
"\n海外站点:TikTok|AfreecaTV|PandaTV|WinkTV|FlexTV|PopkonTV|TwitchTV"
|
||||
|
||||
# --------------------------全局变量-------------------------------------
|
||||
|
||||
recording = set()
|
||||
unrecording = set()
|
||||
warning_count = 0
|
||||
@@ -98,9 +99,9 @@ rstr = r"[\/\\\:\*\?\"\<\>\|&.。,,]"
|
||||
ffmpeg_path = "ffmpeg" # ffmpeg文件路径
|
||||
default_path = os.getcwd() + '/downloads'
|
||||
os.makedirs(default_path, exist_ok=True)
|
||||
file_update_lock = threading.Lock()
|
||||
|
||||
|
||||
# --------------------------用到的函数-------------------------------------
|
||||
def signal_handler(_signal, _frame):
|
||||
sys.exit(0)
|
||||
|
||||
@@ -162,10 +163,8 @@ def display_info():
|
||||
logger.error(f"错误信息: {e} 发生错误的行数: {e.__traceback__.tb_lineno}")
|
||||
|
||||
|
||||
def update_file(file_path: str, old_str: str, new_str: str, start_str: str = None, lock: threading.Lock = None):
|
||||
if lock is None:
|
||||
lock = threading.Lock()
|
||||
with lock:
|
||||
def update_file(file_path: str, old_str: str, new_str: str, start_str: str = None):
|
||||
with file_update_lock:
|
||||
file_data = ""
|
||||
with open(file_path, "r", encoding="utf-8-sig") as f:
|
||||
for text_line in f:
|
||||
@@ -241,9 +240,7 @@ def create_ass_file(filegruop: list):
|
||||
def change_max_connect():
|
||||
global max_request
|
||||
global warning_count
|
||||
# 动态控制连接次数
|
||||
preset = max_request
|
||||
# 记录当前时间
|
||||
start_time = time.time()
|
||||
|
||||
while True:
|
||||
@@ -252,10 +249,10 @@ def change_max_connect():
|
||||
if preset > 5:
|
||||
max_request = 5
|
||||
else:
|
||||
max_request //= 2 # 将max_request除以2(向下取整)
|
||||
if max_request > 0: # 如果得到的结果大于0,则直接取该结果
|
||||
max_request //= 2
|
||||
if max_request > 0:
|
||||
max_request = preset
|
||||
else: # 否则将其设置为1
|
||||
else:
|
||||
preset = 1
|
||||
|
||||
print("同一时间访问网络的线程数动态改为", max_request)
|
||||
@@ -276,7 +273,7 @@ def change_max_connect():
|
||||
|
||||
|
||||
@trace_error_decorator
|
||||
def get_douyin_stream_url(json_data: dict, video_quality: str) -> dict:
|
||||
def get_douyin_stream_url(json_data: dict, video_quality: str) -> Dict[str, Any]:
|
||||
# TODO: 获取抖音直播源地址
|
||||
|
||||
anchor_name = json_data.get('anchor_name', None)
|
||||
@@ -319,12 +316,12 @@ def get_douyin_stream_url(json_data: dict, video_quality: str) -> dict:
|
||||
|
||||
|
||||
@trace_error_decorator
|
||||
def get_tiktok_stream_url(json_data: dict, video_quality: str) -> dict:
|
||||
def get_tiktok_stream_url(json_data: dict, video_quality: str) -> Dict[str, Any]:
|
||||
# TODO: 获取tiktok直播源地址
|
||||
if not json_data:
|
||||
return {"anchor_name": None, "is_live": False}
|
||||
|
||||
def get_video_quality_url(stream, q_key):
|
||||
def get_video_quality_url(stream, q_key) -> Dict[str, str]:
|
||||
return {
|
||||
'hls': re.sub("https", "http", stream[q_key]['main']['hls']),
|
||||
'flv': re.sub("https", "http", stream[q_key]['main']['flv']),
|
||||
@@ -360,7 +357,7 @@ def get_tiktok_stream_url(json_data: dict, video_quality: str) -> dict:
|
||||
|
||||
|
||||
@trace_error_decorator
|
||||
def get_kuaishou_stream_url(json_data: dict, video_quality: str) -> dict:
|
||||
def get_kuaishou_stream_url(json_data: dict, video_quality: str) -> Dict[str, Any]:
|
||||
# TODO: 获取快手直播源地址
|
||||
|
||||
if json_data['type'] == 1 and not json_data["is_live"]:
|
||||
@@ -399,7 +396,7 @@ def get_kuaishou_stream_url(json_data: dict, video_quality: str) -> dict:
|
||||
|
||||
|
||||
@trace_error_decorator
|
||||
def get_huya_stream_url(json_data: dict, video_quality: str) -> dict:
|
||||
def get_huya_stream_url(json_data: dict, video_quality: str) -> Dict[str, Any]:
|
||||
# TODO: 获取虎牙直播源地址
|
||||
|
||||
game_live_info = json_data.get('data', [])[0].get('gameLiveInfo', {})
|
||||
@@ -420,7 +417,7 @@ def get_huya_stream_url(json_data: dict, video_quality: str) -> dict:
|
||||
hls_url_suffix = select_cdn.get('sHlsUrlSuffix')
|
||||
flv_anti_code = select_cdn.get('sFlvAntiCode')
|
||||
|
||||
def get_anti_code(old_anti_code):
|
||||
def get_anti_code(old_anti_code: str) -> str:
|
||||
|
||||
# js地址:https://hd.huya.com/cdn_libs/mobile/hysdk-m-202402211431.js
|
||||
|
||||
@@ -461,19 +458,17 @@ def get_huya_stream_url(json_data: dict, video_quality: str) -> dict:
|
||||
m3u8_url = f'{hls_url}/{stream_name}.{hls_url_suffix}?{new_anti_code}&ratio='
|
||||
|
||||
quality_list = flv_anti_code.split('&exsphd=')
|
||||
if len(quality_list) > 1:
|
||||
if len(quality_list) > 1 and video_quality not in ["原画", "蓝光"]:
|
||||
pattern = r"(?<=264_)\d+"
|
||||
quality_list = [x for x in re.findall(pattern, quality_list[1])][::-1]
|
||||
while len(quality_list) < 5:
|
||||
quality_list.append(quality_list[-1])
|
||||
|
||||
video_quality_options = {
|
||||
"原画": quality_list[0],
|
||||
"蓝光": quality_list[0],
|
||||
"超清": quality_list[1],
|
||||
"高清": quality_list[2],
|
||||
"标清": quality_list[3],
|
||||
"流畅": quality_list[4]
|
||||
"超清": quality_list[0],
|
||||
"高清": quality_list[1],
|
||||
"标清": quality_list[2],
|
||||
"流畅": quality_list[3]
|
||||
}
|
||||
|
||||
if video_quality not in video_quality_options:
|
||||
@@ -491,7 +486,7 @@ def get_huya_stream_url(json_data: dict, video_quality: str) -> dict:
|
||||
|
||||
|
||||
@trace_error_decorator
|
||||
def get_douyu_stream_url(json_data: dict, cookies: str, video_quality: str, proxy_address: str) -> dict:
|
||||
def get_douyu_stream_url(json_data: dict, cookies: str, video_quality: str, proxy_address: str) -> Dict[str, Any]:
|
||||
# TODO: 获取斗鱼直播源地址
|
||||
if not json_data["is_live"]:
|
||||
return json_data
|
||||
@@ -517,7 +512,7 @@ def get_douyu_stream_url(json_data: dict, cookies: str, video_quality: str, prox
|
||||
|
||||
|
||||
@trace_error_decorator
|
||||
def get_yy_stream_url(json_data: dict) -> dict:
|
||||
def get_yy_stream_url(json_data: dict) -> Dict[str, Any]:
|
||||
# TODO: 获取YY直播源地址
|
||||
anchor_name = json_data.get('anchor_name', '')
|
||||
result = {
|
||||
@@ -536,7 +531,7 @@ def get_yy_stream_url(json_data: dict) -> dict:
|
||||
|
||||
|
||||
@trace_error_decorator
|
||||
def get_bilibili_stream_url(json_data: dict, video_quality: str) -> dict:
|
||||
def get_bilibili_stream_url(json_data: dict, video_quality: str) -> Dict[str, Any]:
|
||||
# TODO: 获取B站直播源地址
|
||||
if "is_live" in json_data and not json_data['anchor_name']:
|
||||
return json_data
|
||||
@@ -601,7 +596,7 @@ def get_bilibili_stream_url(json_data: dict, video_quality: str) -> dict:
|
||||
|
||||
|
||||
@trace_error_decorator
|
||||
def get_afreecatv_stream_url(json_data: dict, video_quality: str) -> dict:
|
||||
def get_afreecatv_stream_url(json_data: dict, video_quality: str) -> Dict[str, Any]:
|
||||
# TODO: 获取afreecatv直播源地址
|
||||
if not json_data['is_live']:
|
||||
return json_data
|
||||
@@ -623,7 +618,7 @@ def get_afreecatv_stream_url(json_data: dict, video_quality: str) -> dict:
|
||||
|
||||
|
||||
@trace_error_decorator
|
||||
def get_netease_stream_url(json_data: dict, video_quality: str) -> dict:
|
||||
def get_netease_stream_url(json_data: dict, video_quality: str) -> Dict[str, Any]:
|
||||
# TODO: 获取netease直播源地址
|
||||
if not json_data['is_live']:
|
||||
return json_data
|
||||
@@ -646,7 +641,7 @@ def get_netease_stream_url(json_data: dict, video_quality: str) -> dict:
|
||||
|
||||
|
||||
@trace_error_decorator
|
||||
def get_pandatv_stream_url(json_data: dict, video_quality: str) -> dict:
|
||||
def get_pandatv_stream_url(json_data: dict, video_quality: str) -> Dict[str, Any]:
|
||||
# TODO: 获取pandatv直播源地址
|
||||
if not json_data['is_live']:
|
||||
return json_data
|
||||
@@ -668,7 +663,7 @@ def get_pandatv_stream_url(json_data: dict, video_quality: str) -> dict:
|
||||
|
||||
|
||||
@trace_error_decorator
|
||||
def get_winktv_stream_url(json_data: dict, video_quality: str) -> dict:
|
||||
def get_winktv_stream_url(json_data: dict, video_quality: str) -> Dict[str, Any]:
|
||||
# TODO: 获取winktv直播源地址
|
||||
if not json_data['is_live']:
|
||||
return json_data
|
||||
@@ -690,7 +685,7 @@ def get_winktv_stream_url(json_data: dict, video_quality: str) -> dict:
|
||||
|
||||
|
||||
@trace_error_decorator
|
||||
def get_flextv_stream_url(json_data: dict, video_quality: str) -> dict:
|
||||
def get_flextv_stream_url(json_data: dict, video_quality: str) -> Dict[str, Any]:
|
||||
# TODO: 获取flextv直播源地址
|
||||
if not json_data['is_live']:
|
||||
return json_data
|
||||
@@ -712,7 +707,7 @@ def get_flextv_stream_url(json_data: dict, video_quality: str) -> dict:
|
||||
|
||||
|
||||
@trace_error_decorator
|
||||
def get_baidu_stream_url(json_data: dict, video_quality: str) -> dict:
|
||||
def get_baidu_stream_url(json_data: dict, video_quality: str) -> Dict[str, Any]:
|
||||
# TODO: 获取百度直播源地址
|
||||
if not json_data['is_live']:
|
||||
return json_data
|
||||
@@ -733,7 +728,8 @@ def get_baidu_stream_url(json_data: dict, video_quality: str) -> dict:
|
||||
}
|
||||
|
||||
|
||||
def get_twitchtv_stream_url(json_data: dict, video_quality: str) -> dict:
|
||||
def get_twitchtv_stream_url(json_data: dict, video_quality: str) -> Dict[str, Any]:
|
||||
# TODO: 获取twitchtv直播源地址
|
||||
if not json_data['is_live']:
|
||||
return json_data
|
||||
|
||||
@@ -753,7 +749,7 @@ def get_twitchtv_stream_url(json_data: dict, video_quality: str) -> dict:
|
||||
}
|
||||
|
||||
|
||||
def push_message(content: str):
|
||||
def push_message(content: str) -> Union[str, list]:
|
||||
push_pts = []
|
||||
if '微信' in live_status_push:
|
||||
push_pts.append('微信')
|
||||
@@ -764,7 +760,7 @@ def push_message(content: str):
|
||||
if 'TG' in live_status_push or 'tg' in live_status_push:
|
||||
push_pts.append('TG')
|
||||
tg_bot(tg_chat_id, tg_token, content)
|
||||
push_pts = '、'.join(push_pts) if len(push_pts) > 0 else ''
|
||||
push_pts = '、'.join(push_pts) if len(push_pts) > 0 else []
|
||||
return push_pts
|
||||
|
||||
|
||||
@@ -1057,6 +1053,12 @@ def start_record(url_data: tuple, count_variable: int = -1):
|
||||
with semaphore:
|
||||
port_info = get_huajiao_stream_url(
|
||||
url=record_url, proxy_addr=proxy_address, cookies=huajiao_cookie)
|
||||
|
||||
elif record_url.find("7u66.com/") > -1:
|
||||
platform = '流星直播'
|
||||
with semaphore:
|
||||
port_info = get_liuxing_stream_url(
|
||||
url=record_url, proxy_addr=proxy_address, cookies=liuxing_cookie)
|
||||
else:
|
||||
logger.error(f'{record_url} 未知直播地址')
|
||||
return
|
||||
@@ -1192,7 +1194,8 @@ def start_record(url_data: tuple, count_variable: int = -1):
|
||||
if platform in re_plat:
|
||||
logger.info(f"{platform} | {anchor_name} | 直播源地址: {port_info['m3u8_url']}")
|
||||
else:
|
||||
logger.info(f"{platform} | {anchor_name} | 直播源地址: {port_info['record_url']}")
|
||||
logger.info(
|
||||
f"{platform} | {anchor_name} | 直播源地址: {port_info['record_url']}")
|
||||
|
||||
if video_save_type == "FLV":
|
||||
filename = anchor_name + '_' + now + '.flv'
|
||||
@@ -1540,7 +1543,7 @@ def start_record(url_data: tuple, count_variable: int = -1):
|
||||
|
||||
def backup_file(file_path: str, backup_dir_path: str):
|
||||
"""
|
||||
备份配置文件到备份目录,分别保留最新 5 个文件
|
||||
备份配置文件到备份目录,分别保留最新 8 个文件
|
||||
"""
|
||||
try:
|
||||
if not os.path.exists(backup_dir_path):
|
||||
@@ -1561,13 +1564,13 @@ def backup_file(file_path: str, backup_dir_path: str):
|
||||
url_files.sort(key=lambda x: os.path.getmtime(os.path.join(backup_dir_path, x)))
|
||||
config_files.sort(key=lambda x: os.path.getmtime(os.path.join(backup_dir_path, x)))
|
||||
|
||||
while len(url_files) > 5:
|
||||
while len(url_files) > 8:
|
||||
oldest_file = url_files[0]
|
||||
os.remove(os.path.join(backup_dir_path, oldest_file))
|
||||
# print(f'\r已删除最旧的 URL_config.ini 备份文件 {oldest_file}')
|
||||
url_files = url_files[1:]
|
||||
|
||||
while len(config_files) > 5:
|
||||
while len(config_files) > 8:
|
||||
oldest_file = config_files[0]
|
||||
os.remove(os.path.join(backup_dir_path, oldest_file))
|
||||
# print(f'\r已删除最旧的 config.ini 备份文件 {oldest_file}')
|
||||
@@ -1641,8 +1644,8 @@ except Exception as err:
|
||||
print("An unexpected error occurred:", err)
|
||||
|
||||
|
||||
def read_config_value(config_parser: configparser.RawConfigParser, section: str, option: str, default_value: Any) -> (
|
||||
Union)[str, int, bool]:
|
||||
def read_config_value(config_parser: configparser.RawConfigParser, section: str, option: str, default_value: Any) \
|
||||
-> Union[str, int, bool]:
|
||||
try:
|
||||
|
||||
config_parser.read(config_file, encoding=encoding)
|
||||
@@ -1761,6 +1764,7 @@ while True:
|
||||
twitch_cookie = read_config_value(config, 'Cookie', 'twitch_cookie', '')
|
||||
liveme_cookie = read_config_value(config, 'Cookie', 'liveme_cookie', '')
|
||||
huajiao_cookie = read_config_value(config, 'Cookie', 'huajiao_cookie', '')
|
||||
liuxing_cookie = read_config_value(config, 'Cookie', 'liuxing_cookie', '')
|
||||
|
||||
if len(video_save_type) > 0:
|
||||
if video_save_type.upper().lower() == "FLV".lower():
|
||||
@@ -1821,7 +1825,7 @@ while True:
|
||||
else:
|
||||
quality, url, name = split_line
|
||||
|
||||
if quality not in ["原画", "蓝光", "超清", "高清", "标清"]:
|
||||
if quality not in ["原画", "蓝光", "超清", "高清", "标清", "流畅"]:
|
||||
quality = '原画'
|
||||
|
||||
if ('http://' not in url) and ('https://' not in url):
|
||||
@@ -1852,6 +1856,8 @@ while True:
|
||||
'mfanxing.kugou.com',
|
||||
'www.liveme.com',
|
||||
'www.huajiao.com',
|
||||
'www.7u66.com',
|
||||
'wap.7u66.com',
|
||||
]
|
||||
overseas_platform_host = [
|
||||
'www.tiktok.com',
|
||||
@@ -1869,6 +1875,12 @@ while True:
|
||||
if url_host in ['live.douyin.com', 'live.bilibili.com', 'www.huajiao.com']:
|
||||
update_file(url_config_file, url, url.split('?')[0])
|
||||
url = url.split('?')[0]
|
||||
if url_host in ['www.xiaohongshu.com', 'www.redelight.cn']:
|
||||
if 'share_source' in url:
|
||||
xhs_url_h, xhs_url_t, = url.split('?')
|
||||
new_xhs_url = xhs_url_h + '?appuid=' + xhs_url_t.split('&appuid=')[1].split('&')[0]
|
||||
update_file(url_config_file, url, new_xhs_url)
|
||||
url = new_xhs_url
|
||||
|
||||
new_line = (quality, url, name)
|
||||
url_tuples_list.append(new_line)
|
||||
@@ -1901,7 +1913,6 @@ while True:
|
||||
print(f"\r新增链接: {url_tuple[1]}")
|
||||
monitoring += 1
|
||||
args = [url_tuple, monitoring]
|
||||
# TODO: 执行开始录制的操作
|
||||
create_var['thread' + str(monitoring)] = threading.Thread(target=start_record, args=args)
|
||||
create_var['thread' + str(monitoring)].daemon = True
|
||||
create_var['thread' + str(monitoring)].start()
|
||||
@@ -1921,4 +1932,4 @@ while True:
|
||||
|
||||
first_run = False
|
||||
|
||||
time.sleep(3)
|
||||
time.sleep(3)
|
||||
|
||||
53
spider.py
53
spider.py
@@ -4,7 +4,7 @@
|
||||
Author: Hmily
|
||||
GitHub:https://github.com/ihmily
|
||||
Date: 2023-07-15 23:15:00
|
||||
Update: 2024-04-27 23:00:11
|
||||
Update: 2024-05-06 23:00:11
|
||||
Copyright (c) 2023 by Hmily, All Rights Reserved.
|
||||
Function: Get live stream data.
|
||||
"""
|
||||
@@ -15,7 +15,7 @@ import time
|
||||
import urllib.parse
|
||||
import urllib.error
|
||||
from urllib.request import Request
|
||||
from typing import Union, Dict, Any, Tuple
|
||||
from typing import Union, Dict, Any, Tuple, List
|
||||
import requests
|
||||
import ssl
|
||||
import re
|
||||
@@ -125,7 +125,7 @@ def replace_url(file_path: str, old: str, new: str) -> None:
|
||||
|
||||
|
||||
def get_play_url_list(m3u8: str, proxy: Union[str, None] = None, header: Union[dict, None] = None,
|
||||
abroad: bool = False) -> list:
|
||||
abroad: bool = False) -> List[str]:
|
||||
resp = get_req(url=m3u8, proxy_addr=proxy, headers=header, abroad=abroad)
|
||||
play_url_list = []
|
||||
for i in resp.split('\n'):
|
||||
@@ -430,7 +430,7 @@ def get_bilibili_stream_data(url: str, proxy_addr: Union[str, None] = None, cook
|
||||
if cookies:
|
||||
headers['Cookie'] = cookies
|
||||
|
||||
def get_data_from_api(link: str):
|
||||
def get_data_from_api(link: str) -> Dict[str, Any]:
|
||||
room_id = link.split('?')[0].rsplit('/', maxsplit=1)[1]
|
||||
api = f'https://api.live.bilibili.com/xlive/web-room/v2/index/getRoomPlayInfo?room_id={room_id}&no_playurl=0&mask=1&qn=0&platform=web&protocol=0,1&format=0,1,2&codec=0,1,2&dolby=5&panorama=1'
|
||||
json_str = get_req(url=api, proxy_addr=proxy_addr, headers=headers)
|
||||
@@ -714,7 +714,7 @@ def get_afreecatv_stream_data(
|
||||
"is_live": False,
|
||||
}
|
||||
|
||||
def get_url_list(m3u8: str) -> list:
|
||||
def get_url_list(m3u8: str) -> List[str]:
|
||||
resp = get_req(url=m3u8, proxy_addr=proxy_addr, headers=headers, abroad=True)
|
||||
play_url_list = []
|
||||
url_prefix = m3u8.rsplit('/', maxsplit=1)[0] + '/'
|
||||
@@ -1811,7 +1811,7 @@ def get_huajiao_sn(live_id: str, cookies: Union[str, None] = None, proxy_addr: U
|
||||
live_id = url.split('?')[0].rsplit('/', maxsplit=1)[1]
|
||||
return nickname, sn, uid, live_id
|
||||
except Exception:
|
||||
replace_url('./config/URL_config.ini', old=url, new='#'+url)
|
||||
replace_url('./config/URL_config.ini', old=url, new='#' + url)
|
||||
raise RuntimeError('获取直播间数据失败,花椒直播间地址非固定,请使用主播主页地址进行录制')
|
||||
|
||||
|
||||
@@ -1847,7 +1847,7 @@ def get_huajiao_user_info(url: str, cookies: Union[str, None] = None, proxy_addr
|
||||
return anchor_name, None
|
||||
|
||||
else:
|
||||
live_id = url.split('?')[0].rsplit('/',maxsplit=1)[1]
|
||||
live_id = url.split('?')[0].rsplit('/', maxsplit=1)[1]
|
||||
data = get_huajiao_sn(live_id)
|
||||
if data:
|
||||
profile_url = f'https://www.huajiao.com/user/{data[2].split("?")[0]}'
|
||||
@@ -1891,6 +1891,37 @@ def get_huajiao_stream_url(url: str, proxy_addr: Union[str, None] = None, cookie
|
||||
return result
|
||||
|
||||
|
||||
@trace_error_decorator
|
||||
def get_liuxing_stream_url(url: str, proxy_addr: Union[str, None] = None, cookies: Union[str, None] = None) -> \
|
||||
Dict[str, Any]:
|
||||
headers = {
|
||||
'Accept': 'application/json, text/plain, */*',
|
||||
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
|
||||
'Referer': 'https://wap.7u66.com/198189?promoters=0',
|
||||
'User-Agent': 'Mozilla/5.0 (Linux; Android 8.0.0; SM-G955U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36 Edg/121.0.0.0',
|
||||
|
||||
}
|
||||
if cookies:
|
||||
headers['Cookie'] = cookies
|
||||
|
||||
room_id = url.split('?')[0].rsplit('/', maxsplit=1)[1]
|
||||
api = f'https://wap.7u66.com/api/ui/room/v1.0.0/live.ashx?promoters=0&roomidx={room_id}¤tUrl=https://www.7u66.com/{room_id}?promoters=0'
|
||||
json_str = get_req(url=api, proxy_addr=proxy_addr, headers=headers)
|
||||
json_data = json.loads(json_str)
|
||||
room_info = json_data['data']['roomInfo']
|
||||
anchor_name = room_info['nickname']
|
||||
live_status = room_info["live_stat"]
|
||||
result = {"anchor_name": anchor_name, "is_live": False}
|
||||
if live_status == 1:
|
||||
result["is_live"] = True
|
||||
idx = room_info['idx']
|
||||
live_id = room_info['liveId1']
|
||||
flv_url = f'https://txpull1.5see.com/live/{idx}/{live_id}.flv'
|
||||
result['flv_url'] = flv_url
|
||||
result['record_url'] = flv_url
|
||||
return result
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# 尽量用自己的cookie,以避免默认的不可用导致无法获取数据
|
||||
# 以下示例链接不保证时效性,请自行查看链接是否能正常访问
|
||||
@@ -1905,8 +1936,8 @@ if __name__ == '__main__':
|
||||
# room_url = 'https://live.bilibili.com/21593109' # b站直播
|
||||
# room_url = 'https://live.bilibili.com/23448867' # b站直播
|
||||
# 小红书直播
|
||||
# room_url = 'https://www.redelight.cn/hina/livestream/569077534207413574/1707413727088?appuid=5f3f478a00000000010005b3&'
|
||||
# room_url = 'https://www.xiaohongshu.com/hina/livestream/569098486282043893/1708661048594?appuid=5f3f478a00000000010005b3&'
|
||||
# room_url = 'https://www.redelight.cn/hina/livestream/569077534207413574?appuid=5f3f478a00000000010005b3&'
|
||||
# room_url = 'https://www.xiaohongshu.com/hina/livestream/569098486282043893?appuid=5f3f478a00000000010005b3&'
|
||||
# room_url = 'https://www.bigo.tv/cn/716418802' # bigo直播
|
||||
# room_url = 'https://app.blued.cn/live?id=Mp6G2R' # blued直播
|
||||
# room_url = 'https://play.afreecatv.com/sw7love' # afreecatv直播
|
||||
@@ -1928,6 +1959,7 @@ if __name__ == '__main__':
|
||||
# room_url = 'https://www.twitch.tv/gamerbee' # TwitchTV
|
||||
# room_url = 'https://www.liveme.com/zh/v/17141937295821012854/index.html' # LiveMe
|
||||
# room_url = 'https://www.huajiao.com/user/223184650' # 花椒直播
|
||||
# room_url = 'https://www.7u66.com/100960' # 流星直播
|
||||
|
||||
print(get_douyin_stream_data(room_url, proxy_addr=''))
|
||||
# print(get_tiktok_stream_data(room_url, proxy_addr=''))
|
||||
@@ -1955,4 +1987,5 @@ if __name__ == '__main__':
|
||||
# print(get_kugou_stream_url(room_url, proxy_addr=''))
|
||||
# print(get_twitchtv_stream_data(room_url, proxy_addr=''))
|
||||
# print(get_liveme_stream_url(room_url, proxy_addr=''))
|
||||
# print(get_huajiao_stream_url(room_url, proxy_addr=''))
|
||||
# print(get_huajiao_stream_url(room_url, proxy_addr=''))
|
||||
# print(get_liuxing_stream_url(room_url, proxy_addr=''))
|
||||
|
||||
Reference in New Issue
Block a user