哼哼猫文档
本页内容

PHP 代码示例

PHP 调这套接口不需要额外依赖:allow_url_fopen 开着时 file_get_contents 就能发 POST,装了 cURL 扩展(多数环境默认带)则用 cURL 更可控。

本页给两段代码:一段是能贴进任何脚本的最短写法,一段是带异常类的封装。鉴权都是 Authorization: Bearer <你的 API Key> 请求头,只有成功的请求才扣次数。

🚀 使用 file_get_contents

适合小脚本,或者主机不让装扩展的环境。这种写法有两个坑几乎人人踩到:不加 ignore_errors,非 200 时 file_get_contents 会直接返回 false 并抛 warning,错误体根本读不到;状态码也没有返回值可取,只能从 $http_response_header 里解析——这个变量是函数执行后被注入到当前作用域的,只在发起调用的那个函数里可见。

它默认用 php.ini 的 default_socket_timeout(通常 60 秒),要自己控制超时得在 http 选项里补一个 timeout。响应里的 title 与 text 都是可选字段,例子用 ?? 依次兜底;媒体的多档清晰度在 variants 里,取 is_default 为真的那一档即可。

<?php

$apiUrl = "https://api.meowload.net/openapi/v1/extract/post";
$apiKey = "<你的 API Key>";

$params = array("url" => "https://www.youtube.com/watch?v=dQw4w9WgXcQ");

$options = array(
    "http" => array(
        "header" =>
            "Content-Type: application/json\r\n" .
            "Authorization: Bearer " . $apiKey . "\r\n" .
            "Accept-Language: zh",
        "method" => "POST",
        "content" => json_encode($params),
        "ignore_errors" => true, // 非 200 时也读取响应体,否则拿不到错误信息
    ),
);

$context = stream_context_create($options);
$response = file_get_contents($apiUrl, false, $context);

// 解析 HTTP 响应状态码
$statusLine = $http_response_header[0];
preg_match('{HTTP\/\S*\s(\d{3})}', $statusLine, $match);
$statusCode = $match[1];

$data = json_decode($response, true);

if ($statusCode == 200) {
    // title 与 text 都是可选的:有标题的平台取 title,其余取 text
    $caption = $data['title'] ?? $data['text'] ?? '无';
    echo "✅ 提取成功,平台: " . ($data['site'] ?? '未知') . ",文案: " . $caption . "\n";

    foreach ($data['medias'] as $media) {
        echo "- " . $media['media_type'] . ": " . $media['resource_url'] . "\n";
        // 多清晰度 / 多音轨在 variants 里;video_url 与 audio_url 同时存在表示音视频分离
        foreach ($media['variants'] ?? array() as $variant) {
            $split = (!empty($variant['video_url']) && !empty($variant['audio_url'])) ? "(需合并)" : "";
            echo "    " . ($variant['quality_label'] ?? '默认') . $split . "\n";
        }
    }
} else {
    echo "❌ 请求失败 (" . $statusCode . "): " . $data['message'] . "\n";
    if (!empty($data['retryable'])) {
        echo "   错误码 " . $data['code'] . " 是临时失败,可稍后重试\n";
    }
}
?>

📦 使用 cURL

生产代码建议用这段:状态码、错误码、是否可重试一起塞进异常,上层一处 catch 就能判断。CURLOPT_RETURNTRANSFER 不能漏——不设它 curl_exec 会把响应直接打到输出、只返回 true,json_decode 拿到的是空。

还要分清两种失败:curl_exec 返回 false 是网络层出错,此时才该看 curl_error;而 HTTP 400 是接口正常返回的业务失败,响应体里带 code 与 retryable,retryable 为真才值得退避重试。再补一个 CURLOPT_TIMEOUT,默认不限时会让脚本卡死。下载媒体直链时,若那条 media 带了 headers,要用 CURLOPT_HTTPHEADER 原样带上。

<?php

class ExtractException extends Exception {
    public $code;
    public $retryable;

    public function __construct($message, $statusCode, $code = null, $retryable = false) {
        parent::__construct($message, $statusCode);
        $this->code = $code;
        $this->retryable = $retryable;
    }
}

function extractPost($url, $apiKey) {
    $apiUrl = "https://api.meowload.net/openapi/v1/extract/post";

    $ch = curl_init($apiUrl);

    $payload = json_encode(array("url" => $url));

    curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Content-Type: application/json',
        'Authorization: Bearer ' . $apiKey,
        'Accept-Language: zh'
    ));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $response = curl_exec($ch);
    $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    $data = json_decode($response, true);

    if ($statusCode == 200) {
        return $data;
    }
    // 400 带 code 与 retryable;401/402/422/429 只看状态码
    throw new ExtractException(
        $data['message'],
        $statusCode,
        $data['code'] ?? null,
        !empty($data['retryable'])
    );
}

// 使用
try {
    $result = extractPost("https://www.youtube.com/watch?v=dQw4w9WgXcQ", "<你的 API Key>");
    $caption = $result['title'] ?? $result['text'] ?? '无';
    echo "✅ 提取成功,文案: " . $caption . ",媒体数量: " . count($result['medias']) . "\n";
} catch (ExtractException $e) {
    echo "❌ 错误 (" . $e->getCode() . "): " . $e->getMessage() . "\n";
    if ($e->retryable) {
        echo "   错误码 " . $e->code . " 是临时失败,可稍后重试\n";
    }
}
?>

写完这段可以继续看: