mirror of
https://github.com/ihmily/DouyinLiveRecorder.git
synced 2025-12-25 21:36:46 +08:00
Fix douyin live update and bilibili live record bug
This commit is contained in:
parent
9be963d3b5
commit
fc3449e7d9
20
README.md
20
README.md
@ -24,10 +24,11 @@
|
||||
```
|
||||
.
|
||||
└── DouyinLiveRecorder/
|
||||
├── /api -> (get live stream api )
|
||||
├── /api -> (get live stream api )
|
||||
├── /config -> (config record)
|
||||
├── /log -> (save runing log file)
|
||||
├── /backup_config -> (backup file)
|
||||
├── /libs -> (dll file)
|
||||
├── main.py -> (main file)
|
||||
├── spider.py-> (get live url)
|
||||
├── web_rid.py -> (get web_rid)
|
||||
@ -36,6 +37,7 @@
|
||||
├── x-bogus.js -> (get douyin xbogus token)
|
||||
├── ffmpeg.exe -> (record video)
|
||||
├── index.html -> (play m3u8 and flv video)
|
||||
├── requirements.txt -> (library dependencies)
|
||||
```
|
||||
|
||||
</div>
|
||||
@ -47,12 +49,13 @@
|
||||
- 抖音录制需要使用到PC网页端直播间页面的Cookie,请先在config.ini配置文件中添加后再进行抖音录制
|
||||
- 注意事项① 录制使用到了ffmpeg,如果没有则无法进行录制,请将ffmpeg.exe放置运行文件同个文件夹
|
||||
- 注意事项② 录制Tiktok时需要使用vpn代理,请先在配置文件中设置开启代理并添加proxy_addr链接
|
||||
- 注意事项③ 如果电脑开启了`全局或者规则代理`,可不用添加proxy_addr参数值但仍需在config.ini配置文件中设置开启代理 (最好还是设置一下代理地址,降低出错概率)
|
||||
- 注意事项③ 如果电脑开启了`全局或者规则代理`,可不用添加proxy_addr参数值但仍需在config.ini配置文件中设置开启代理 (最好还是设置一下代理地址,否则很容易请求出错)
|
||||
- 注意事项④ 可以在URL_config.ini中的链接开头加上#,此时将不会录制该条链接对应的直播
|
||||
- 注意事项⑤ 测试时有可能会出现在IDE如Pycharm中运行代码进行直播录制,录制出来的视频却无法正常播放的现象,如果遇到这个问题 最好在命令控制台DOS界面运行代码,录制出来的视频即可正常播放。
|
||||
- 可使用 `pyinstaller -D或-F` 将代码打包成exe可执行文件 ,前提是已经安装了`pyinstaller`库
|
||||
- 当同时在录制多个直播时,最好线程数设置大一些,否则可能出现其中一个直播录制出错。当然设置的过大也没用,要同时考虑自身电脑的配置,如CPU内核数、网络带宽等限制。
|
||||
- 如果想直接使用打包好的录制软件,进入[Releases](https://github.com/ihmily/DouyinLiveRecorder/releases) 下载最新发布的 zip压缩包即可,可能有些电脑会报毒,直接忽略即可,这是pyinstaller打包的锅。
|
||||
- 如果要长时间挂着软件循环监测直播,最好循环时间设置长一点,避免因请求频繁导致被官方封禁IP 。
|
||||
|
||||
 
|
||||
|
||||
@ -83,7 +86,7 @@ B站:
|
||||
https://live.bilibili.com/320
|
||||
```
|
||||
|
||||
Tiktok目前只支持PC网页端地址(没下载app),其他平台 app端直播间分享地址和网页端长地址都能正常进行录制(抖音尽量用长链接,避免因短链接转换失效导致不能正常录制)。
|
||||
Tiktok目前只支持PC网页端地址(我没下载app),其他平台 app端直播间分享地址和网页端长地址都能正常进行录制(抖音尽量用长链接,避免因短链接转换失效导致不能正常录制)。
|
||||
|
||||
</div>
|
||||
|
||||
@ -105,7 +108,7 @@ GET https://hmily.vip/api/jx/live/?url=https://live.douyin.com/573716250978
|
||||
GET https://hmily.vip/api/jx/live/convert.php?url=https://v.douyin.com/iQLgKSj/
|
||||
```
|
||||
|
||||
在线播放m3u8视频地址:[https://jx.hmily.vip/play/ ](https://jx.hmily.vip/play/)
|
||||
在线播放m3u8和flv视频网站:[M3U8 在线视频播放器 ](https://jx.hmily.vip/play/)
|
||||
|
||||
 
|
||||
|
||||
@ -117,11 +120,18 @@ GET https://hmily.vip/api/jx/live/convert.php?url=https://v.douyin.com/iQLgKSj/
|
||||
|
||||
## ⏳提交日志
|
||||
|
||||
- 20230907
|
||||
- 修复了因抖音官方更新了版本导致的录制出错以及短链接转换出错
|
||||
|
||||
- 修复B站无法录制原画视频的bug
|
||||
|
||||
- 修改了配置文件字段,新增各平台自定义设置Cookie
|
||||
|
||||
- 20230903
|
||||
- 修复了Tiktok录制时报644无法录制的问题
|
||||
- 新增直播状态推送到钉钉和微信的功能,如有需要请看 [设置推送教程](https://d04vqdiqwr3.feishu.cn/docx/XFPwdDDvfobbzlxhmMYcvouynDh?from=from_copylink)
|
||||
- 最近比较忙,其他问题有时间再更新
|
||||
|
||||
|
||||
- 20230816
|
||||
- 修复斗鱼直播(官方更新了字段)和快手直播录制出错的问题
|
||||
- 20230814
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
* Author: Hmily
|
||||
* Github:https://github.com/ihmily
|
||||
* Date: 2023-07-20 21:06:20
|
||||
* Update: 2023-09-07 22:34:57
|
||||
* Copyright (c) 2023 by Hmily, All Rights Reserved.
|
||||
* Function:convert short url to long url
|
||||
* Address:https://github.com/ihmily/DouyinLiveRecorder
|
||||
@ -20,8 +21,8 @@ if(empty($_GET['url'])){
|
||||
$share_url=$_GET['url'];
|
||||
|
||||
$get_id=get_redirect_url($share_url);
|
||||
preg_match('/reflow\/(.*?)\?u_code/', $get_id, $room_id);
|
||||
preg_match('/&sec_user_id=(.*?)&ecom_share_track_params/', $get_id, $sec_user_id);
|
||||
preg_match('/reflow\/(.*?)\?/', $get_id, $room_id);
|
||||
preg_match('/sec_user_id=([\w\d_\-]+)&/', $get_id, $sec_user_id);
|
||||
$room_data=get_live_web_rid($room_id[1],$sec_user_id[1]);
|
||||
$title=$room_data[0];
|
||||
$web_rid=$room_data[1];
|
||||
@ -44,7 +45,7 @@ $return=
|
||||
exit(json_encode($return,448));
|
||||
|
||||
|
||||
// 抖音X-bogus算法,这里我直接封装成接口进行调用了
|
||||
// 抖音X-bogus算法,直接调用我封装的接口
|
||||
function get_xbogus($url) {
|
||||
$query = parse_url($url, PHP_URL_QUERY);
|
||||
$url = "http://43.138.133.177:8890/xbogus";
|
||||
@ -115,4 +116,6 @@ function get_redirect_url($url) {
|
||||
curl_close($curl);
|
||||
preg_match("/Location: (.*?)\r\n/iU",$ret,$location);
|
||||
return $location[1];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -4,12 +4,14 @@
|
||||
* Author: Hmily
|
||||
* Github:https://github.com/ihmily
|
||||
* Date: 2023-07-20 21:06:20
|
||||
* Update: 2023-08-05 23:35:00
|
||||
* Update: 2023-09-07 23:53:07
|
||||
* Copyright (c) 2023 by Hmily, All Rights Reserved.
|
||||
* Function:Spider the live stream url
|
||||
* Address:https://github.com/ihmily/DouyinLiveRecorder
|
||||
*/
|
||||
|
||||
|
||||
// 本API代码只有解析抖音、快手和虎牙的,有需要其他的可自己根据源码增加
|
||||
header('Content-type: application/json; charset=utf-8');
|
||||
|
||||
if(empty($_GET['url'])){
|
||||
@ -23,7 +25,7 @@ if (strpos($live_url, 'douyin') !== false) {
|
||||
// 判断是否是app端分享链接,如果是则转为PC网页端地址,否则无法解析
|
||||
// 示例链接:
|
||||
// $live_url="https://live.douyin.com/187615265444";
|
||||
$json_str=get_curl("https://hmily.vip/api/dy/live/convert.php?url=".$live_url);
|
||||
$json_str=get_curl("https://hmily.vip/api/jx/live/convert.php?url=".$live_url);
|
||||
$json_data=json_decode($json_str,true);
|
||||
$live_url = $json_data['long_url'];
|
||||
}
|
||||
@ -52,20 +54,37 @@ function get_douyin_json_data($url) {
|
||||
$cookies='ttwid=1%7CIkooT8SJQrpeYtHlSALuhz9BdcHpaaf9tHQRKHuDaYE%7C1687785070%7C6690250483b63b6482128174d0f93bd879614d76f1b6e03ca52e032cf7fbaafd; passport_csrf_token=52bece134ac246c81163cc93b72f86a6; passport_csrf_token_default=52bece134ac246c81163cc93b72f86a6; d_ticket=2b9e3eb3626216c0122f0d980f867deb7b414; n_mh=hvnJEQ4Q5eiH74-84kTFUyv4VK8xtSrpRZG1AhCeFNI; passport_auth_status=a74f300f376940d65914eb148d55ca96%2C9ca487aea255972120d502f736c5dd7b; passport_auth_status_ss=a74f300f376940d65914eb148d55ca96%2C9ca487aea255972120d502f736c5dd7b; sso_auth_status=52ecac30d95890cc7896c880366aa21a; sso_auth_status_ss=52ecac30d95890cc7896c880366aa21a; LOGIN_STATUS=1; store-region=cn-fj; store-region-src=uid; __security_server_data_status=1; __live_version__=%221.1.1.1853%22; live_can_add_dy_2_desktop=%220%22; xgplayer_user_id=528819598596; msToken=ZfXzPPa_KqQDF9wkHigKqgyUMIt33-qgLl1qqthGsAea4L69i9wxWaGH4GaQ9M_Q-eqhLpnD4v8FRGIj9KGJGIyLmjPkR1uepZ0gBaqhCkqK1KaauPXT_VK_uVgW6q4=; home_can_add_dy_2_desktop=%220%22; strategyABtestKey=%221689685952.92%22; FOLLOW_LIVE_POINT_INFO=%22MS4wLjABAAAAf6aekfyBsc4u8jMkeYbgnkFa0ksIWKWpGOywuyHXyo4%2F1689609600000%2F0%2F1689606316434%2F0%22; FOLLOW_NUMBER_YELLOW_POINT_INFO=%22MS4wLjABAAAAf6aekfyBsc4u8jMkeYbgnkFa0ksIWKWpGOywuyHXyo4%2F1689609600000%2F0%2F0%2F1689594083273%22; FORCE_LOGIN=%7B%22videoConsumedRemainSeconds%22%3A180%7D; volume_info=%7B%22isUserMute%22%3Afalse%2C%22isMute%22%3Atrue%2C%22volume%22%3A0.6%7D; device_web_cpu_core=8; device_web_memory_size=-1; webcast_local_quality=origin; csrf_session_id=0446f50cc7e08f146ad07351af90f413; __ac_nonce=064be522600a12daa29ff; __ac_signature=_02B4Z6wo00f0145FB4AAAIDCkga5P5okFMuOdAMAAIc3h1Lmbu.WZmNdgawlJBkHRSAf1yndkZFgF.zN2OHlE62.f.4ZFt740eSkTrQW8j3EM2s9s3vtK9LGh-h9jhUkgSbj4UOtYTqpCZZc88; webcast_leading_last_show_time=1690194481638; webcast_leading_total_show_times=1; odin_tt=6ebbe0a3c1b4e5bc6d333c5c7514fc88a288b3b03b1f0cf34826dee5d6d6394620f17fd4eb624b710954233f38fa3c67fd4a5338bffaa792a2cf71d1b51d837f079925497d6b372f47a577d779036a71; msToken=uHqyINCG79-ojuC5cXU6tYm0Av3BqNzqLkFGvbNw5QmSCtFY7xYHJjJ3wu-gk2Evj5QQ7D6UMsz2inlRN-aZf8xTGMAnpmgieOrygPqoK7QboFwCXR7aLi4KKcFXvFu2; tt_scid=BVvDLf3XEG4PZlY2-haad4.kR2BYWdq4X88b6-sPA2Wpg2lsSDI5M7YuZ7H-GPf.6646';
|
||||
|
||||
$html_str = get_curl($url,$headers,$cookies);
|
||||
preg_match('/<script id="RENDER_DATA" type="application\/json">(.*?)<\/script><script type=/', $html_str, $matches);
|
||||
$quote_json_str = $matches[1];
|
||||
$unquote_json_str = urldecode($quote_json_str);
|
||||
$json_data = json_decode($unquote_json_str, true);
|
||||
// print_r($html_str);
|
||||
|
||||
$pattern = '/self\.__pace_f\.push(.*?)<\/script><div hidden id/Us';
|
||||
$p_result = preg_match($pattern, $html_str, $matches);
|
||||
$pattern2 = '/state\\\":(.*?),\\\"isAsianGames/';
|
||||
$p_result2 = preg_match($pattern2, $matches[1], $matches2);
|
||||
$cleaned_string = str_replace("\\", "", $matches2[1].'}]}');
|
||||
$cleaned_string = preg_replace('/bdp_log=(.*?)&bdpsum=/', '', $cleaned_string);
|
||||
|
||||
$replacements = array(
|
||||
'"[' => '[',
|
||||
']"' => ']',
|
||||
'"{' => '{',
|
||||
'}"' => '}',
|
||||
'u0026' => '&'
|
||||
);
|
||||
|
||||
$cleaned_string = strtr($cleaned_string, $replacements);
|
||||
$json_str='{"state":'.$cleaned_string;
|
||||
// echo $json_str;
|
||||
$json_data = json_decode($json_str, true);
|
||||
return $json_data;
|
||||
|
||||
}
|
||||
|
||||
|
||||
# 第一种数据
|
||||
function get_douyin_stream_url($json_data) {
|
||||
$initialState = $json_data['app']['initialState'];
|
||||
$initialState = $json_data['state'];
|
||||
$streamStore = $initialState['streamStore'];
|
||||
$roomStore = $initialState['roomStore'];
|
||||
$is_login = $json_data['app']['odin']['user_is_login'];
|
||||
$streamData = $streamStore['streamData']['H265_streamData']['options'];
|
||||
$stream = $streamStore['streamData']['H265_streamData']['stream'];
|
||||
$stream2 = $streamStore['streamData']['H264_streamData']['stream'];
|
||||
@ -93,7 +112,7 @@ function get_douyin_stream_url($json_data) {
|
||||
|
||||
# 第二种数据(更好)
|
||||
function get_douyin_stream_url2($json_data,$live_url) {
|
||||
$roomStore = $json_data['app']['initialState']['roomStore'];
|
||||
$roomStore = $json_data['state']['roomStore'];
|
||||
$roomInfo = $roomStore['roomInfo'];
|
||||
$anchor_name = $roomInfo['anchor']['nickname'];
|
||||
$live_title = $roomInfo['room']['title'] ;
|
||||
@ -103,7 +122,6 @@ function get_douyin_stream_url2($json_data,$live_url) {
|
||||
if ($status == 4) {
|
||||
$data=["live_status"=>'主播未开播或者直播已经结束!'];
|
||||
} 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'];
|
||||
@ -128,7 +146,8 @@ function get_douyin_stream_url2($json_data,$live_url) {
|
||||
function get_kuaishou_stream_url($live_url){
|
||||
$headers = array(
|
||||
'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'
|
||||
'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',
|
||||
'Cookie:clientid=3; did=web_2e5935532808ea57f357c827b45abaf4; didv=1687682547000; client_key=65890b29; kpn=GAME_ZONE; clientid=3; did=web_2e5935532808ea57f357c827b45abaf4; client_key=65890b29; kpn=GAME_ZONE; userId=580178847; kuaishou.live.web_st=ChRrdWFpc2hvdS5saXZlLndlYi5zdBKgAQ-E2wk--dxc2ehil5tQ5PZxSAAy_WocJekwLrvD4yIZxEo4y76RBkXONqX9xSLhyX5WOyhWdsXrwH-Nj0RTgM4csF_UwnsIclnnZT6WNO2tfB3fmNHvZHAIRtqDl6hXsS1x8vwgHCii65me0EiPh1LK855TafkNx9A7wrTma6XPlCPL8L1GNKTjtiQB2L7Y0kuOp-l0zVzIidHhFvGXfFEaEgCrAu8bFEUPixNgRvVq1Nb0ZSIghKUYro_uVYFHrcP3wJ93ACmwb-oSRGVtcLhGUdaI43UoBTAB; kuaishou.live.web_ph=c371edbd1ecfdc90fb87ae8c0c8738ec6f3f; userId=580178847; kuaishou.live.bfb1s=477cb0011daca84b36b3a4676857e5a1'
|
||||
);
|
||||
$html_str = get_curl($live_url,$headers);
|
||||
preg_match('/__INITIAL_STATE__=(.*?);\(function/', $html_str, $matches);
|
||||
@ -170,8 +189,7 @@ function get_huya_stream_url($live_url){
|
||||
$gameLiveInfo = $json_data['data'][0]['gameLiveInfo'];
|
||||
$live_title=$gameLiveInfo['introduction'];
|
||||
$gameStreamInfoList = $json_data['data'][0]['gameStreamInfoList'];
|
||||
// var_dump($gameStreamInfoList);
|
||||
// exit();
|
||||
|
||||
$anchor_name = $gameLiveInfo['nick'];
|
||||
if (count($gameStreamInfoList)==0) {
|
||||
$data=["live_status"=>'主播未开播或者直播已经结束!'];
|
||||
@ -231,3 +249,10 @@ function get_curl($url,$headers=array(),$cookies=''){
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,2 +1 @@
|
||||
https://live.douyin.com/326500301367
|
||||
https://live.kuaishou.com/u/yall1102
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
[1]
|
||||
[录制设置]
|
||||
直播保存路径(不填则默认) =
|
||||
视频保存格式ts|mkv|flv|mp4|ts音频|mkv音频 = MP4
|
||||
视频保存格式ts|mkv|flv|mp4|ts音频|mkv音频 = mp4
|
||||
原画|超清|高清|标清 = 原画
|
||||
是否使用代理ip(是/否) = 否
|
||||
代理地址 =
|
||||
是否使用代理ip(是/否) = 是
|
||||
代理地址 =
|
||||
同一时间访问网络的线程数 = 3
|
||||
循环时间(秒) = 60
|
||||
排队读取网址时间(秒) = 0
|
||||
@ -15,5 +15,19 @@ 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
|
||||
|
||||
[推送配置]
|
||||
直播状态通知(可选微信|钉钉或者两个都填) =
|
||||
钉钉推送接口链接 =
|
||||
微信推送接口链接 =
|
||||
钉钉通知@对象(填手机号) =
|
||||
|
||||
[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
|
||||
快手cookie =
|
||||
tiktok_cookie =
|
||||
虎牙cookie =
|
||||
斗鱼cookie =
|
||||
yy_cookie =
|
||||
b站cookie =
|
||||
|
||||
|
||||
144
main.py
144
main.py
@ -4,14 +4,17 @@
|
||||
Author: Hmily
|
||||
Github: https://github.com/ihmily
|
||||
Date: 2023-07-17 23:52:05
|
||||
Update: 2023-09-03 19:18:36
|
||||
Update: 2023-09-07 10:56:25
|
||||
Copyright (c) 2023 by Hmily, All Rights Reserved.
|
||||
Function: Record live stream video.
|
||||
"""
|
||||
|
||||
|
||||
import functools
|
||||
import random
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
import urllib.parse
|
||||
import configparser
|
||||
import subprocess
|
||||
@ -24,7 +27,7 @@ from web_rid import *
|
||||
from msg_push import *
|
||||
|
||||
# 版本号
|
||||
version = "v1.0.6"
|
||||
version = "v1.0.7"
|
||||
platforms = "抖音|Tiktok|快手|虎牙|斗鱼|YY|B站"
|
||||
|
||||
# --------------------------log日志-------------------------------------
|
||||
@ -70,6 +73,19 @@ default_path = os.getcwd()
|
||||
|
||||
|
||||
# --------------------------用到的函数-------------------------------------
|
||||
def trace_error_decorator(func):
|
||||
@functools.wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
try:
|
||||
return func(*args, **kwargs)
|
||||
except Exception as e:
|
||||
error_line = traceback.extract_tb(e.__traceback__)[-1].lineno
|
||||
error_info=f"错误信息: type: {type(e).__name__}, {str(e)} in function {func.__name__} at line: {error_line}"
|
||||
print(error_info)
|
||||
logger.warning(error_info)
|
||||
return []
|
||||
return wrapper
|
||||
|
||||
|
||||
def display_info():
|
||||
# TODO: 显示当前录制配置信息
|
||||
@ -231,12 +247,10 @@ def change_max_connect():
|
||||
print("同一时间访问网络的线程数动态改为", max_request)
|
||||
|
||||
|
||||
@trace_error_decorator
|
||||
def get_douyin_stream_url(json_data):
|
||||
# TODO: 获取抖音直播源地址
|
||||
data = [] # 定义一个返回数据列表
|
||||
|
||||
room_store = json_data['app']['initialState']['roomStore']
|
||||
room_info = room_store['roomInfo']
|
||||
room_info = json_data['roomInfo']
|
||||
anchor_name = room_info['anchor']['nickname']
|
||||
status = 4
|
||||
# 获取直播间状态
|
||||
@ -270,10 +284,9 @@ def get_douyin_stream_url(json_data):
|
||||
return data
|
||||
|
||||
|
||||
@trace_error_decorator
|
||||
def get_tiktok_stream_url(json_data):
|
||||
# TODO: 获取Tiktok直播源地址
|
||||
data = []
|
||||
|
||||
live_room = json_data['LiveRoom']['liveRoomUserInfo']
|
||||
anchor_name = live_room['user']['nickname']
|
||||
status = live_room['user']["status"]
|
||||
@ -305,10 +318,9 @@ def get_tiktok_stream_url(json_data):
|
||||
return data
|
||||
|
||||
|
||||
@trace_error_decorator
|
||||
def get_kuaishou_stream_url(json_data):
|
||||
# TODO: 获取快手直播源地址
|
||||
data = []
|
||||
|
||||
live_room = json_data['liveroom']
|
||||
anchor_name = live_room['author']['name']
|
||||
# 获取直播间状态
|
||||
@ -319,23 +331,26 @@ def get_kuaishou_stream_url(json_data):
|
||||
else:
|
||||
stream_data = live_room['liveStream']['playUrls'][0]['adaptationSet']['representation']
|
||||
# stream_data数组中索引从小到大分别是高清、超清、蓝光4M、蓝光8M (每个直播间不一样)
|
||||
quality_list = [i for i in range(len(stream_data))][::-1]
|
||||
while len(quality_list) < 4:
|
||||
quality_list.append(quality_list[-1])
|
||||
|
||||
if video_quality == "原画" or video_quality == "蓝光":
|
||||
flv_url = stream_data[-1]['url']
|
||||
flv_url = stream_data[quality_list[0]]['url']
|
||||
elif video_quality == "超清":
|
||||
flv_url = stream_data[-2]['url']
|
||||
flv_url = stream_data[quality_list[1]]['url']
|
||||
elif video_quality == "高清":
|
||||
flv_url = stream_data[1]['url']
|
||||
flv_url = stream_data[quality_list[2]]['url']
|
||||
elif video_quality == "标清":
|
||||
flv_url = stream_data[0]['url']
|
||||
flv_url = stream_data[quality_list[3]]['url']
|
||||
|
||||
data = [anchor_name, True, flv_url, flv_url] # 快手只有flv视频流
|
||||
return data
|
||||
|
||||
|
||||
@trace_error_decorator
|
||||
def get_huya_stream_url(json_data):
|
||||
# TODO: 获取虎牙直播源地址
|
||||
data = []
|
||||
|
||||
game_live_info = json_data['data'][0]['gameLiveInfo']
|
||||
stream_info_list = json_data['data'][0]['gameStreamInfoList']
|
||||
anchor_name = game_live_info['nick']
|
||||
@ -377,9 +392,9 @@ def get_huya_stream_url(json_data):
|
||||
return data
|
||||
|
||||
|
||||
@trace_error_decorator
|
||||
def get_douyu_stream_url(json_data):
|
||||
# TODO: 获取斗鱼直播源地址
|
||||
data = [] # 定义一个返回数据列表
|
||||
|
||||
room_info = json_data.get('pageContext',json_data)['pageProps']['room']['roomInfo']['roomInfo']
|
||||
anchor_name = room_info['nickname']
|
||||
@ -405,10 +420,9 @@ def get_douyu_stream_url(json_data):
|
||||
return data
|
||||
|
||||
|
||||
@trace_error_decorator
|
||||
def get_yy_stream_url(json_data):
|
||||
# TODO: 获取YY直播源地址
|
||||
data = []
|
||||
|
||||
anchor_name = json_data['anchor_name']
|
||||
if 'avp_info_res' not in json_data:
|
||||
data = [anchor_name, False, '', '']
|
||||
@ -421,9 +435,9 @@ def get_yy_stream_url(json_data):
|
||||
return data
|
||||
|
||||
|
||||
@trace_error_decorator
|
||||
def get_bilibili_stream_url(json_data):
|
||||
# TODO: 获取B站直播源地址
|
||||
data = []
|
||||
|
||||
anchor_name = json_data['roomInfoRes']['data']['anchor_info']['base_info']['uname']
|
||||
playurl_info = json_data['roomInitRes']['data']['playurl_info']
|
||||
@ -433,19 +447,19 @@ def get_bilibili_stream_url(json_data):
|
||||
def get_url(m, n):
|
||||
format_list = ['.flv', '.m3u8']
|
||||
# 字典中的键就是qn,其中qn=30000为杜比 20000为4K 10000为原画 400蓝光 250超清 150高清,qn=0是默认画质
|
||||
quality_list = {'10000': 'bluray', '400': '4000', '250': '2500', '150': '1500'}
|
||||
quality_list = {'10000': '', '400': '_4000', '250': '_2500', '150': '_1500'}
|
||||
|
||||
stream_data = playurl_info['playurl']['stream'][m]['format'][0]['codec'][0]
|
||||
accept_qn_list = stream_data['accept_qn']
|
||||
while len(accept_qn_list) < 4:
|
||||
accept_qn_list.append(accept_qn_list[0])
|
||||
accept_qn_list.append(accept_qn_list[-1])
|
||||
base_url = stream_data['base_url']
|
||||
host = stream_data['url_info'][0]['host']
|
||||
extra = stream_data['url_info'][0]['extra']
|
||||
format = format_list[m]
|
||||
url_type = format_list[m]
|
||||
qn = str(accept_qn_list[n])
|
||||
quality = quality_list[qn]
|
||||
base_url = re.sub(r'(\d+)' + f'(?={format}\?)', quality, base_url)
|
||||
base_url = re.sub(r'_(\d+)' + f'(?={url_type}\?)', quality, base_url)
|
||||
extra = re.sub('&qn=0', f'&qn={qn}', extra)
|
||||
url = host + base_url + extra
|
||||
return url
|
||||
@ -491,7 +505,7 @@ def start_record(line, count_variable=-1):
|
||||
# 判断如果是浏览器长链接
|
||||
with semaphore:
|
||||
# 使用semaphore来控制同时访问资源的线程数量
|
||||
json_data = get_douyin_stream_data(record_url, cookies_set) # 注意这里需要配置文件中的cookie
|
||||
json_data = get_douyin_stream_data(record_url, dy_cookie) # 注意这里需要配置文件中的cookie
|
||||
port_info = get_douyin_stream_url(json_data)
|
||||
elif record_url.find("https://v.douyin.com/") > -1:
|
||||
# 判断如果是app分享链接
|
||||
@ -503,39 +517,39 @@ def start_record(line, count_variable=-1):
|
||||
new_record_url = "https://live.douyin.com/" + str(web_rid)
|
||||
not_record_list.append(new_record_url)
|
||||
with semaphore:
|
||||
json_data = get_douyin_stream_data(new_record_url, cookies_set)
|
||||
json_data = get_douyin_stream_data(new_record_url, dy_cookie)
|
||||
port_info = get_douyin_stream_url(json_data)
|
||||
|
||||
elif record_url.find("https://www.tiktok.com/") > -1:
|
||||
with semaphore:
|
||||
if use_proxy:
|
||||
if global_proxy or proxy_addr != '':
|
||||
json_data = get_tiktok_stream_data(record_url, proxy_addr)
|
||||
json_data = get_tiktok_stream_data(record_url, proxy_addr,tiktok_cookie)
|
||||
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)
|
||||
json_data = get_kuaishou_stream_data(record_url, ks_cookie)
|
||||
port_info = get_kuaishou_stream_url(json_data)
|
||||
|
||||
elif record_url.find("https://www.huya.com/") > -1:
|
||||
with semaphore:
|
||||
json_data = get_huya_stream_data(record_url)
|
||||
json_data = get_huya_stream_data(record_url,hy_cookie)
|
||||
port_info = get_huya_stream_url(json_data)
|
||||
|
||||
elif record_url.find("https://www.douyu.com/") > -1:
|
||||
with semaphore:
|
||||
json_data = get_douyu_info_data(record_url)
|
||||
port_info = get_douyu_stream_url(json_data)
|
||||
port_info = get_douyu_stream_url(json_data,douyu_cookie)
|
||||
|
||||
elif record_url.find("https://www.yy.com/") > -1:
|
||||
with semaphore:
|
||||
json_data = get_yy_stream_data(record_url)
|
||||
json_data = get_yy_stream_data(record_url,yy_cookie)
|
||||
port_info = get_yy_stream_url(json_data)
|
||||
|
||||
elif record_url.find("https://live.bilibili.com/") > -1:
|
||||
with semaphore:
|
||||
json_data = get_bilibili_stream_data(record_url)
|
||||
json_data = get_bilibili_stream_data(record_url,bili_cookie)
|
||||
port_info = get_bilibili_stream_url(json_data)
|
||||
|
||||
# print("端口信息:" + str(port_info))
|
||||
@ -1019,23 +1033,28 @@ t3 = threading.Thread(target=backup_file_start, args=(), daemon=True)
|
||||
t3.start()
|
||||
Monitoring = 0
|
||||
|
||||
# 如果开启了电脑全局/规则代理,可以不用再在配置文件中填写代理地址
|
||||
# 录制tiktok时,如果开启了电脑全局/规则代理,可以不用再在配置文件中填写代理地址
|
||||
# 但强烈建议还是配置一下代理地址,否则非常不稳定
|
||||
try:
|
||||
# 检测电脑是否开启了全局/规则代理
|
||||
print('系统代理检测中...')
|
||||
response_g = urllib.request.urlopen("https://www.tiktok.com/", timeout=10)
|
||||
response_g = urllib.request.urlopen("https://www.tiktok.com", timeout=15)
|
||||
global_proxy = True
|
||||
print('系统代理已开启√ 注意:配置文件中的代理设置也要开启才会生效哦!')
|
||||
|
||||
except Exception as e:
|
||||
print('INFO:未检测到网络代理,请检查代理是否生效(若无需录制Tiktok直播请忽略此条提示)')
|
||||
print('INFO:未检测到全局/规则网络代理,请检查代理配置(若无需录制Tiktok直播请忽略此条提示)')
|
||||
|
||||
|
||||
def read_config_value(config, section, option, default_value):
|
||||
try:
|
||||
config.read(config_file, encoding=encoding)
|
||||
if '1' not in config.sections():
|
||||
config.add_section('1')
|
||||
if '录制设置' not in config.sections():
|
||||
config.add_section('录制设置')
|
||||
if '推送配置' not in config.sections():
|
||||
config.add_section('推送配置')
|
||||
if 'Cookie' not in config.sections():
|
||||
config.add_section('Cookie')
|
||||
return config.get(section, option)
|
||||
except (configparser.NoSectionError, configparser.NoOptionError):
|
||||
config.set(section, option, str(default_value))
|
||||
@ -1066,28 +1085,34 @@ while True:
|
||||
with open(url_config_file, 'a+', encoding=encoding) as f:
|
||||
f.write(inurl)
|
||||
|
||||
video_save_path = read_config_value(config, '1', '直播保存路径(不填则默认)', "")
|
||||
video_save_type = read_config_value(config, '1', '视频保存格式TS|MKV|FLV|MP4|TS音频|MKV音频', "MP4")
|
||||
video_quality = read_config_value(config, '1', '原画|超清|高清|标清', "原画")
|
||||
use_proxy = read_config_value(config, '1', '是否使用代理ip(是/否)', "是")
|
||||
proxy_addr = read_config_value(config, '1', '代理地址', "")
|
||||
max_request = int(read_config_value(config, '1', '同一时间访问网络的线程数', 3))
|
||||
video_save_path = read_config_value(config, '录制设置', '直播保存路径(不填则默认)', "")
|
||||
video_save_type = read_config_value(config, '录制设置', '视频保存格式TS|MKV|FLV|MP4|TS音频|MKV音频', "mp4")
|
||||
video_quality = read_config_value(config, '录制设置', '原画|超清|高清|标清', "原画")
|
||||
use_proxy = read_config_value(config, '录制设置', '是否使用代理ip(是/否)', "是")
|
||||
proxy_addr = read_config_value(config, '录制设置', '代理地址', "")
|
||||
max_request = int(read_config_value(config, '录制设置', '同一时间访问网络的线程数', 3))
|
||||
semaphore = threading.Semaphore(max_request)
|
||||
delay_default = int(read_config_value(config, '1', '循环时间(秒)', 60))
|
||||
local_delay_default = int(read_config_value(config, '1', '排队读取网址时间(秒)', 0))
|
||||
video_m3u8 = read_config_value(config, '1', '是否显示直播地址', "否")
|
||||
loop_time = read_config_value(config, '1', '是否显示循环秒数', "否")
|
||||
Splitvideobysize = read_config_value(config, '1', 'TS格式分段录制是否开启', "否")
|
||||
Splitsize = int(read_config_value(config, '1', '视频分段大小(兆)', '1000'))
|
||||
tsconvert_to_mp4 = read_config_value(config, '1', 'TS录制完成后自动增加生成MP4格式', "否")
|
||||
tsconvert_to_m4a = read_config_value(config, '1', 'TS录制完成后自动增加生成m4a格式', "否")
|
||||
delFilebeforeconversion = read_config_value(config, '1', '追加格式后删除原文件', "否")
|
||||
create_time_file = read_config_value(config, '1', '生成时间文件', "否")
|
||||
live_status_push = read_config_value(config, '1', '直播状态通知(可选微信|钉钉或者两个都填)', "")
|
||||
dingtalk_api_url = read_config_value(config, '1', '钉钉推送接口链接', "")
|
||||
xizhi_api_url = read_config_value(config, '1', '微信推送接口链接', "")
|
||||
dingtalk_phone_num = read_config_value(config, '1', '钉钉通知@对象(填手机号)', "")
|
||||
cookies_set = read_config_value(config, '1', 'cookie(录制抖音必须要有)', '')
|
||||
delay_default = int(read_config_value(config, '录制设置', '循环时间(秒)', 60))
|
||||
local_delay_default = int(read_config_value(config, '录制设置', '排队读取网址时间(秒)', 0))
|
||||
video_m3u8 = read_config_value(config, '录制设置', '是否显示直播地址', "否")
|
||||
loop_time = read_config_value(config, '录制设置', '是否显示循环秒数', "否")
|
||||
Splitvideobysize = read_config_value(config, '录制设置', 'TS格式分段录制是否开启', "否")
|
||||
Splitsize = int(read_config_value(config, '录制设置', '视频分段大小(兆)', '1000'))
|
||||
tsconvert_to_mp4 = read_config_value(config, '录制设置', 'TS录制完成后自动增加生成MP4格式', "否")
|
||||
tsconvert_to_m4a = read_config_value(config, '录制设置', 'TS录制完成后自动增加生成m4a格式', "否")
|
||||
delFilebeforeconversion = read_config_value(config, '录制设置', '追加格式后删除原文件', "否")
|
||||
create_time_file = read_config_value(config, '录制设置', '生成时间文件', "否")
|
||||
live_status_push = read_config_value(config, '推送配置', '直播状态通知(可选微信|钉钉或者两个都填)', "")
|
||||
dingtalk_api_url = read_config_value(config, '推送配置', '钉钉推送接口链接', "")
|
||||
xizhi_api_url = read_config_value(config, '推送配置', '微信推送接口链接', "")
|
||||
dingtalk_phone_num = read_config_value(config, '推送配置', '钉钉通知@对象(填手机号)', "")
|
||||
dy_cookie = read_config_value(config, 'Cookie', '抖音cookie(录制抖音必须要有)', '')
|
||||
ks_cookie = read_config_value(config, 'Cookie', '快手cookie', '')
|
||||
tiktok_cookie = read_config_value(config, 'Cookie', 'Tiktok_cookie', '')
|
||||
hy_cookie = read_config_value(config, 'Cookie', '虎牙cookie', '')
|
||||
douyu_cookie = read_config_value(config, 'Cookie', '斗鱼cookie', '')
|
||||
yy_cookie = read_config_value(config, 'Cookie', 'YY_cookie', '')
|
||||
bili_cookie = read_config_value(config, 'Cookie', 'B站cookie', '')
|
||||
|
||||
if len(video_save_type) > 0:
|
||||
if video_save_type.upper().lower() == "FLV".lower():
|
||||
@ -1208,5 +1233,4 @@ while True:
|
||||
firstRunOtherLine = False
|
||||
|
||||
# 总体循环3s
|
||||
time.sleep(3)
|
||||
|
||||
time.sleep(3)
|
||||
130
spider.py
130
spider.py
@ -4,12 +4,11 @@
|
||||
Author: Hmily
|
||||
Github:https://github.com/ihmily
|
||||
Date: 2023-07-15 23:15:00
|
||||
Update: 2023-09-03 19:18:36
|
||||
Update: 2023-09-07 20:25:16
|
||||
Copyright (c) 2023 by Hmily, All Rights Reserved.
|
||||
Function: Get live stream data.
|
||||
"""
|
||||
|
||||
|
||||
import hashlib
|
||||
import time
|
||||
import urllib.parse
|
||||
@ -23,31 +22,40 @@ import urllib.request
|
||||
no_proxy_handler = urllib.request.ProxyHandler({})
|
||||
opener = urllib.request.build_opener(no_proxy_handler)
|
||||
|
||||
|
||||
# 直接选择从网页HTML中获取直播间数据
|
||||
def get_douyin_stream_data(url, cookies):
|
||||
def get_douyin_stream_data(url, cookies=''):
|
||||
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'
|
||||
if cookies != '':
|
||||
cookie = 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': cookies
|
||||
'Cookie': cookie
|
||||
}
|
||||
|
||||
# response = requests.get(url, headers=headers)
|
||||
# html_str = response.text
|
||||
# 使用更底层的urllib内置库,防止开启代理时导致的抖音录制SSL 443报错
|
||||
req = urllib.request.Request(url, headers=headers)
|
||||
response = opener.open(req,timeout=10)
|
||||
response = opener.open(req, timeout=15)
|
||||
html_str = response.read().decode('utf-8')
|
||||
quote_json_str = re.search('<script id="RENDER_DATA" type="application\/json">(.*?)<\/script><script type=',
|
||||
html_str).group(1)
|
||||
unquote_json_str = urllib.parse.unquote(quote_json_str)
|
||||
json_data = json.loads(unquote_json_str)
|
||||
json_str = re.findall(r'(\{\\\"state\\\"\:\{\\\"appStore\\\"\:.*?)\]\\n\"\]\)', html_str)[-1]
|
||||
cleaned_string = re.sub('bdp_log=(.*?)&bdpsum=', '', json_str.replace('\\', '')).replace(r'u0026', r'&')
|
||||
cleaned_string = cleaned_string.replace('"[', '[').replace(']"', ']').replace('"{', '{').replace('}"', '}')
|
||||
room_store = re.search('"roomStore":(.*?),"linkmicStore"', cleaned_string, re.S).group(1)
|
||||
json_data = json.loads(room_store)
|
||||
return json_data
|
||||
|
||||
|
||||
def get_tiktok_stream_data(url, proxy_addr):
|
||||
def get_tiktok_stream_data(url, proxy_addr, cookies=''):
|
||||
cookie = 'ttwid=1%7CM-rF193sJugKuNz2RGNt-rh6pAAR9IMceUSzlDnPCNI%7C1683274418%7Cf726d4947f2fc37fecc7aeb0cdaee52892244d04efde6f8a8edd2bb168263269; tiktok_webapp_theme=light; tt_chain_token=VWkygAWDlm1cFg/k8whmOg==; passport_csrf_token=6e422c5a7991f8cec7033a8082921510; passport_csrf_token_default=6e422c5a7991f8cec7033a8082921510; d_ticket=f8c267d4af4523c97be1ccb355e9991e2ae06; odin_tt=320b5f386cdc23f347be018e588873db7f7aea4ea5d1813681c3fbc018ea025dde957b94f74146dbc0e3612426b865ccb95ec8abe4ee36cca65f15dbffec0deff7b0e69e8ea536d46e0f82a4fc37d211; cmpl_token=AgQQAPNSF-RO0rT04baWtZ0T_jUjl4fVP4PZYM2QPw; uid_tt=319b558dbba684bb1557206c92089cd113a875526a89aee30595925d804b81c7; uid_tt_ss=319b558dbba684bb1557206c92089cd113a875526a89aee30595925d804b81c7; sid_tt=ad5e736f4bedb2f6d42ccd849e706b1d; sessionid=ad5e736f4bedb2f6d42ccd849e706b1d; sessionid_ss=ad5e736f4bedb2f6d42ccd849e706b1d; store-idc=useast5; store-country-code=us; store-country-code-src=uid; tt-target-idc=useast5; tt-target-idc-sign=qXNk0bb1pDQ0FbCNF120Pl9WWMLZg9Edv5PkfyCbS4lIk5ieW5tfLP7XWROnN0mEaSlc5hg6Oji1pF-yz_3ZXnUiNMrA9wNMPvI6D9IFKKVmq555aQzwPIGHv0aQC5dNRgKo5Z5LBkgxUMWEojTKclq2_L8lBciw0IGdhFm_XyVJtbqbBKKgybGDLzK8ZyxF4Jl_cYRXaDlshZjc38JdS6wruDueRSHe7YvNbjxCnApEFUv-OwJANSPU_4rvcqpVhq3JI2VCCfw-cs_4MFIPCDOKisk5EhAo2JlHh3VF7_CLuv80FXg_7ZqQ2pJeMOog294rqxwbbQhl3ATvjQV_JsWyUsMd9zwqecpylrPvtySI2u1qfoggx1owLrrUynee1R48QlanLQnTNW_z1WpmZBgVJqgEGLwFoVOmRzJuFFNj8vIqdjM2nDSdWqX8_wX3wplohkzkPSFPfZgjzGnQX28krhgTytLt7BXYty5dpfGtsdb11WOFHM6MZ9R9uLVB; sid_guard=ad5e736f4bedb2f6d42ccd849e706b1d%7C1690990657%7C15525213%7CMon%2C+29-Jan-2024+08%3A11%3A10+GMT; sid_ucp_v1=1.0.0-KGM3YzgwYjZhODgyYWI1NjIwNTA0NjBmOWUxMGRhMjIzYTI2YjMxNDUKGAiqiJ30keKD5WQQwfCppgYYsws4AkDsBxAEGgd1c2Vhc3Q1IiBhZDVlNzM2ZjRiZWRiMmY2ZDQyY2NkODQ5ZTcwNmIxZA; ssid_ucp_v1=1.0.0-KGM3YzgwYjZhODgyYWI1NjIwNTA0NjBmOWUxMGRhMjIzYTI2YjMxNDUKGAiqiJ30keKD5WQQwfCppgYYsws4AkDsBxAEGgd1c2Vhc3Q1IiBhZDVlNzM2ZjRiZWRiMmY2ZDQyY2NkODQ5ZTcwNmIxZA; tt_csrf_token=dD0EIH8q-pe3qDQsCyyD1jLN6KizJDRjOEyk; __tea_cache_tokens_1988={%22_type_%22:%22default%22%2C%22user_unique_id%22:%227229608516049831425%22%2C%22timestamp%22:1683274422659}; ttwid=1%7CM-rF193sJugKuNz2RGNt-rh6pAAR9IMceUSzlDnPCNI%7C1694002151%7Cd89b77afc809b1a610661a9d1c2784d80ebef9efdd166f06de0d28e27f7e4efe; msToken=KfJAVZ7r9D_QVeQlYAUZzDFbc1Yx-nZz6GF33eOxgd8KlqvTg1lF9bMXW7gFV-qW4MCgUwnBIhbiwU9kdaSpgHJCk-PABsHCtTO5J3qC4oCTsrXQ1_E0XtbqiE4OVLZ_jdF1EYWgKNPT2SnwGkQ=; msToken=KfJAVZ7r9D_QVeQlYAUZzDFbc1Yx-nZz6GF33eOxgd8KlqvTg1lF9bMXW7gFV-qW4MCgUwnBIhbiwU9kdaSpgHJCk-PABsHCtTO5J3qC4oCTsrXQ1_E0XtbqiE4OVLZ_jdF1EYWgKNPT2SnwGkQ='
|
||||
if cookies != '':
|
||||
cookie = cookies
|
||||
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'
|
||||
'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',
|
||||
'Cookie': cookie
|
||||
}
|
||||
|
||||
if proxy_addr != '':
|
||||
@ -73,44 +81,54 @@ def get_tiktok_stream_data(url, proxy_addr):
|
||||
return json_data
|
||||
|
||||
|
||||
def get_kuaishou_stream_data(url):
|
||||
def get_kuaishou_stream_data(url, cookies=''):
|
||||
cookie = 'did=web_7a4e65ac197566d457bc452ee5ade7d0; clientid=3; did=web_7a4e65ac197566d457bc452ee5ade7d0; client_key=65890b29; kpn=GAME_ZONE; kuaishou.live.bfb1s=3e261140b0cf7444a0ba411c6f227d88'
|
||||
if cookies != '':
|
||||
cookie = 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',
|
||||
'Cookie': cookie
|
||||
}
|
||||
|
||||
req = urllib.request.Request(url, headers=headers)
|
||||
response = opener.open(req,timeout=10)
|
||||
response = opener.open(req, timeout=15)
|
||||
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
|
||||
|
||||
def get_huya_stream_data(url):
|
||||
|
||||
def get_huya_stream_data(url, cookies=''):
|
||||
cookie = 'huya_ua=webh5&0.0.1&websocket; SoundValue=0.50; alphaValue=0.80; isInLiveRoom=true; game_did=-GcWYDglXNu2ZzqqTr4X-L4PSTclU2iheFm; Hm_lvt_51700b6c722f5bb4cf39906a596ea41f=1691210433,1691477318; udb_deviceid=w_610934293339279360; __yamid_tt1=0.5879880896254449; __yamid_new=C9EFFE0C63A00001A7A94510B5E718A6; guid=0a70d5e7b1d2cd644301d168d268de7b; guid=0a70d5e7b1d2cd644301d168d268de7b; udb_cred=CnDN6T9nhzPKEPgJieRfkuh2PcVTTfwhGVayc7q49srtD2angI9ShGfVHENqGqcGVvyssMbG1spibOt1mjsa57ZsNwEJ1sYVRedE_rsSN30WBp783NmwViE2I-Zh1yPV1MD6NRQURwYmyAUA5YOaY8iT; udb_passdata=3'
|
||||
if cookies != '':
|
||||
cookie = 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',
|
||||
'Cookie': cookie
|
||||
}
|
||||
|
||||
req = urllib.request.Request(url, headers=headers)
|
||||
response = opener.open(req,timeout=10)
|
||||
response = opener.open(req, timeout=15)
|
||||
html_str = response.read().decode('utf-8')
|
||||
json_str = re.findall('stream: (\{"data".*?),"iWebDefaultBitRate"', html_str)[0]
|
||||
json_data = json.loads(json_str + '}')
|
||||
return json_data
|
||||
|
||||
|
||||
def md5(data):
|
||||
return hashlib.md5(data.encode('utf-8')).hexdigest()
|
||||
|
||||
def get_token_js(rid,did,cdn='ws-h5', rate="0"):
|
||||
|
||||
def get_token_js(rid, did):
|
||||
"""
|
||||
通过PC网页端的接口获取完整直播源。
|
||||
:param cdn: 主线路ws-h5、备用线路tct-h5
|
||||
:param rate: 1流畅;2高清;3超清;4蓝光4M;0蓝光8M或10M
|
||||
"""
|
||||
url = f'https://www.douyu.com/{rid}'
|
||||
response = opener.open(url, timeout=10)
|
||||
response = opener.open(url, timeout=15)
|
||||
html_str = response.read().decode('utf-8')
|
||||
result = re.search(r'(vdwdae325w_64we[\s\S]*function ub98484234[\s\S]*?)function', html_str).group(1)
|
||||
func_ub9 = re.sub(r'eval.*?;}', 'strc;}', result)
|
||||
@ -126,14 +144,13 @@ def get_token_js(rid,did,cdn='ws-h5', rate="0"):
|
||||
func_sign = func_sign.replace('CryptoJS.MD5(cb).toString()', '"' + rb + '"')
|
||||
|
||||
js = execjs.compile(func_sign)
|
||||
params = js.call('sign', rid, did, t10)
|
||||
params = js.call('sign', rid, did, t10)
|
||||
# print(params)
|
||||
params_list=re.findall('=(.*?)(?=&|$)',params)
|
||||
params_list = re.findall('=(.*?)(?=&|$)', params)
|
||||
return params_list
|
||||
|
||||
|
||||
def get_douyu_info_data(url):
|
||||
|
||||
match_rid = re.search('rid=(.*?)&', url)
|
||||
if match_rid:
|
||||
rid = match_rid.group(1)
|
||||
@ -144,85 +161,97 @@ def get_douyu_info_data(url):
|
||||
}
|
||||
url = f'https://m.douyu.com/{rid}'
|
||||
req = urllib.request.Request(url, headers=headers)
|
||||
response = opener.open(req, timeout=10)
|
||||
response = opener.open(req, timeout=15)
|
||||
|
||||
html_str = response.read().decode('utf-8')
|
||||
json_str = re.search('ssr_pageContext" type="application\/json">(.*?)<\/script>', html_str).group(1)
|
||||
# print(json_str)
|
||||
json_data=json.loads(json_str)
|
||||
json_data = json.loads(json_str)
|
||||
return json_data
|
||||
|
||||
def get_douyu_stream_data(rid,rate='-1'):
|
||||
|
||||
def get_douyu_stream_data(rid, rate='-1', cookies=''):
|
||||
did = '10000000000000000000000000003306'
|
||||
params_list=get_token_js(rid, did, cdn='ws-h5', rate=rate)
|
||||
|
||||
params_list = get_token_js(rid, did)
|
||||
|
||||
cookie = 'dy_did=413b835d2ae00270f0c69f6400031601; acf_did=413b835d2ae00270f0c69f6400031601; Hm_lvt_e99aee90ec1b2106afe7ec3b199020a7=1692068308,1694003758; m_did=96003918aa5365bc6dcb4933000316p1; dy_teen_mode=%7B%22uid%22%3A%22472647365%22%2C%22status%22%3A0%2C%22birthday%22%3A%22%22%2C%22password%22%3A%22%22%7D; PHPSESSID=td59qi2fu2gepngb8mlehbeme3; acf_auth=94fc9s%2FeNj%2BKlpU%2Br8tZC3Jo9sZ0wz9ClcHQ1akL2Nhb6ZyCmfjVWSlR3LFFPuePWHRAMo0dt9vPSCoezkFPOeNy4mYcdVOM1a8CbW0ZAee4ipyNB%2Bflr58; dy_auth=bec5yzM8bUFYe%2FnVAjmUAljyrsX%2FcwRW%2FyMHaoArYb5qi8FS9tWR%2B96iCzSnmAryLOjB3Qbeu%2BBD42clnI7CR9vNAo9mva5HyyL41HGsbksx1tEYFOEwxSI; wan_auth37wan=5fd69ed5b27fGM%2FGoswWwDo%2BL%2FRMtnEa4Ix9a%2FsH26qF0sR4iddKMqfnPIhgfHZUqkAk%2FA1d8TX%2B6F7SNp7l6buIxAVf3t9YxmSso8bvHY0%2Fa6RUiv8; acf_uid=472647365; acf_username=472647365; acf_nickname=%E7%94%A8%E6%88%B776576662; acf_own_room=0; acf_groupid=1; acf_phonestatus=1; acf_avatar=https%3A%2F%2Fapic.douyucdn.cn%2Fupload%2Favatar%2Fdefault%2F24_; acf_ct=0; acf_ltkid=25305099; acf_biz=1; acf_stk=90754f8ed18f0c24; Hm_lpvt_e99aee90ec1b2106afe7ec3b199020a7=1694003778'
|
||||
if cookies != '':
|
||||
cookie = cookies
|
||||
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',
|
||||
'Referer': 'https://m.douyu.com/3125893?rid=3125893&dyshid=0-96003918aa5365bc6dcb4933000316p1&dyshci=181',
|
||||
'Cookie': cookie
|
||||
}
|
||||
data = {
|
||||
'v': params_list[0],
|
||||
'did': params_list[1],
|
||||
'tt': params_list[2],
|
||||
'sign': params_list[3], # 10分钟过期
|
||||
'sign': params_list[3], # 10分钟有效期
|
||||
'ver': '22011191',
|
||||
'rid': rid,
|
||||
'rate': rate, # 0蓝光、3超清、2高清、-1默认
|
||||
}
|
||||
# 将数据转换为 URL 编码的字节格式
|
||||
data = urllib.parse.urlencode(data).encode('utf-8')
|
||||
app_api='https://m.douyu.com/hgapi/livenc/room/getStreamUrl'
|
||||
app_api = 'https://m.douyu.com/hgapi/livenc/room/getStreamUrl'
|
||||
req = urllib.request.Request(app_api, data=data, headers=headers)
|
||||
response = opener.open(req, timeout=10)
|
||||
response = opener.open(req, timeout=15)
|
||||
json_str = response.read().decode('utf-8')
|
||||
json_data = json.loads(json_str)
|
||||
return json_data
|
||||
|
||||
|
||||
def get_yy_stream_data(url):
|
||||
cid=re.search('yy.com/(.*?)/',url).group(1)
|
||||
def get_yy_stream_data(url, cookies=''):
|
||||
cid = re.search('yy.com/(.*?)/', url).group(1)
|
||||
|
||||
cookie = 'hd_newui=0.2103068903976506; hdjs_session_id=0.4929014850884579; hdjs_session_time=1694004002636; hiido_ui=0.923076230899782'
|
||||
if cookies != '':
|
||||
cookie = 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://www.yy.com/',
|
||||
'Cookie': cookie
|
||||
}
|
||||
req = urllib.request.Request(url, headers=headers)
|
||||
response = opener.open(req, timeout=10)
|
||||
response = opener.open(req, timeout=15)
|
||||
html_str = response.read().decode('utf-8')
|
||||
live_info = re.search('<div class="w-liveplayer-head__content">(.*)<i class="follow-i">', html_str, re.S).group(1)
|
||||
anchor_name = re.search('<h2>(.*?)</h2>', live_info).group(1)
|
||||
|
||||
data = '{"head":{"seq":1691766627723,"appidstr":"0","bidstr":"121","cidstr":"'+cid+'","sidstr":"'+cid+'","uid64":0,"client_type":108,"client_ver":"5.14.13","stream_sys_ver":1,"app":"yylive_web","playersdk_ver":"5.14.13","thundersdk_ver":"0","streamsdk_ver":"5.14.13"},"client_attribute":{"client":"web","model":"","cpu":"","graphics_card":"","os":"chrome","osversion":"0","vsdk_version":"","app_identify":"","app_version":"","business":"","width":"1536","height":"864","scale":"","client_type":8,"h265":0},"avp_parameter":{"version":1,"client_type":8,"service_type":0,"imsi":0,"send_time":1691766627,"line_seq":-1,"gear":4,"ssl":1,"stream_format":0}}'
|
||||
data = '{"head":{"seq":1691766627723,"appidstr":"0","bidstr":"121","cidstr":"' + cid + '","sidstr":"' + cid + '","uid64":0,"client_type":108,"client_ver":"5.14.13","stream_sys_ver":1,"app":"yylive_web","playersdk_ver":"5.14.13","thundersdk_ver":"0","streamsdk_ver":"5.14.13"},"client_attribute":{"client":"web","model":"","cpu":"","graphics_card":"","os":"chrome","osversion":"0","vsdk_version":"","app_identify":"","app_version":"","business":"","width":"1536","height":"864","scale":"","client_type":8,"h265":0},"avp_parameter":{"version":1,"client_type":8,"service_type":0,"imsi":0,"send_time":1691766627,"line_seq":-1,"gear":4,"ssl":1,"stream_format":0}}'
|
||||
data_bytes = data.encode('utf-8')
|
||||
url2=f'https://stream-manager.yy.com/v3/channel/streams?uid=0&cid={cid}&sid={cid}&appid=0&sequence=1691766112069&encode=json'
|
||||
req = urllib.request.Request(url2,data=data_bytes, headers=headers)
|
||||
response = opener.open(req, timeout=10)
|
||||
url2 = f'https://stream-manager.yy.com/v3/channel/streams?uid=0&cid={cid}&sid={cid}&appid=0&sequence=1691766112069&encode=json'
|
||||
req = urllib.request.Request(url2, data=data_bytes, headers=headers)
|
||||
response = opener.open(req, timeout=15)
|
||||
json_str = response.read().decode('utf-8')
|
||||
json_data = json.loads(json_str)
|
||||
json_data['anchor_name']=anchor_name
|
||||
json_data['anchor_name'] = anchor_name
|
||||
return json_data
|
||||
|
||||
|
||||
def get_bilibili_stream_data(url):
|
||||
def get_bilibili_stream_data(url, cookies=''):
|
||||
cookie = "buvid3=13436C33-39B8-C4D5-C5C6-3F31B85716A131745infoc; b_nut=1680525931; CURRENT_FNVAL=4048; _uuid=B10E775DC-168D-CA47-E1B8-CEF7C52FA84234052infoc; buvid_fp=a2f7f8f3977824b52ec75cf23e5b6754; CURRENT_PID=70fa2680-d21d-11ed-ba58-9979ebfa5794; rpdid=|(JYYJ|uuYm)0J'uY)|lklmRJ; buvid4=C29E3582-5740-8FF3-AFD1-98B345DDAF5393968-022082019-Vk7oLekZ8O%2FtgWtFEu98GQ%3D%3D; DedeUserID=623475372; DedeUserID__ckMd5=db79fcea5a8315aa; i-wanna-go-back=-1; b_ut=5; FEED_LIVE_VERSION=V8; header_theme_version=CLOSE; home_feed_column=5; browser_resolution=1483-722; SESSDATA=122468fe%2C1707184844%2C2c98c%2A827Ts7uT3NZIxeOzop88h3EdmSUIG9NhWF9VkiidKIkTgJkTbh5WcONjTKuaOwfeR9t6uUZAAASAA; bili_jct=b8479df41520c402eb0a1a7f37a26de8; bp_video_offset_623475372=827303476826472609; PVID=1; LIVE_BUVID=AUTO5816940041629512; GIFT_BLOCK_COOKIE=GIFT_BLOCK_COOKIE"
|
||||
if cookies != '':
|
||||
cookie = cookies
|
||||
headers = {
|
||||
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0',
|
||||
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
|
||||
'Referer':'https://live.bilibili.com/?spm_id_from=333.1296.0.0',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0',
|
||||
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
|
||||
'Referer': 'https://live.bilibili.com/?spm_id_from=333.1296.0.0',
|
||||
'Cookie': cookie
|
||||
}
|
||||
req = urllib.request.Request(url, headers=headers)
|
||||
response = opener.open(req, timeout=10)
|
||||
response = opener.open(req, timeout=15)
|
||||
html_str = response.read().decode('utf-8')
|
||||
json_str=re.search('<script>window.__NEPTUNE_IS_MY_WAIFU__=(.*?)</script><script>',html_str,re.S).group(1)
|
||||
json_data=json.loads(json_str)
|
||||
json_str = re.search('<script>window.__NEPTUNE_IS_MY_WAIFU__=(.*?)</script><script>', html_str, re.S).group(1)
|
||||
json_data = json.loads(json_str)
|
||||
return json_data
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# 抖音直播间页面的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'
|
||||
# 尽量用自己的cookie,以避免默认的不可用导致无法获取数据
|
||||
dy_cookie = ''
|
||||
ks_cookie = ''
|
||||
url = "https://live.douyin.com/745964462470" # 抖音直播
|
||||
# url = "https://www.tiktok.com/@pearlgaga88/live" # Tiktok直播
|
||||
# url = "https://live.kuaishou.com/u/yall1102" # 快手直播
|
||||
@ -232,10 +261,9 @@ if __name__ == '__main__':
|
||||
# url = 'https://www.yy.com/22490906/22490906' # YY直播
|
||||
# url = 'https://live.bilibili.com/21593109' # b站直播
|
||||
|
||||
|
||||
print(get_douyin_stream_data(url,Cookie))
|
||||
print(get_douyin_stream_data(url, dy_cookie))
|
||||
# print(get_tiktok_stream_data(url,'http://127.0.0.1:7890'))
|
||||
# print(get_kuaishou_stream_data(url))
|
||||
# print(get_kuaishou_stream_data(url,ks_cookie))
|
||||
# print(get_huya_stream_data(url))
|
||||
# print(get_douyu_info_data(url))
|
||||
# print(get_douyu_stream_data("4921614",rate='-1'))
|
||||
@ -243,3 +271,5 @@ if __name__ == '__main__':
|
||||
# print(get_bilibili_stream_data(url))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
41
web_rid.py
41
web_rid.py
@ -4,13 +4,19 @@
|
||||
Author: Hmily
|
||||
Github:https://github.com/ihmily
|
||||
Date: 2023-07-17 23:52:05
|
||||
Update: 2023-08-05 23:47:30
|
||||
Update: 2023-09-07 23:35:00
|
||||
Copyright (c) 2023 by Hmily, All Rights Reserved.
|
||||
"""
|
||||
import json
|
||||
import re
|
||||
import urllib.parse
|
||||
# import execjs # pip install PyExecJS
|
||||
import execjs # pip install PyExecJS
|
||||
import requests
|
||||
import urllib.request
|
||||
|
||||
|
||||
no_proxy_handler = urllib.request.ProxyHandler({})
|
||||
opener = urllib.request.build_opener(no_proxy_handler)
|
||||
|
||||
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',
|
||||
@ -20,29 +26,18 @@ headers = {
|
||||
|
||||
|
||||
# X-bogus算法
|
||||
# def get_xbogus(url) -> str:
|
||||
# query = urllib.parse.urlparse(url).query
|
||||
# xbogus = execjs.compile(open('./x-bogus.js').read()).call('sign', query, headers["User-Agent"])
|
||||
# # print(xbogus)
|
||||
# return xbogus
|
||||
|
||||
# X-Bogus.js在我的服务器上用node.js运行了,这里直接调用就好
|
||||
def get_xbogus2(url) -> str:
|
||||
def get_xbogus(url) -> str:
|
||||
query = urllib.parse.urlparse(url).query
|
||||
url = "http://43.138.133.177:8890/xbogus"
|
||||
data = {"url":query,"ua":headers["User-Agent"]}
|
||||
response = requests.get(url,params=data)
|
||||
xbogus =response.json()["result"]
|
||||
# print(f'生成的X-Bogus签名为: {xbogus}')
|
||||
xbogus = execjs.compile(open('./x-bogus.js').read()).call('sign', query, headers["User-Agent"])
|
||||
# print(xbogus)
|
||||
return xbogus
|
||||
|
||||
|
||||
# 获取房间ID和用户secID
|
||||
def get_sec_user_id(url):
|
||||
# response=requests.get(url)
|
||||
response = urllib.request.urlopen(url)
|
||||
response = opener.open(url, timeout=15)
|
||||
redirect_url = response.url
|
||||
sec_user_id=redirect_url.split('sec_user_id=')[1].rsplit('&ecom_share')[0]
|
||||
sec_user_id=re.search(r'sec_user_id=([\w\d_\-]+)&',redirect_url).group(1)
|
||||
room_id=redirect_url.split('?')[0].rsplit('/',maxsplit=1)[1]
|
||||
return room_id,sec_user_id
|
||||
|
||||
@ -50,13 +45,13 @@ def get_sec_user_id(url):
|
||||
# 获取直播间webID
|
||||
def get_live_room_id(room_id,sec_user_id):
|
||||
url= f'https://webcast.amemv.com/webcast/room/reflow/info/?verifyFp=verify_lk07kv74_QZYCUApD_xhiB_405x_Ax51_GYO9bUIyZQVf&type_id=0&live_id=1&room_id={room_id}&sec_user_id={sec_user_id}&app_id=1128&msToken=wrqzbEaTlsxt52-vxyZo_mIoL0RjNi1ZdDe7gzEGMUTVh_HvmbLLkQrA_1HKVOa2C6gkxb6IiY6TY2z8enAkPEwGq--gM-me3Yudck2ailla5Q4osnYIHxd9dI4WtQ=='
|
||||
xbogus = get_xbogus2(url) # 获取X-Bogus算法
|
||||
xbogus = get_xbogus(url) # 获取X-Bogus算法
|
||||
url = url + "&X-Bogus=" + xbogus
|
||||
# response = requests.get(url,headers=headers)
|
||||
# json_data=response.json()
|
||||
# 通通改成用urlib库,防止同时录制Tiktok直播时,代理影响requests请求出错
|
||||
request = urllib.request.Request(url, headers=headers)
|
||||
response = urllib.request.urlopen(request, timeout=10)
|
||||
req = urllib.request.Request(url, headers=headers)
|
||||
response = opener.open(req, timeout=15)
|
||||
html_str = response.read().decode('utf-8')
|
||||
json_data = json.loads(html_str)
|
||||
web_rid=json_data['data']['room']['owner']['web_rid']
|
||||
@ -66,7 +61,11 @@ def get_live_room_id(room_id,sec_user_id):
|
||||
if __name__ == '__main__':
|
||||
url="https://v.douyin.com/iQLgKSj/"
|
||||
# url="https://v.douyin.com/iQFeBnt/"
|
||||
# url="https://v.douyin.com/iehvKttp/"
|
||||
room_id,sec_user_id = get_sec_user_id(url)
|
||||
web_rid=get_live_room_id(room_id,sec_user_id)
|
||||
print(web_rid)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user