> ## Documentation Index
> Fetch the complete documentation index at: https://help.miyaip.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Crawler API 接入教程：任务提交、查询与计费

> 使用 cURL 或 Python 调用 MiyaIP Crawler API，读取接口参数、提交并查询异步任务，处理错误并核对 credits 消耗。

Crawler API 创建异步抓取任务。按**查询接口 → 读取参数 → 提交一次 → 查询同一任务 → 核对扣费**完成调用。你可以在[控制台](https://miyaip.com/dashboard/crawlerInvoke?tab=invoke)查看接口、套餐和调用日志。

## 准备鉴权

基址为 `https://miyaip.com`。先登录控制台，在浏览器开发者工具的\*\*网络（Network）\*\*面板中查看你自己的 `/api/SysLogin/GetUserInfo` 请求，仅复制 `Authorization` 头中 `Bearer` 后的 Token。这是控制台登录会话凭证；MCP 密钥只用于 MCP 服务，不能替代它。

以下命令使用 Bash、支持 `--fail-with-body` 的 cURL，以及 Python 3.8 或更高版本。在 Windows 中使用 `curl.exe`，并在 PowerShell 中通过 `$env:变量名` 设置同名变量。Token 请保留在本地；创建任务可能消耗账户 credits。

```bash theme={null}
read -rsp 'Console token: ' MIYA_CONSOLE_TOKEN
echo
export MIYA_CONSOLE_TOKEN
export MIYA_INTERFACE_KEY='replace-with-an-interface-key'
```

## 完成一次任务

<Steps>
  <Step title="查询可用接口">
    从返回的接口数组中选择已启用的接口，使用它的实际 `InterfaceKey`。

    ```bash theme={null}
    curl --fail-with-body -sS --max-time 30 \
      -H "Authorization: Bearer $MIYA_CONSOLE_TOKEN" \
      https://miyaip.com/api/CrawlerInterface/List
    ```
  </Step>

  <Step title="读取所选接口的参数定义">
    ```bash theme={null}
    curl --fail-with-body -sS --max-time 30 --get \
      -H "Authorization: Bearer $MIYA_CONSOLE_TOKEN" \
      --data-urlencode "interfaceKey=$MIYA_INTERFACE_KEY" \
      https://miyaip.com/api/CrawlerInterface/Detail
    ```

    解析返回的 `ParamSchema` 字符串。按实际字段名、类型、必填值和限制创建 `params.json`，文件中只放该接口的参数对象。仅没有必填参数时才使用 `{}`。
  </Step>

  <Step title="只提交一次任务">
    用保存的参数对象生成请求。保留以下请求字段的大小写。

    ```bash theme={null}
    python -c 'import json,os; p=json.load(open("params.json",encoding="utf-8")); print(json.dumps({"InterfaceKey":os.environ["MIYA_INTERFACE_KEY"],"Params":p}))' > request.json
    curl --fail-with-body -sS --max-time 30 \
      -H "Authorization: Bearer $MIYA_CONSOLE_TOKEN" \
      -H 'Content-Type: application/json' \
      --data-binary @request.json \
      https://miyaip.com/api/Crawler/Invoke
    ```

    同时检查 HTTP 状态与数字业务 `code`。创建成功会返回 `taskId`、运行状态和 `costCredits`，不表示抓取已经完成。保留返回的任务 ID。
  </Step>

  <Step title="查询已创建的任务">
    ```bash theme={null}
    export MIYA_TASK_ID='replace-with-returned-taskId'
    curl --fail-with-body -sS --max-time 30 --get \
      -H "Authorization: Bearer $MIYA_CONSOLE_TOKEN" \
      --data-urlencode "taskId=$MIYA_TASK_ID" \
      https://miyaip.com/api/Crawler/TaskResult
    ```

    状态为 `running` 时，通常间隔五秒再次查询此接口。到达 `success`、`failed` 或 `timeout` 后停止轮询。成功后还要检查 `result` 是否包含应用需要的数据。

    本地等待超时不会取消服务端任务。保留 `taskId`，稍后继续查询。如果创建请求超时，先查看调用日志再决定是否重新提交；没有收到响应不代表任务没有创建。
  </Step>

  <Step title="核对实际消耗和调用日志">
    读取任务响应的 `costCredits`，与控制台调用日志核对。计算套餐能运行多少任务时，要考虑接口与参数，不能把 credits 数量直接当作任务数量。
  </Step>
</Steps>

## 使用完整 Python 脚本

[下载 crawler\_api.py](/examples/crawler_api.py)。两种语言共用此脚本，仅使用 Python 标准库。它会先检查接口定义，提交一次任务，再按期限轮询；兼容常用响应字段大小写，遇到未知状态停止，避免将 Token 转发到重定向主机，失败时退出码为 `1`。

```bash theme={null}
python crawler_api.py "$MIYA_INTERFACE_KEY" params.json --wait-seconds 600
```

默认单次请求超时为 30 秒，轮询期限为 600 秒。这是客户端设置。任务 ID 输出到 stderr，最终任务对象输出到 stdout。脚本结束不会取消服务端任务。

## 接口参考

| 方法与路径 | 请求 | 返回信息 |
| - | - | - |
| `GET /api/CrawlerInterface/List` | 无参数 | 接口定义、名称、`ParamSchema`、消耗元数据和启用状态 |
| `GET /api/CrawlerInterface/Detail` | Query：`interfaceKey` | 单个接口当前的参数与消耗定义 |
| `POST /api/Crawler/Invoke` | JSON：`InterfaceKey` 与对象 `Params` | `taskId`、运行状态、`costCredits` |
| `GET /api/Crawler/TaskResult` | Query：`taskId` | 状态、`result`、`error`、credits、`totalCostMs`、开始和结束时间 |
| `GET /api/Crawler/CallLogPage` | `PageNo=1`、`PageSize=10`；其他筛选项见下文 | 记录、总数、请求与结果 JSON、错误、credits、耗时及 `refunded` |

日志可选筛选字段包括 `KeyWord`、`InterfaceKey`、`Status`、`SearchBeginTime`、`SearchEndTime`。状态值为 `running`、`success`、`failed`、`timeout`。日期边界使用 `YYYY-MM-DD 00:00:00` 和 `YYYY-MM-DD 23:59:59`；比较统计区间前先确认服务端时区。`UserId` 是管理员筛选项，不会授予读取其他用户记录的权限。

响应通常采用 `{ code, message, body }`，数字业务码 `0` 和 `200` 表示成功。脚本也会解包外层 `data` 对象。响应可能使用 `body`/`Body` 及 camelCase/PascalCase 字段；请求参数保留文档规定的大小写。

## 解析 ParamSchema

`ParamSchema` 是内容为字段定义数组的 JSON 字符串，不是标准 JSON Schema 文档。下面仅展示解析后的结构，不代表某个在线接口的契约：

```json theme={null}
[
  { "name": "url", "label": "URL", "type": "string", "required": true },
  { "name": "limit", "label": "Limit", "type": "int", "min": 1, "max": 100, "default": 10 }
]
```

| 属性 | 使用方法 |
| - | - |
| `name`、`label` | 提交 `name`，用 `label` 显示说明 |
| `required`、`default` | 填写必填值并检查默认值 |
| `type` | 按定义使用 `string`、`int`、`number`、`float`、`bool`、`enum`、`string[]` |
| `min`、`max`、`options` | 检查数值上下限、整数要求、有限值和枚举选项 |
| `showWhen` | 不同键之间为 AND，同一键候选值之间为 OR；条件不满足时不提交该字段 |
| `hidden`、`advanced`、`group` | 展示提示；隐藏字段不代表自动省略已有有效值 |

请求中使用 JSON 布尔值和数组。是否支持渲染、会话或特定输出格式，以接口当前的定义为准。

## 处理结果和错误

`success` 后的 `result` 可能是对象、数组、字符串或 null。`totalCostMs` 的单位是毫秒。任务状态成功后，仍需单独验证结果内容。

| 情况 | 处理方法 |
| - | - |
| HTTP 或业务码 `401` | 重新登录并更换控制台 Token |
| HTTP 失败或业务码不是 `0`/`200` | 读取服务端响应；不能仅凭 HTTP 200 判定成功 |
| `failed` 或 `timeout` | 停止轮询，查看 `error` 和现有调用日志 |
| 达到本地等待期限 | 保留任务 ID，稍后恢复查询 |
| JSON 格式异常或未知状态 | 停止执行，保留已有任务 ID，查看日志时不暴露 Token |

SignalR 是可选机制。控制台订阅 `PublicCrawlerTaskStatus`，Hub 地址取决于部署配置。没有确认的 Hub 地址时使用 HTTP 轮询即可，重连不需要再创建一个任务。

## 理解 credits 和限制

存在计费参数和乘数时，预估消耗为：

```text theme={null}
CreditCostBase + Params[CreditCostParam] × CreditCostMultiplier
```

否则采用基础消耗。实际返回的扣费以 `costCredits` 为准。例如，**1,000 credits ÷ 每个任务 2 credits = 500 个同类任务**。Credits 不等于保证完成的 API 调用次数或成功结果数量。`refunded` 记录退款状态，不保证所有失败任务免费。

并发限制同时运行的任务数量。当前契约没有提供独立轮询费率、任务保留保证、确切退款时点或完整限流错误码清单。规划用量前查看当前接口、套餐与控制台信息。

当前契约可参考[官方 API 文档](https://miyaip.com/docs/crawler-api)与[消耗指南](https://miyaip.com/blog/web-scraping-api-cost)。本项目示例使用离线响应验证，没有执行付费生产任务。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.