需求
需要做一个获取视频网站的后台服务接口,输入一个房间号,获取对应的直播URL,然后给客户端展示直播。
效果图
选择平台,输入房间号,或许直播线路图 如果未开播的话,则会返回未开播
体验地址 : http://116.205.247.142:8080/GetBrocastLiveUrl.html
分析
- 执行对应的python逻辑,输入房间号,返回直播URL
- 创建对应的webform一般处理程序服务,需要用到C#执行python
- 发布IIS,这里需要避免权限问题的坑
对应代码
Python
import requests
import argparse
parser = argparse.ArgumentParser(description='manual to this script')
parser.add_argument("--roomId", type=str, default="2171135", help='search roomId')
args = parser.parse_args()
class BiliBili:
def __init__(self, rid):
"""
有些地址无法在PotPlayer播放,建议换个播放器试试
Args:
rid:
"""
rid = rid
self.header = {
'User-Agent': 'Mozilla/5.0 (iPod; CPU iPhone OS 14_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, '
'like Gecko) CriOS/87.0.4280.163 Mobile/15E148 Safari/604.1',
}
r_url = 'https://api.live.bilibili.com/room/v1/Room/room_init'
param = {
'id': rid
}
with requests.Session() as self.s:
res = self.s.get(r_url, headers=self.header, params=param).json()
if res['msg'] == '直播间不存在':
raise Exception(f'bilibili {rid} {res["msg"]}')
live_status = res['data']['live_status']
if live_status != 1:
raise Exception(f'bilibili {rid} 未开播')
self.real_room_id = res['data']['room_id']
def get_real_url(self, current_qn: int = 10000) -> dict:
url = 'https://api.live.bilibili.com/xlive/web-room/v2/index/getRoomPlayInfo'
param = {
'room_id': self.real_room_id,
'protocol': '0,1',
'format': '0,1,2',
'codec': '0,1',
'qn': current_qn,
'platform': 'h5',
'ptype': 8,
}
res = self.s.get(url, headers=self.header, params=param).json()
stream_info = res['data']['playurl_info']['playurl']['stream']
qn_max = 0
for data in stream_info:
accept_qn = data['format'][0]['codec'][0]['accept_qn']
for qn in accept_qn:
qn_max = qn if qn > qn_max else qn_max
if qn_max != current_qn:
param['qn'] = qn_max
res = self.s.get(url, headers=self.header, params=param).json()
stream_info = res['data']['playurl_info']['playurl']['stream']
stream_urls = {}
for data in stream_info:
format_name = data['format'][0]['format_name']
if format_name == 'ts':
base_url = data['format'][-1]['codec'][0]['base_url']
url_info = data['format'][-1]['codec'][0]['url_info']
for i, info in enumerate(url_info):
host = info['host']
extra = info['extra']
stream_urls[f'线路{i + 1}'] = f'{host}{base_url}{extra}'
break
return stream_urls
def get_real_url(rid):
try:
bilibili = BiliBili(rid)
return bilibili.get_real_url()
except Exception as e:
print('Exception:', e)
return False
if __name__ == '__main__':
print(args.roomId)
print(get_real_url(args.roomId))
C#一般处理程序
using System;
using System.IO;
using System.Web;
namespace MonitorToolSystem
{
public class GetBrocastLiveUrl : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
var roomId = context.Request["roomId"];
string pyToolPath = @"C:\Users\Administrator\AppData\Local\Programs\Python\Python39\python.exe";
System.Diagnostics.Process p = new System.Diagnostics.Process();
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Pythons/bilibiliModify.py"); ;
string sArguments = path;
if (!string.IsNullOrEmpty(roomId))
{
sArguments = sArguments + $" --roomId={roomId}";
}
p.StartInfo.FileName = pyToolPath;
p.StartInfo.UseShellExecute = true;
p.StartInfo.Arguments = sArguments;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = false;
p.Start();
while (!p.HasExited)
{
p.WaitForExit();
}
string output = p.StandardOutput.ReadToEnd();
if (string.IsNullOrEmpty(output))
{
context.Response.Write($"error:沒有查询到房间数据");
}
else
{
context.Response.Write($"{output}");
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
}
这里Python版本是3.9.6
IIS设置避坑
本地跑的好好的,但一旦发布IIS,就会碰到访问权限的问题,会报错System.ComponentModel.Win32Exception拒绝访问,首先IIS需要以管理员身份运行,其次在Web.config中配置管理员账户访问权限,在<system.web>中配置
<identity impersonate="true" userName="Administrator" password="xxx"/>
然后发现不报访问权限的错了,但是process没有返回值,这就很蛋疼,前面用户权限的问题坑了我一晚上,在公司处理到11点还没搞定失望而归,今天又在公司白天解决了访问权限的问题,但却没有正确得到返回值,又是解决问题,后来发现应用程序池需要设置标识为LocalSystem,非常重要,然后就能正确运行了 http://116.205.247.142:8080/GetBrocastLiveUrl.ashx?roomId=2171135 上图是房间号为2171135的直播间的直播线路地址,如果当前房间没有直播,就是返回一下值
结论
有以上经验,我就能做一个直播平台的聚合app了,只要知道各个平台的房间号,就能做一个根据直播类型分类的超大聚合直播app,是不是很开心呢!
|