哼哼猫文档
本页内容

Python 代码示例

Python 调这套接口只需要一个 HTTP 客户端,标准库的 urllib.request 也能跑,但下面两段用的是更顺手的 requests(同步)和 aiohttp(异步),先 pip install requests aiohttp。

本页给两个例子:一次提取一条链接的同步写法,和一次跑一批链接的并发写法。两段都用 Authorization: Bearer <你的 API Key> 请求头鉴权,Bearer 与 Key 之间有一个空格;把占位符换成开发者管理中心里的真实 Key 再跑。

🚀 使用 requests

最常见的用法:脚本或定时任务里逐条提取,同步等结果回来。两个地方容易踩——requests 默认不设超时,目标平台卡住时线程会一直挂着,生产代码要显式传 timeout=(一次提取偶尔要十几秒,别设太小);另一处是拿到响应先看 status_code,非 200 时响应体是 {message, code?, retryable?} 这套形状(只有 message 一定有,code 与 retryable 是提取失败的 400 才带的),直接按成功结构去取 medias 会 KeyError。

成功响应里 title 与 text 都是可选字段,有标题的平台(YouTube、B 站等)两个都可能有,没标题的只给 text,例子里用 or 依次兜底;媒体在 medias 里,同一个媒体的多档清晰度在 variants 里——挑 is_default 为 true 的那一档就是推荐清晰度。拿到的媒体直链是短效的,取到后尽快下载;如果 media 上带了 headers,下载请求要把这些头原样带上,否则会被平台拒绝。

import requests

api_url = "https://api.meowload.net/openapi/v1/extract/post"
api_key = "<你的 API Key>"

payload = {"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"}
headers = {"Authorization": f"Bearer {api_key}", "Accept-Language": "zh"}

response = requests.post(api_url, json=payload, headers=headers)

if response.status_code == 200:
    data = response.json()
    # title 与 text 都是可选的:有标题的平台取 title,其余取 text
    caption = data.get("title") or data.get("text") or "无"
    print(f"✅ 提取成功,平台: {data.get('site')},文案: {caption}")

    for media in data["medias"]:
        print(f"- {media['media_type']}: {media['resource_url']}")
        # 多清晰度 / 多音轨在 variants 里;video_url 与 audio_url 同时存在表示音视频分离
        for variant in media.get("variants", []):
            split = "(需合并)" if variant.get("video_url") and variant.get("audio_url") else ""
            print(f"    {variant.get('quality_label', '默认')}{split}")
else:
    error = response.json()
    print(f"❌ 请求失败 ({response.status_code}): {error['message']}")
    if error.get("retryable"):
        print(f"   错误码 {error['code']} 是临时失败,可稍后重试")

🎯 使用 aiohttp 异步调用

要跑几十上百条链接时逐条同步等待太慢,用 aiohttp 把请求并发出去更合适。这里最容易出事的是并发数:asyncio.gather 会把所有任务一起放出去,链接一多就撞上每个 Key 每分钟 1200 次的限流拿到 429,实际用时套一个 asyncio.Semaphore 控制同时在飞的请求数,并对 429 退避重试。

另一处是异常:gather 默认会让第一个抛出的异常终止整批,所以例子把失败也当成一条结果返回,一条链接失败不影响其余的。示例为了简短在每次调用里各建了一个 ClientSession,批量场景把它提到外层共用,能省掉重复的连接建立开销。

import aiohttp
import asyncio

async def extract_async(url, api_key):
    api_url = "https://api.meowload.net/openapi/v1/extract/post"

    async with aiohttp.ClientSession() as session:
        async with session.post(
            api_url,
            json={"url": url},
            headers={"Authorization": f"Bearer {api_key}"}
        ) as response:
            data = await response.json()
            if response.status != 200:
                # 400 带 code 与 retryable,retryable 为 True 时可稍后重试
                return {"url": url, "error": data}
            return {"url": url, "result": data}

# 并发提取多个 URL
async def batch_extract(urls, api_key):
    tasks = [extract_async(url, api_key) for url in urls]
    return await asyncio.gather(*tasks)

# 运行
urls = [
    "https://www.youtube.com/watch?v=video1",
    "https://www.youtube.com/watch?v=video2",
]
results = asyncio.run(batch_extract(urls, "<你的 API Key>"))

for item in results:
    if "error" in item:
        error = item["error"]
        print(f"❌ {item['url']}: {error['message']} ({error.get('code')}, retryable={error.get('retryable')})")
    else:
        print(f"✅ {item['url']}: {len(item['result']['medias'])} 个媒体")

把示例跑通之后,可以顺着这几篇继续: