diff --git a/plugins/mipu-api/skills/mipu-api/SKILL.md b/plugins/mipu-api/skills/mipu-api/SKILL.md index 2bff3c3..f248630 100644 --- a/plugins/mipu-api/skills/mipu-api/SKILL.md +++ b/plugins/mipu-api/skills/mipu-api/SKILL.md @@ -20,9 +20,9 @@ allowed-tools: "Read,Grep,Glob" | 前缀 | 类别 | 内容 | |------|------|------| -| 01-01 | 解锁器 | Unlocker API(Agent/Request 模式、异步轮询、mipu_requests SDK) | | 02-xx | 缓存查询 | cache/search | | 03-01~03-05 | 报价相关 | search、select、baggage、seat、async-query | +| 03-06 | 解锁器 | Unlocker API(Agent/Request 模式、异步轮询、mipu_requests SDK) | | 04-01~04-05 | 订单管理 | hold、payment、query、cancel、retry | | 07-01~07-04 | 请求实体 | FlightSegmentRequest、Passenger、ContactInfo、Ancillary | | 08-01~08-06 | 响应实体 | Itinerary、FlightFare、SegmentElement、FlightPolicy、AncillaryProduct、feeItems | diff --git a/plugins/mipu-api/skills/mipu-api/docs/01-01_unlocker.md b/plugins/mipu-api/skills/mipu-api/docs/01-01_unlocker.md deleted file mode 100644 index e9f6d51..0000000 --- a/plugins/mipu-api/skills/mipu-api/docs/01-01_unlocker.md +++ /dev/null @@ -1,381 +0,0 @@ - -# 解锁器 (Unlocker) - -## 概述 - -解锁器是米普云的核心代理服务,允许你通过米普 API 代理发送 HTTP 请求到目标网站。所有请求经过米普网关转发,目标网站看到的是米普的 IP 和会话,而非你的真实信息。 - -### 典型用途 - -- 代理访问航司官网,模拟浏览器操作 -- 通过 Agent 机制维持登录态和会话 -- 获取航司网页数据(HTML、JSON) - -### 两种模式 - -| 模式 | 端点 | 适用场景 | -|------|------|----------| -| Agent 模式 | `/unlocker/agent` | 通过 Agent 代理,Agent 维持登录态和会话,适合需要身份验证的场景 | -| Request 模式 | `/unlocker/request` | 直接代理请求,无需 Agent,适合简单的 HTTP 代理场景 | - -## 认证 - -所有请求必须包含以下 Header: - -| 参数 | 值 | 说明 | -|------|-----|------| -| Content-Type | application/json | 固定值 | -| Accept-Encoding | gzip, deflate, br | 必填 | -| client-key | (由米普云提供) | 客户端 key | -| client-secret | (由米普云提供) | 客户端 secret | - -## 请求说明 - -### Agent 模式 - -| 项目 | 值 | -|------|-----| -| URL | `POST https://{endpoint}/unlocker/agent` | -| Content-Type | application/json | - -**请求体:** - -```json -{ - "url": "https://www.example.com/page", - "method": "GET", - "agent": "JQ", - "proxy": "res_mipu_xxx", - "async": true, - "headers": { - "user-agent": "Mozilla/5.0 ...", - "accept": "text/html" - }, - "sessionId": "" -} -``` - -| 字段 | 类型 | 必填 | 说明 | -|------|------|------|------| -| url | string | 是 | 目标 URL | -| method | string | 是 | HTTP 方法:GET、POST、PUT、DELETE 等 | -| agent | string | 是 | Agent 编码(在米普控制台创建) | -| proxy | string | 是 | 代理资源标识(在米普控制台获取) | -| async | boolean | 否 | 是否异步模式,默认 true | -| headers | object | 否 | 请求头(传递给目标网站) | -| body | string | 否 | 请求体(POST/PUT 时使用) | -| contentType | string | 否 | Content-Type 覆盖 | -| sessionId | string | 否 | 会话 ID(首次请求后自动返回,后续请求传入以保持会话) | - -### Request 模式 - -| 项目 | 值 | -|------|-----| -| URL | `POST https://{endpoint}/unlocker/request` | -| Content-Type | application/json | - -请求体与 Agent 模式相同,但**不需要 `agent` 字段**。请求直接到达网关,不经过 Agent。 - -## 响应说明 - -### 同步响应 - -当 `async=false` 或目标网站快速返回时,直接返回结果: - -```json -{ - "code": 0, - "sessionId": "abc123", - "statusCode": 200, - "responseBody": "...", - "responseHeaders": { - "content-type": "text/html" - } -} -``` - -| 字段 | 类型 | 说明 | -|------|------|------| -| code | int | 0 = 成功,其他见错误码 | -| sessionId | string | 会话 ID,后续请求传入以保持会话连续性 | -| statusCode | int | 目标网站返回的 HTTP 状态码 | -| responseBody | string | 目标网站返回的响应体 | -| responseHeaders | object | 目标网站返回的响应头 | - -### 异步响应 - -当 `async=true` 时,首次提交返回: - -```json -{ - "code": 202, - "agentRequestId": "req_xxx" -} -``` - -需要通过异步查询接口轮询获取结果。 - -## 异步查询 - -| 项目 | 值 | -|------|-----| -| URL | `GET https://{endpoint}/async/query/{agentRequestId}` | - -**请求头:** - -| 参数 | 值 | -|------|-----| -| client-key | 客户端 key | -| client-secret | 客户端 secret | - -**轮询策略:** - -1. 提交请求后等待 2 秒 -2. 每隔 3 秒查询一次 -3. 最多查询 20 次(约 62 秒) -4. 返回 `code=0` 表示完成 -5. 超过最大次数仍无结果则视为超时 - -## 错误码 - -| 码 | 含义 | 处理建议 | -|----|------|----------| -| 0 | 成功 | — | -| 100 | 鉴权失败 | 检查 client-key 和 client-secret | -| 102 | 超过限流 | 降低请求频率,稍后重试 | -| 103 | Proxy 错误 | 检查 proxy 标识是否正确,IP 是否可用 | -| 104 | Agent 不存在 | 检查 agent 编码,新创建的 Agent 需等待 5 分钟生效 | -| 202 | 异步处理中 | 继续轮询 /async/query/{id} | - -更多错误码请查阅 `10_error-codes.md`。 - -## 会话管理(sessionId) - -sessionId 用于保持与目标网站的会话连续性。工作流程: - -``` -第 1 次请求: 传入 sessionId = ""(空或不传) - ↓ -响应返回: sessionId = "abc123" - ↓ -第 2 次请求: 传入 sessionId = "abc123" - ↓ -响应返回: sessionId = "abc123"(相同会话) -``` - -- 首次请求不传 sessionId -- 从第一次响应中获取 sessionId -- 后续请求都传入该 sessionId -- 同一 sessionId 共享 Cookie、登录态等 - -## 直接调用示例 - -### cURL - -```bash -curl -X POST "https://api-eu.mipuyun.com/unlocker/agent" \ - -H "Content-Type: application/json" \ - -H "client-key: " \ - -H "client-secret: " \ - -d '{ - "url": "https://www.example.com/api/data", - "method": "GET", - "agent": "JQ", - "proxy": "res_mipu_xxx", - "async": true, - "headers": { - "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)" - } - }' -``` - -### Python (requests) - -```python -import requests - -API_URL = "https://api-eu.mipuyun.com/unlocker/agent" -HEADERS = { - "Content-Type": "application/json", - "client-key": "", - "client-secret": "", -} - -# 提交请求 -payload = { - "url": "https://www.example.com/api/data", - "method": "GET", - "agent": "JQ", - "proxy": "res_mipu_xxx", - "async": True, - "headers": {"user-agent": "Mozilla/5.0"}, -} -resp = requests.post(API_URL, json=payload, headers=HEADERS) -data = resp.json() - -# 异步轮询 -if data["code"] == 202: - import time - query_url = f"https://api-eu.mipuyun.com/async/query/{data['agentRequestId']}" - for _ in range(20): - time.sleep(3) - result = requests.get(query_url, headers=HEADERS).json() - if result["code"] == 0: - print(result["responseBody"]) - break -``` - -## 使用 mipu_requests SDK - -[`mipu-requests`](https://pypi.org/project/mipu-requests/) 是米普官方 Python SDK,兼容 `requests` 接口,封装了解锁器的提交、异步轮询、会话管理等细节。 - -### 安装 - -```bash -pip install mipu-requests -``` - -### 基础用法 - -```python -import mipu_requests - -# 创建 Session(凭据通过构造参数传入) -s = mipu_requests.session( - base_url="https://api-eu.mipuyun.com", - client_key="", - client_secret="", - agent="JQ", -) - -# 设置代理 -s.proxies = "res_mipu_xxx" - -# 发送 GET 请求(SDK 自动处理异步轮询) -resp = s.get("https://www.example.com/page", - headers={"user-agent": "Mozilla/5.0"}) - -print(resp.status_code) # 200 -print(resp.text) # 目标网站 HTML -print(resp.session_id) # 自动管理的 sessionId - -# 发送 POST 请求 -resp = s.post("https://www.example.com/api", - json={"key": "value"}, - headers={"content-type": "application/json"}) -print(resp.json()) -``` - -### Agent 模式 vs Request 模式 - -```python -# Agent 模式 — 通过 Agent 代理(默认) -s = mipu_requests.session(..., agent="JQ") - -# Request 模式 — 直接代理,无需 Agent -s = mipu_requests.session(..., mode="request") -``` - -### 异步模式 - -SDK 默认启用异步模式,自动处理提交和轮询: - -```python -# 默认异步(推荐) -s = mipu_requests.session(..., async_mode=True) - -# 关闭异步(同步等待,可能因长连接断连) -s = mipu_requests.session(..., async_mode=False) - -# 自定义轮询参数 -s = mipu_requests.session( - ..., - poll_interval=3, # 轮询间隔(秒) - poll_max=20, # 最大轮询次数 - submit_timeout=60, # 提交超时(秒) - poll_timeout=(5, 30), # 轮询超时 (connect, read) -) -``` - -### 会话管理 - -SDK 自动管理 sessionId,无需手动传递: - -```python -s = mipu_requests.session(...) - -# 第 1 次请求 — SDK 自动获取 sessionId -resp1 = s.get("https://example.com/login") -# s.session_id 已自动设置 - -# 第 2 次请求 — SDK 自动传入 sessionId,保持会话 -resp2 = s.get("https://example.com/dashboard") -``` - -### 错误处理 - -```python -import mipu_requests - -try: - resp = s.get("https://example.com/api") - resp.raise_for_status() # 目标网站 4xx/5xx 时抛出异常 -except mipu_requests.HTTPError as e: - print(f"目标网站错误: {e.response.status_code}") -except mipu_requests.APIError as e: - print(f"米普 API 错误: {e}") -except mipu_requests.PollTimeoutError as e: - print(f"异步轮询超时: {e}") -except mipu_requests.RequestException as e: - print(f"请求异常: {e}") -``` - -### 完整流程示例 - -```python -import mipu_requests - -with mipu_requests.session( - base_url="https://api-eu.mipuyun.com", - client_key="", - client_secret="", - agent="JQ", -) as s: - s.proxies = "res_mipu_xxx" - - # 访问首页 - resp = s.get("https://www.example.com/home") - resp.raise_for_status() - - # 提交表单(sessionId 自动传递) - resp = s.post("https://www.example.com/submit", - data={"field": "value"}, - headers={"content-type": "application/x-www-form-urlencoded"}) - resp.raise_for_status() - print(resp.json()) -``` - -## 从 requests 迁移 - -如果已有 `requests` 代码,迁移只需两步: - -```python -# ── 迁移前 ── -import requests -s = requests.Session() -s.proxies = {"https": "http://proxy:8080"} -resp = s.get("https://example.com/api") - -# ── 迁移后 ── -import mipu_requests -s = mipu_requests.session( - base_url="https://api-eu.mipuyun.com", - client_key="", - client_secret="", - agent="JQ", -) -s.proxies = "res_mipu_xxx" -resp = s.get("https://example.com/api") -``` - -`.get()`、`.post()`、`.json()`、`.raise_for_status()` 等方法完全兼容,其余代码无需改动。 diff --git a/plugins/mipu-api/skills/mipu-api/docs/03-06_unlocker.md b/plugins/mipu-api/skills/mipu-api/docs/03-06_unlocker.md new file mode 100644 index 0000000..9eccbb0 --- /dev/null +++ b/plugins/mipu-api/skills/mipu-api/docs/03-06_unlocker.md @@ -0,0 +1,275 @@ + +# 解锁器 (Unlocker) + +解锁器是米普云的核心代理服务,通过米普 API 代理发送 HTTP 请求到目标网站。目标网站看到的是米普的 IP 和会话,而非你的真实信息。 + +## 安装 SDK + +```bash +pip install mipu-requests +``` + +升级到最新版本: + +```bash +pip install --upgrade mipu-requests +``` + +查看当前版本: + +```bash +pip show mipu-requests +``` + +## 快速开始 + +```python +import mipu_requests + +s = mipu_requests.session( + base_url="https://api-eu.mipuyun.com", + client_key="", + client_secret="", + agent="JQ", +) +s.proxies = "res_mipu_xxx" + +# 发送请求(SDK 自动处理异步轮询、会话管理) +resp = s.get("https://www.example.com/page", + headers={"user-agent": "Mozilla/5.0"}) +resp.raise_for_status() +print(resp.text) +``` + +## 从 requests 迁移 + +只需两步: + +1. `import requests` → `import mipu_requests` +2. 构造时传入凭据,`proxies` 改为字符串 + +```python +# ── 迁移前 ── +import requests +s = requests.Session() +s.proxies = {"https": "http://proxy:8080"} +resp = s.get("https://example.com/api") + +# ── 迁移后 ── +import mipu_requests +s = mipu_requests.session( + base_url="https://api-eu.mipuyun.com", + client_key="", + client_secret="", + agent="JQ", +) +s.proxies = "res_mipu_xxx" +resp = s.get("https://example.com/api") +``` + +`.get()`、`.post()`、`.json()`、`.raise_for_status()` 等方法完全兼容,其余代码无需改动。 + +## 请求方法 + +```python +resp = s.get(url, params={"key": "value"}, headers={...}) +resp = s.post(url, data={"key": "value"}, headers={...}) +resp = s.post(url, json={"key": "value"}, headers={...}) +resp = s.put(url, data=body, headers={...}) +resp = s.delete(url, headers={...}) +``` + +## Agent 模式 vs Request 模式 + +```python +# Agent 模式 — 通过 Agent 代理,维持登录态和会话(默认) +s = mipu_requests.session(..., agent="JQ") + +# Request 模式 — 直接代理,无需 Agent +s = mipu_requests.session(..., mode="request") +``` + +## 异步模式 + +SDK 默认启用异步模式,自动处理提交和轮询: + +```python +# 默认异步(推荐) +s = mipu_requests.session(..., async_mode=True) + +# 关闭异步 +s = mipu_requests.session(..., async_mode=False) + +# 自定义轮询参数 +s = mipu_requests.session( + ..., + poll_interval=3, # 轮询间隔(秒) + poll_max=20, # 最大轮询次数 + submit_timeout=60, # 提交超时(秒) + poll_timeout=(5, 30), # 轮询超时 (connect, read) +) +``` + +## 会话管理 + +SDK 自动管理 sessionId,无需手动传递: + +```python +s = mipu_requests.session(...) + +# 第 1 次请求 — SDK 自动获取 sessionId +resp1 = s.get("https://example.com/login") + +# 第 2 次请求 — SDK 自动传入 sessionId,保持会话 +resp2 = s.get("https://example.com/dashboard") +``` + +## 错误处理 + +```python +import mipu_requests + +try: + resp = s.get("https://example.com/api") + resp.raise_for_status() +except mipu_requests.HTTPError as e: + print(f"目标网站错误: {e.response.status_code}") +except mipu_requests.APIError as e: + # 米普 API 返回非零 code,如反爬失败、鉴权失败等 + print(f"API 错误: {e}") +except mipu_requests.PollTimeoutError as e: + print(f"异步轮询超时: {e}") +except mipu_requests.RequestException as e: + print(f"请求异常: {e}") +``` + +## Response 对象 + +与 `requests.Response` 完全兼容: + +```python +resp.status_code # int 目标网站 HTTP 状态码 +resp.text # str 响应体文本 +resp.content # bytes 响应体字节 +resp.headers # dict 响应头 +resp.ok # bool status_code 在 200-399 +resp.url # str 请求 URL +resp.json() # dict 解析 JSON +resp.raise_for_status() # >=400 抛异常 +resp.session_id # str 当前会话 ID +``` + +## 完整流程示例 + +```python +import mipu_requests + +with mipu_requests.session( + base_url="https://api-eu.mipuyun.com", + client_key="", + client_secret="", + agent="JQ", +) as s: + s.proxies = "res_mipu_xxx" + + # 访问首页 + resp = s.get("https://www.example.com/home") + resp.raise_for_status() + + # 提交表单(sessionId 自动传递) + resp = s.post("https://www.example.com/submit", + data={"field": "value"}, + headers={"content-type": "application/x-www-form-urlencoded"}) + resp.raise_for_status() + print(resp.json()) +``` + +--- + +## 原始 API 参考 + +以下为直接调用解锁器 API 的参考,推荐优先使用上方 SDK。 + +### 认证 + +所有请求必须包含以下 Header: + +| 参数 | 值 | 说明 | +|------|-----|------| +| Content-Type | application/json | 固定值 | +| client-key | (由米普云提供) | 客户端 key | +| client-secret | (由米普云提供) | 客户端 secret | + +### Agent 模式 + +| 项目 | 值 | +|------|-----| +| URL | `POST https://{endpoint}/unlocker/agent` | + +**请求体:** + +```json +{ + "url": "https://www.example.com/page", + "method": "GET", + "agent": "JQ", + "proxy": "res_mipu_xxx", + "async": true, + "headers": {"user-agent": "Mozilla/5.0"}, + "sessionId": "" +} +``` + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| url | string | 是 | 目标 URL | +| method | string | 是 | HTTP 方法 | +| agent | string | 是 | Agent 编码 | +| proxy | string | 是 | 代理资源标识 | +| async | boolean | 否 | 异步模式,默认 true | +| headers | object | 否 | 传递给目标网站的请求头 | +| body | string | 否 | 请求体 | +| contentType | string | 否 | Content-Type 覆盖 | +| sessionId | string | 否 | 会话 ID | + +### Request 模式 + +| 项目 | 值 | +|------|-----| +| URL | `POST https://{endpoint}/unlocker/request` | + +请求体与 Agent 模式相同,但不需要 `agent` 字段。 + +### 同步响应 + +```json +{ + "code": 0, + "sessionId": "abc123", + "statusCode": 200, + "responseBody": "...", + "responseHeaders": {"content-type": "text/html"} +} +``` + +### 异步响应 + +首次提交返回 `{"code": 202, "agentRequestId": "req_xxx"}`,通过轮询接口获取结果: + +| 项目 | 值 | +|------|-----| +| URL | `GET https://{endpoint}/async/query/{agentRequestId}` | + +### 错误码 + +| 码 | 含义 | 处理建议 | +|----|------|----------| +| 0 | 成功 | — | +| 100 | 鉴权失败 | 检查 client-key 和 client-secret | +| 102 | 超过限流 | 降低请求频率,稍后重试 | +| 103 | Proxy 错误 | 检查 proxy 标识是否正确 | +| 104 | Agent 不存在 | 检查 agent 编码,新创建的 Agent 需等待 5 分钟生效 | +| 202 | 异步处理中 | 继续轮询 | +| 403 | 反爬拦截 | 目标网站触发了反爬机制 | + +更多错误码请查阅 `10_error-codes.md`。