记录一次IIS部署webform请求调用python服务的异常处理

需求

需要做一个获取视频网站的后台服务接口,输入一个房间号,获取对应的直播URL,然后给客户端展示直播。

效果图

获取直播URL工具

在这里插入图片描述
选择平台,输入房间号,或许直播线路图
在这里插入图片描述
如果未开播的话,则会返回未开播

体验地址 : http://116.205.247.142:8080/GetBrocastLiveUrl.html

分析

  • 执行对应的python逻辑,输入房间号,返回直播URL
  • 创建对应的webform一般处理程序服务,需要用到C#执行python
  • 发布IIS,这里需要避免权限问题的坑

对应代码

Python

# 获取哔哩哔哩直播的真实流媒体地址,默认获取直播间提供的最高画质
# qn=150高清
# qn=250超清
# qn=400蓝光
# qn=10000原画
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 = {
    
    }
        # flv流无法播放,暂修改成获取hls格式的流,
        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__':
    #r = input('请输入bilibili直播房间号:\n')
    print(args.roomId)
    print(get_real_url(args.roomId))

C#一般处理程序

using System;
using System.IO;
using System.Web;

namespace MonitorToolSystem
{
    
    
    /// <summary>
    /// GetBrocastLiveUrl 的摘要说明
    /// </summary>
    public class GetBrocastLiveUrl : IHttpHandler
    {
    
    
        public void ProcessRequest(HttpContext context)
        {
    
    
            context.Response.ContentType = "text/plain";
            var roomId = context.Request["roomId"];
            //服务器跟PC的python地址
            string pyToolPath = @"C:\Users\Administrator\AppData\Local\Programs\Python\Python39\python.exe"; //c:\users\d00605132\appdata\local\programs\python\python39\python.exe
            //string pyToolPath = @"c:\users\d00605132\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"); ;//(因为我没放debug下,所以直接写的绝对路径,替换掉上面的路径了)
            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,是不是很开心呢!

猜你喜欢

转载自blog.csdn.net/s10141303/article/details/126076254