内容提取
从 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']请求参数:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
source | object | 是 | 提取来源 |
source.type | string | 是 | 必须为 "url" |
source.uri | string | 是 | 要提取内容的 URL |
options | object | 否 | 提取选项(默认 {}) |
options.summarize | boolean | 否 | 对提取的文本生成 AI 摘要(默认 false) |
options.maxLength | integer | 否 | 内容最大长度(字符数,默认 100000,最小 1,最大 500000) |
options.twitter | object | 否 | Twitter/X 专用选项 |
options.twitter.count | integer | 否 | 从个人主页 URL 获取的推文数量(1–100,默认 20) |
响应示例:
{
"code": 0,
"message": "success",
"data": {
"taskId": "67f6a1b2c3d4e5f6a7b8c9d0"
}
}taskId 是 24 位十六进制字符串,将其传给下方的状态查询接口。
查询任务状态
GET /v1/content/extract/{taskId}
轮询此接口直到 status 为 completed 或 failed。任务运行期间,响应仅携带状态——提取出的内容会等到提取与扣费结算完成后才返回。
请求示例:
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'])路径参数:
| 字段 | 类型 | 说明 |
|---|---|---|
taskId | string | 创建接口返回的 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"
}
}响应字段:
| 字段 | 类型 | 说明 |
|---|---|---|
taskId | string | 任务标识符 |
status | string | processing、completed 或 failed |
createdAt | integer | 创建时间,13 位毫秒级时间戳 |
data | object | 提取的内容,仅当 status 为 completed 时返回 |
data.content | string | 提取的文本内容(summarize: true 时为摘要) |
data.metadata | object | 页面元数据,如标题、作者 |
data.references | array | 内容中发现的引用 URL |
credits | integer | 消耗的积分(status 为 completed 时返回) |
failCode | integer | 错误码(status 为 failed 时返回) |
message | string | 错误描述(status 为 failed 时返回) |
注意事项
Twitter/X 个人主页 URL:
- 当源 URL 为 Twitter/X 个人主页(如
https://x.com/username)时,API 会获取最近的推文。 - 使用
options.twitter.count控制获取推文数量(1–100,默认20)。 - 非 Twitter URL 会忽略此选项。
微信公众号:
- 使用完整的
mp.weixin.qq.com/s/...文章链接。 - 提取结果包含文章正文和元数据。
任务生命周期:
| 状态 | 说明 |
|---|---|
processing | 提取进行中 |
completed | 内容提取成功 |
failed | 提取失败 -- 请检查 failCode 和 message |
轮询建议:
- 首次等待:任务创建后等待 5 秒
- 轮询间隔:5 秒
- 典型完成时间:10-30 秒,取决于 URL 复杂度
积分消耗:
内容提取在任务开始时预扣积分,待内容长度确定后结算为实际金额。完成响应中的 credits 字段反映最终扣费。
| 规则 | 说明 |
|---|---|
| 预扣 | 任务开始时预留一笔积分 |
| 实际扣费 | 按提取内容的字符数计算,并受 maxLength 上限约束 |
| 失败退还 | 提取失败时全额退还预留积分 |
内容提取本身没有预估接口——最终的 credits 值要在内容长度结算后才能确定。可用 GET /v1/user/subscription 查询实时余额;积分与功能的对应关系参见定价。