From 0f43cb005602265956753582f8e502e335521275 Mon Sep 17 00:00:00 2001 From: ihmily <961532186@qq.com> Date: Tue, 7 May 2024 09:14:14 +0800 Subject: [PATCH] feat: add liuxing live record and fix huya live --- README.md | 21 +++++---- config/config.ini | 2 +- main.py | 111 +++++++++++++++++++++++++--------------------- spider.py | 53 +++++++++++++++++----- 4 files changed, 118 insertions(+), 69 deletions(-) diff --git a/README.md b/README.md index ec06c2a..50e214a 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ - [x] TwitchTV - [x] LiveMe - [x] 花椒直播 +- [x] 流星直播 - [ ] 更多平台正在更新中 @@ -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直播录制 diff --git a/config/config.ini b/config/config.ini index 5b83741..4bcc4b1 100644 --- a/config/config.ini +++ b/config/config.ini @@ -2,7 +2,7 @@ 直播保存路径(不填则默认) = 保存文件夹是否以作者区分 = 是 视频保存格式ts|mkv|flv|mp4|ts音频|mkv音频 = ts -原画|超清|高清|标清 = 原画 +原画|超清|高清|标清|流畅 = 原画 是否使用代理ip(是/否) = 是 代理地址 = 同一时间访问网络的线程数 = 3 diff --git a/main.py b/main.py index 59b4356..fe657fb 100644 --- a/main.py +++ b/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) \ No newline at end of file + time.sleep(3) diff --git a/spider.py b/spider.py index 6b72a4d..83434a4 100644 --- a/spider.py +++ b/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='')) \ No newline at end of file + # print(get_huajiao_stream_url(room_url, proxy_addr='')) + # print(get_liuxing_stream_url(room_url, proxy_addr=''))