首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 解析優酷視頻真實下載地址:API 請求、JSON 解析、SID/FILEID 解密完整流程

     編輯:PHP 綜合知識

優酷視頻採用動態加密機制,播放地址需經過 getPlayList API 取得加密參數,再本地解密組合真實 CDN 鏈接。本文提供完整 PHP 實作,涵蓋 HTTP 請求、JSON 解析、Seed 混淆演算法、SID 生成與最終 URL 組裝。

核心流程概覽

  1. 從分享頁 URL 提取 Video ID(如 id_XMzkyODA2NTEy)。
  2. 請求 https://v.youku.com/player/getPlayList/VideoIDS/{id} 取得 JSON。
  3. 解析 JSON 中的 seed、streamfileids、segs、key1/key2。
  4. 本地實作 getMixString(seed) 生成混淆字串,解密 streamfileids 獲得 fileid。
  5. 生成隨機 sid,組合最終 FLV/MP4 下載地址。

完整 PHP 實作

<?php
/**
 * 取得優酷視頻真實下載地址 (FLV/MP4)
 * @param string $url  分享頁 URL,如 https://v.youku.com/v_show/id_XMzkyODA2NTEy.html
 * @return string|false  真實下載地址,失敗回傳 false
 */
function getYoukuFlv(string $url)
{
    // 1. 提取 Video ID
    if (!preg_match('#id_(.*?)\.html#', $url, $m)) {
        return false;
    }
    $videoId = $m[1];

    // 2. 請求 API 取得播放清單
    $apiUrl = "https://v.youku.com/player/getPlayList/VideoIDS/$videoId";
    $json = getCurlContents($apiUrl);
    if (!$json) return false;

    $data = json_decode($json);
    if (json_last_error() !== JSON_ERROR_NONE || empty($data->data)) {
        return false;
    }

    $video = $data->data[0];
    $seed  = $video->seed;
    $segs  = $video->segs;          // 各畫質分段資訊,含 k (加密金鑰)
    $streamIds = $video->streamfileids; // stdClass: flv => "加密id", mp4 => "加密id", ...

    // 3. 遍歷畫質優先順序(flv > mp4 > hd2 > ...)
    $preferred = ['flv', 'mp4', 'hd2', 'hd3'];
    foreach ($preferred as $format) {
        if (!isset($streamIds->$format) || !isset($segs->$format)) continue;

        $encryptedId = $streamIds->$format;
        $segInfo     = $segs->$format[0]; // 取第一分段
        $k           = $segInfo->k;       // 分段解密金鑰

        // 4. 解密 fileid
        $fileId = decryptFileId($encryptedId, $seed);
        if (!$fileId) continue;

        // 5. 生成 sid (時間戳 + 隨機數)
        $sid = time() . mt_rand(10000, 99999);

        // 6. 組裝最終下載地址
        $downloadUrl = "https://f.youku.com/player/getFlvPath/sid/{$sid}_00/st/{$format}/fileid/{$fileId}?K={$k}";
        return $downloadUrl;
    }

    return false;
}

/**
 * cURL 取得內容(模擬瀏覽器 UA)
 */
function getCurlContents(string $url, int $timeout = 10): string|false
{
    if (!function_exists('curl_init')) return false;

    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => $timeout,
        CURLOPT_USERAGENT      => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
        CURLOPT_REFERER        => 'https://v.youku.com/',
        CURLOPT_SSL_VERIFYPEER => false, // 僅測試環境
        CURLOPT_HEADER         => false,
    ]);

    $content = curl_exec($ch);
    $errno   = curl_errno($ch);
    curl_close($ch);

    return $errno === 0 ? $content : false;
}

/**
 * 解密 fileid:依據 seed 生成混淆字串,按加密 id 索引取字元
 */
function decryptFileId(string $encryptedId, int $seed): string
{
    $mixed = getMixString($seed);           // 64 字元混淆字串
    $parts = explode('*', $encryptedId);    // 如 "12*34*56*"
    array_pop($parts);                      // 移除尾部空元素

    $realId = '';
    foreach ($parts as $idx) {
        $realId .= $mixed[(int)$idx] ?? '';
    }
    return $realId;
}

/**
 * 生成混淆字串(優酷演算法移植)
 * @param int $seed
 * @return string 64 字元
 */
function getMixString(int $seed): string
{
    $source = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/\:._-1234567890';
    $mixed  = '';
    $len    = strlen($source);

    for ($i = 0; $i < $len; $i++) {
        $seed = ($seed * 211 + 30031) % 65536;          // 線性同餘生成器
        $index = (int)($seed / 65536 * strlen($source)); // 比例索引
        $mixed .= $source[$index];
        $source = substr_replace($source, '', $index, 1); // 移除已用字元
    }
    return $mixed;
}

/* ---------- 使用範例 ---------- */
// $url = 'https://v.youku.com/v_show/id_XMzkyODA2NTEy.html';
// $realUrl = getYoukuFlv($url);
// echo $realUrl ?: '解析失敗';

關鍵演算法細節

步驟說明
Seed 混淆線性同餘生成器 (LCG):seed = (seed * 211 + 30031) % 65536,產生偽隨機序列。
字元池洗牌每輪從 source 按比例取一字元,加入 mixed,並從池中移除,確保不重複。
加密 ID 結構以 * 分隔的索引序列,如 12*34*5*,每個數字對應 mixed 的位置。
SID 生成time() . rand(10000,99999),伺服器端不嚴格驗證,但需格式正確。
K 值分段加密金鑰,從 segs.{format}[0].k 取得,直接附加在 URL 參數 ?K=。

注意事項與失效風險

  • 演算法可能更新:優酷不定期調整加密邏輯(如 Seed 演算法、字元池、API 結構),本碼僅供學習研究。
  • 版權與法律:繞過授權下載受保護視頻可能違反《著作權法》及平台服務條款,請僅用於合法授權內容。
  • HTTPS/簽名:新版 API 可能強制 HTTPS、要求簽名參數、Token 驗證,需抓包分析最新協定。
  • 分段視頻:長視頻會切多段(segs.{format} 陣列長度 > 1),需迴圈組裝所有段落 URL 並合併(或用 ffmpeg -i "concat:...")。

現代替代方案:youtube-dl / yt-dlp

# 安裝
pip install yt-dlp

# 取得真實下載鏈接(自動處理加密、分段、字幕)
yt-dlp -g "https://v.youku.com/v_show/id_XMzkyODA2NTEy.html"

# 直接下載最佳畫質
yt-dlp "https://v.youku.com/v_show/id_XMzkyODA2NTEy.html"

維護自建解析器成本極高,生產專案強烈建議直接呼叫 yt-dlp(支援 1000+ 網站、持續更新)或使用成熟的 PHP 封裝庫。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved