Fix douyu and kuaishou live

This commit is contained in:
ihmily 2023-08-16 15:53:27 +08:00
parent c283dd5847
commit 1c0dfadcf1
3 changed files with 47 additions and 43 deletions

View File

@ -50,6 +50,7 @@
- 注意事项④ 可以在URL_config.ini中的链接开头加上#,此时将不会录制该条链接对应的直播
- 注意事项⑤ 测试时有可能会出现在IDE如Pycharm中运行代码进行直播录制录制出来的视频却无法正常播放的现象如果遇到这个问题 最好在命令控制台DOS界面运行代码录制出来的视频即可正常播放。
- 可使用 `pyinstaller -F或-D` 将代码打包成exe可执行文件 ,前提是已经安装了`pyinstaller`
- 当同时在录制多个直播时最好线程数设置大一些否则可能出现其中一个直播录制出错。当然设置的过大也没用要同时考虑自身电脑的配置如CPU内核数、网络带宽等限制。
 
@ -114,34 +115,30 @@ GET https://hmily.vip/api/jx/live/convert.php?url=https://v.douyin.com/iQLgKSj/
## ⏳提交日志
- 20230816
- 修复斗鱼直播(官方更新了字段)和快手直播录制出错的问题
- 20230814
- 新增B站直播录制
- 写了一个在线播放M3U8和FLV视频的网页源码打开即可食用
- 20230812
- 新增YY直播录制
- 20230808
- 修复主播重新开播无法再次录制的问题
- 20230807
- 新增了斗鱼直播录制
- 修复显示录制完成之后会重新开始录制的问题
- 20230805
- 新增了虎牙直播录制其暂时只能用flv视频流进行录制
- Web API 新增了快手和虎牙这两个平台的直播流解析Tiktok要代理
- 20230804
- 新增了快手直播录制,优化了部分代码
- 上传了一个自动化获取抖音直播间页面Cookie的代码可以用于录制
- 20230803
- 通宵更新
- 新增了国际版抖音Tiktok的直播录制去除冗余 简化了部分代码
- 20230724
- 新增了一个通过抖音直播间地址获取直播视频流链接的API接口使用php写的 上传即可用

10
main.py
View File

@ -4,7 +4,7 @@
Author: Hmily
Github: https://github.com/ihmily
Date: 2023-07-17 23:52:05
Update: 2023-08-14 17:13:00
Update: 2023-08-16 14:54:17
Copyright (c) 2023 by Hmily, All Rights Reserved.
Function: Record live stream video.
"""
@ -13,19 +13,17 @@ import random
import os
import sys
import urllib.parse
import time
import configparser
import subprocess
import threading
import logging
import datetime
import shutil
import hashlib
from spider import *
from web_rid import *
# 版本号
version = "v1.0.4"
version = "v1.0.5"
platforms = "抖音|Tiktok|快手|虎牙|斗鱼|YY|B站"
# --------------------------log日志-------------------------------------
@ -382,7 +380,7 @@ def get_douyu_stream_url(json_data):
# TODO: 获取斗鱼直播源地址
data = [] # 定义一个返回数据列表
room_info = json_data['pageContext']['pageProps']['room']['roomInfo']['roomInfo']
room_info = json_data.get('pageContext',json_data)['pageProps']['room']['roomInfo']['roomInfo']
anchor_name = room_info['nickname']
status = room_info['isLive']
@ -1197,3 +1195,5 @@ while True:
# 总体循环3s
time.sleep(3)

View File

@ -4,20 +4,24 @@
Author: Hmily
Github:https://github.com/ihmily
Date: 2023-07-15 23:15:00
Update: 2023-08-14 01:42:23
Update: 2023-08-16 14:07:30
Copyright (c) 2023 by Hmily, All Rights Reserved.
Function: Get live stream data.
"""
import hashlib
import time
import urllib
import urllib.parse
import requests
import re
import json
# pip install PyExecJS
import execjs
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):
@ -31,8 +35,8 @@ def get_douyin_stream_data(url, cookies):
# response = requests.get(url, headers=headers)
# html_str = response.text
# 使用更底层的urllib内置库防止开启代理时导致的抖音录制SSL 443报错
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=10)
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)
@ -53,12 +57,12 @@ def get_tiktok_stream_data(url, proxy_addr):
'https': proxy_addr
}
html = requests.get(url, headers=headers, proxies=proxies)
html = requests.get(url, headers=headers, proxies=proxies, timeout=15)
html_str = html.text
else:
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_str = re.findall(
@ -66,7 +70,6 @@ def get_tiktok_stream_data(url, proxy_addr):
html_str)[0]
# print(json_str)
json_data = json.loads(json_str)
return json_data
@ -76,8 +79,8 @@ def get_kuaishou_stream_data(url):
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
}
request = urllib.request.Request(url, headers=headers)
response = urllib.request.urlopen(request, timeout=10)
req = urllib.request.Request(url, headers=headers)
response = opener.open(req,timeout=10)
html_str = response.read().decode('utf-8')
json_str = re.findall('__INITIAL_STATE__=(.*?);\(function', html_str)[0]
# print(json_str)
@ -90,8 +93,8 @@ def get_huya_stream_data(url):
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
}
request = urllib.request.Request(url, headers=headers)
response = urllib.request.urlopen(request, timeout=10)
req = urllib.request.Request(url, headers=headers)
response = opener.open(req,timeout=10)
html_str = response.read().decode('utf-8')
json_str = re.findall('stream: (\{"data".*?),"iWebDefaultBitRate"', html_str)[0]
json_data = json.loads(json_str + '}')
@ -106,7 +109,8 @@ def get_token_js(rid,did,cdn='ws-h5', rate="0"):
:param cdn: 主线路ws-h5备用线路tct-h5
:param rate: 1流畅2高清3超清4蓝光4M0蓝光8M或10M
"""
response = urllib.request.urlopen(f'https://www.douyu.com/{rid}', timeout=10)
url = f'https://www.douyu.com/{rid}'
response = opener.open(url, timeout=10)
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)
@ -134,13 +138,14 @@ def get_douyu_info_data(url):
if match_rid:
rid = match_rid.group(1)
else:
rid = re.search('douyu.com/(.*?)\?dyshid', url).group(1)
rid = re.search('douyu.com/(.*?)(?=\?|$)', url).group(1)
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0',
}
url=f'https://m.douyu.com/{rid}'
request = urllib.request.Request(url, headers=headers)
response = urllib.request.urlopen(request, timeout=10)
url = f'https://m.douyu.com/{rid}'
req = urllib.request.Request(url, headers=headers)
response = opener.open(req, timeout=10)
html_str = response.read().decode('utf-8')
json_str = re.search('ssr_pageContext" type="application\/json">(.*?)<\/script>', html_str).group(1)
# print(json_str)
@ -169,8 +174,8 @@ def get_douyu_stream_data(rid,rate='-1'):
# 将数据转换为 URL 编码的字节格式
data = urllib.parse.urlencode(data).encode('utf-8')
app_api='https://m.douyu.com/hgapi/livenc/room/getStreamUrl'
request = urllib.request.Request(app_api, data=data, headers=headers)
response = urllib.request.urlopen(request, timeout=10)
req = urllib.request.Request(app_api, data=data, headers=headers)
response = opener.open(req, timeout=10)
json_str = response.read().decode('utf-8')
json_data = json.loads(json_str)
return json_data
@ -183,8 +188,8 @@ def get_yy_stream_data(url):
'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/',
}
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=10)
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)
@ -192,8 +197,8 @@ def get_yy_stream_data(url):
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'
request = urllib.request.Request(url2,data=data_bytes, headers=headers)
response = urllib.request.urlopen(request, timeout=10)
req = urllib.request.Request(url2,data=data_bytes, headers=headers)
response = opener.open(req, timeout=10)
json_str = response.read().decode('utf-8')
json_data = json.loads(json_str)
json_data['anchor_name']=anchor_name
@ -206,8 +211,8 @@ def get_bilibili_stream_data(url):
'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',
}
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=10)
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)
@ -218,21 +223,23 @@ def get_bilibili_stream_data(url):
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'
# url = "https://live.douyin.com/745964462470" # 抖音直播
url = "https://live.douyin.com/745964462470" # 抖音直播
# url = "https://www.tiktok.com/@pearlgaga88/live" # Tiktok直播
# url = "https://live.kuaishou.com/u/yall1102" # 快手直播
# url = 'https://www.huya.com/116' # 虎牙直播
# url = 'https://www.douyu.com/topic/wzDBLS6?rid=4921614&dyshid=' # 斗鱼直播
# url = 'https://www.douyu.com/3637778?dyshid='
# url = 'https://www.douyu.com/3637778?dyshid'
# url = 'https://www.yy.com/22490906/22490906' # YY直播
url = 'https://live.bilibili.com/21593109' # b站直播
# url = 'https://live.bilibili.com/21593109' # b站直播
# print(get_douyin_stream_data(url,Cookie))
# print(get_tiktok_stream_data(url,''))
print(get_douyin_stream_data(url,Cookie))
# print(get_tiktok_stream_data(url,'http://127.0.0.1:7890'))
# print(get_kuaishou_stream_data(url))
# print(get_huya_stream_data(url))
# print(get_douyu_info_data(url))
# print(get_douyu_stream_data("4921614",rate='-1'))
# print(get_yy_stream_data(url))
print(get_bilibili_stream_data(url))
# print(get_bilibili_stream_data(url))