ListenHubOpenAPI
API 参考

内容提取

从 URL 异步提取文本内容,支持网页文章、Twitter/X、YouTube、微信公众号等多种来源。

内容提取

从任意 URL 异步提取文本内容。提交 URL 创建任务,然后轮询获取结果。

支持的来源

X / Twitter

个人主页和单条推文 — 抓取任意公开账号的最近动态,或提取单条推文及其上下文。

YouTube

提取任意公开 YouTube 视频的字幕文本和元数据。

微信公众号

提取微信公众号文章内容(mp.weixin.qq.com)。

网页文章

任意可公开访问的网页 — 提取文章正文、元数据和引用链接。

应用场景

  • 播客素材采集 -- 抓取网页文章、推文或公众号内容,作为播客生成的输入源
  • 内容摘要 -- 通过 summarize 一次性提取长文并生成摘要
  • 社交媒体监控 -- 批量提取关键账号的推文
  • 调研聚合 -- 从多个 URL 收集和结构化内容

创建提取任务

POST /v1/content/extract

提交任务是非阻塞的:接口校验请求、预扣积分、启动提取后立即返回 taskId。通过 查询任务状态 获取结果。

请求示例

curl -X POST "https://api.marswave.ai/openapi/v1/content/extract" \
  -H "Authorization: Bearer $LISTENHUB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": {
      "type": "url",
      "uri": "https://example.com/article"
    }
  }'
const response = await fetch('https://api.marswave.ai/openapi/v1/content/extract', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    source: {
      type: 'url',
      uri: 'https://example.com/article',
    },
  }),
});
const data = await response.json();
const taskId = data.data.taskId;
console.log('Task ID:', taskId);
import os
import requests

response = requests.post(
    'https://api.marswave.ai/openapi/v1/content/extract',
    headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
    json={
        'source': {
            'type': 'url',
            'uri': 'https://example.com/article',
        }
    }
)
data = response.json()
task_id = data['data']['taskId']
print('Task ID:', task_id)

带选项(摘要 + 最大长度)

设置 summarize: true 可将提取的文本压缩为 AI 摘要;设置 maxLength 可限制返回的字符数。

curl -X POST "https://api.marswave.ai/openapi/v1/content/extract" \
  -H "Authorization: Bearer $LISTENHUB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": {
      "type": "url",
      "uri": "https://example.com/long-article"
    },
    "options": {
      "summarize": true,
      "maxLength": 5000
    }
  }'
const response = await fetch('https://api.marswave.ai/openapi/v1/content/extract', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    source: {
      type: 'url',
      uri: 'https://example.com/long-article',
    },
    options: {
      summarize: true,
      maxLength: 5000,
    },
  }),
});
const data = await response.json();
console.log(data);
import os
import requests

response = requests.post(
    'https://api.marswave.ai/openapi/v1/content/extract',
    headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
    json={
        'source': {
            'type': 'url',
            'uri': 'https://example.com/long-article',
        },
        'options': {
            'summarize': True,
            'maxLength': 5000,
        },
    }
)
data = response.json()
print(data)

Twitter/X 个人主页 URL(指定推文数量)

# 对于 Twitter/X 个人主页 URL,使用 twitter 选项控制获取推文数量
curl -X POST "https://api.marswave.ai/openapi/v1/content/extract" \
  -H "Authorization: Bearer $LISTENHUB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": {
      "type": "url",
      "uri": "https://x.com/elonmusk"
    },
    "options": {
      "twitter": {
        "count": 50
      }
    }
  }'
const response = await fetch('https://api.marswave.ai/openapi/v1/content/extract', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    source: {
      type: 'url',
      uri: 'https://x.com/elonmusk',
    },
    options: {
      twitter: {
        count: 50,
      },
    },
  }),
});
const data = await response.json();
console.log(data);
import os
import requests

response = requests.post(
    'https://api.marswave.ai/openapi/v1/content/extract',
    headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
    json={
        'source': {
            'type': 'url',
            'uri': 'https://x.com/elonmusk',
        },
        'options': {
            'twitter': {
                'count': 50,
            },
        },
    }
)
data = response.json()
print(data)

微信公众号文章

curl -X POST "https://api.marswave.ai/openapi/v1/content/extract" \
  -H "Authorization: Bearer $LISTENHUB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": {
      "type": "url",
      "uri": "https://mp.weixin.qq.com/s/XXXXXXXXXXXXXXXX"
    }
  }'
const response = await fetch('https://api.marswave.ai/openapi/v1/content/extract', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    source: {
      type: 'url',
      uri: 'https://mp.weixin.qq.com/s/XXXXXXXXXXXXXXXX',
    },
  }),
});
const data = await response.json();
const taskId = data.data.taskId;
import os
import requests

response = requests.post(
    'https://api.marswave.ai/openapi/v1/content/extract',
    headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
    json={
        'source': {
            'type': 'url',
            'uri': 'https://mp.weixin.qq.com/s/XXXXXXXXXXXXXXXX',
        }
    }
)
data = response.json()
task_id = data['data']['taskId']

请求参数

字段类型必填说明
sourceobject提取来源
source.typestring必须为 "url"
source.uristring要提取内容的 URL
optionsobject提取选项(默认 {}
options.summarizeboolean对提取的文本生成 AI 摘要(默认 false
options.maxLengthinteger内容最大长度(字符数,默认 100000,最小 1,最大 500000
options.twitterobjectTwitter/X 专用选项
options.twitter.countinteger从个人主页 URL 获取的推文数量(1100,默认 20

响应示例

{
  "code": 0,
  "message": "success",
  "data": {
    "taskId": "67f6a1b2c3d4e5f6a7b8c9d0"
  }
}

taskId 是 24 位十六进制字符串,将其传给下方的状态查询接口。


查询任务状态

GET /v1/content/extract/{taskId}

轮询此接口直到 statuscompletedfailed。任务运行期间,响应仅携带状态——提取出的内容会等到提取与扣费结算完成后才返回。

请求示例

curl -X GET "https://api.marswave.ai/openapi/v1/content/extract/67f6a1b2c3d4e5f6a7b8c9d0" \
  -H "Authorization: Bearer $LISTENHUB_API_KEY"
const result = await fetch(`https://api.marswave.ai/openapi/v1/content/extract/${taskId}`, {
  headers: {
    'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}`,
  },
});
const data = await result.json();
console.log('Status:', data.data.status);
import os
import requests

result = requests.get(
    f'https://api.marswave.ai/openapi/v1/content/extract/{task_id}',
    headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'}
)
data = result.json()
print('Status:', data['data']['status'])

路径参数

字段类型说明
taskIdstring创建接口返回的 24 位十六进制字符串

处理中时的响应status: "processing"):

{
  "code": 0,
  "message": "success",
  "data": {
    "taskId": "67f6a1b2c3d4e5f6a7b8c9d0",
    "status": "processing",
    "createdAt": 1744200000000
  }
}

任务完成前,data 对象(提取的内容)不会返回。

任务完成时的响应status: "completed"):

{
  "code": 0,
  "message": "success",
  "data": {
    "taskId": "67f6a1b2c3d4e5f6a7b8c9d0",
    "status": "completed",
    "createdAt": 1744200000000,
    "data": {
      "content": "提取的文章正文内容...",
      "metadata": {
        "title": "文章标题",
        "author": "作者名称"
      },
      "references": [
        "https://example.com/related-article"
      ]
    },
    "credits": 100
  }
}

失败时的响应status: "failed"):

{
  "code": 0,
  "message": "success",
  "data": {
    "taskId": "67f6a1b2c3d4e5f6a7b8c9d0",
    "status": "failed",
    "createdAt": 1744200000000,
    "failCode": 1001,
    "message": "Failed to extract content from URL"
  }
}

响应字段

字段类型说明
taskIdstring任务标识符
statusstringprocessingcompletedfailed
createdAtinteger创建时间,13 位毫秒级时间戳
dataobject提取的内容,仅当 statuscompleted 时返回
data.contentstring提取的文本内容(summarize: true 时为摘要)
data.metadataobject页面元数据,如标题、作者
data.referencesarray内容中发现的引用 URL
creditsinteger消耗的积分(statuscompleted 时返回)
failCodeinteger错误码(statusfailed 时返回)
messagestring错误描述(statusfailed 时返回)

注意事项

Twitter/X 个人主页 URL

  • 当源 URL 为 Twitter/X 个人主页(如 https://x.com/username)时,API 会获取最近的推文。
  • 使用 options.twitter.count 控制获取推文数量(1100,默认 20)。
  • 非 Twitter URL 会忽略此选项。

微信公众号

  • 使用完整的 mp.weixin.qq.com/s/... 文章链接。
  • 提取结果包含文章正文和元数据。

任务生命周期

状态说明
processing提取进行中
completed内容提取成功
failed提取失败 -- 请检查 failCodemessage

轮询建议

  • 首次等待:任务创建后等待 5 秒
  • 轮询间隔:5 秒
  • 典型完成时间:10-30 秒,取决于 URL 复杂度

积分消耗

内容提取在任务开始时预扣积分,待内容长度确定后结算为实际金额。完成响应中的 credits 字段反映最终扣费。

规则说明
预扣任务开始时预留一笔积分
实际扣费按提取内容的字符数计算,并受 maxLength 上限约束
失败退还提取失败时全额退还预留积分

内容提取本身没有预估接口——最终的 credits 值要在内容长度结算后才能确定。可用 GET /v1/user/subscription 查询实时余额;积分与功能的对应关系参见定价


On this page