起因

最近想转载B站视频到网站,苦于B站原生分享代码只能转载360P视频,而且播放器太丑,就如某B友说的:B站分享的视频就是一个广告。

在网上找了一圈,都是说怎么下载B站视频的,少有可以引用到网页上直接播放的,幸好还是被我找到了一位技术大佬小姐姐苏晓晴的博客——《[源码分享]B站视频直链解析源码(PHP源码 包含前端解析源码)》,感谢小姐姐的源码开源分享,下面的PHP代码就是基于苏晓晴的代码修改而来的。

前提

  • 此代码只做研究学习用,请不要用于商业目的
  • 尊重视频版权,尽量前往B站看原视频,支持UP主们的视频收益及B站的健康发展
  • 代码开源免费,请不要打包售卖
  • 由于B站限制,此代码只支持中国大陆的服务器正常解析
  • 获取高清视频需要填写登录B站后的cookie
  • 由于B站视频格式限制,解析1080P及以上的视频都是视频和声音分开的两个文件(或许是没找到接口的借口),下载后可以用ffmpeg等视频工具进行合并
  • 尽量不要疯狂传播和高频解析,导致B站api接口或账号被封本人概不负责

代码

<?php
/**
 * 使用方法:
 * 例如:把完整的代码保存为b.php,上传到支持PHP的服务器网站根目录
 * 如果想得到高清的视频真实地址,填写你B站的cookie后:
 * http://youdomain.com/b.php?bv=BV1Qq421c7sQ
 * 如果想把视频放在博客或论坛用<video>标签播放:
 * http://youdomain.com/b.php?bv=BV1Qq421c7sQ&t=mp4&d=y
 */
header('Content-type: text/json;charset=utf-8');
$bvid = $_GET['bv']; //视频bv号,必填项,例如地址后面加?bv=BV1Qq421c7sQ
$type = $_GET['t'];  //非必填项,如果下面填写了cookie,地址后面加&t=mp4,可解析后缀mp4最高720P(新上传的视频)的有声视频(有些老视频还是能解析成1080P的)
$down = $_GET['d'];  //非必填项,地址后面加&d=y,将直接跳转到视频地址,如果解析的是1080P及以上的视频,将跳转到视频m4s(没有声音的视频)
$qxd = ($type === 'mp4')? 3 : 80;
$header = ['Content-type: application/json;charset=UTF-8'];
$useragent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36';
$cookie = ''; //填写登录B站后的cookie,若为空只能解析360P,正确填写后默认解析最高画质(但1080P及以上的视频将解析视频、声音两个m4s地址)
$hqcid = burl(
    'https://api.bilibili.com/x/player/pagelist?bvid='.$bvid, $header, $useragent, $cookie
);
$array = json_decode($hqcid,true);
if($array['code'] == '0'){
    foreach($array['data'] as $keys =>$pron){
        $hqsj = burl(
            "https://api.bilibili.com/x/player/playurl?fnval=".$qxd."&qn=64&bvid=".$bvid."&cid=".$pron['cid']."&platform=html5&high_quality=1", $header, $useragent, $cookie
        );
        $array_2 = json_decode($hqsj,true);
        if (empty($cookie)) {
            $json = [
                'video_url' =>  'https://upos-sz-mirrorhw.bilivideo.com/'.explode('.bilivideo.com/',$array_2['data']['durl'][0]['url'])[1]
            ];
        } elseif ($type === 'mp4') { 
            $json = [
                'video_url' =>  'https://upos-sz-mirrorhw.bilivideo.com/'.explode('.bilivideo.com/',$array_2['data']['durl'][0]['url'])[1]
            ]; 
        } else { 
            $json = [
                'video_url' =>  'https://upos-sz-mirrorhw.bilivideo.com/'.explode('.bilivideo.com/',$array_2['data']['dash']['video'][0]['baseUrl'])[1],
                'audio_url' =>  'https://upos-sz-mirrorhw.bilivideo.com/'.explode('.bilivideo.com/',$array_2['data']['dash']['audio'][0]['baseUrl'])[1]
            ]; 
        }
    }
}else{
    $json = ['code'=>0, 'msg'=>"解析失败!"];
}
if ($down == 'y') {
    $video_url = $json['video_url'];
    header("Location: $video_url");
    exit;
} else {
    exit(json_encode($json, 480));
}
function burl($url, $header, $user_agent, $cookie) {
    $ch = curl_init() ;
    curl_setopt($ch, CURLOPT_URL, $url );
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true) ;
    curl_setopt($ch, CURLOPT_HTTPHEADER,$header);
    curl_setopt($ch, CURLOPT_USERAGENT,$user_agent);
    curl_setopt($ch, CURLOPT_COOKIE, $cookie);
    curl_setopt($ch, CURLOPT_BINARYTRANSFER, true) ;
    $output = curl_exec($ch) ;
    curl_close ($ch);
    return $output;
}
?>

获取cookie

用你的账号登录B站,按F12打开开发者工具,ctrl+r刷新页面,点击网络,找到并点击www.bilibili.com,标头项下拉,找到cookie复制这串数据,粘贴到代码$cookie处

注意

粘贴cookie时如果数据中包含'(单引号),要在单引号前加一个反斜杠\',否则会报错!!!

感谢

感谢苏晓晴提供代码思路。