uapi-sdk-python 0.1.5__tar.gz → 0.1.13__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {uapi_sdk_python-0.1.5 → uapi_sdk_python-0.1.13}/PKG-INFO +2 -2
- {uapi_sdk_python-0.1.5 → uapi_sdk_python-0.1.13}/README.md +1 -1
- {uapi_sdk_python-0.1.5 → uapi_sdk_python-0.1.13}/pyproject.toml +1 -3
- {uapi_sdk_python-0.1.5 → uapi_sdk_python-0.1.13}/uapi/client.py +298 -157
- uapi_sdk_python-0.1.13/uapi/errors.py +335 -0
- {uapi_sdk_python-0.1.5 → uapi_sdk_python-0.1.13}/uapi_sdk_python.egg-info/PKG-INFO +2 -2
- uapi_sdk_python-0.1.5/uapi/errors.py +0 -153
- {uapi_sdk_python-0.1.5 → uapi_sdk_python-0.1.13}/setup.cfg +0 -0
- {uapi_sdk_python-0.1.5 → uapi_sdk_python-0.1.13}/tests/test_client.py +0 -0
- {uapi_sdk_python-0.1.5 → uapi_sdk_python-0.1.13}/uapi/__init__.py +0 -0
- {uapi_sdk_python-0.1.5 → uapi_sdk_python-0.1.13}/uapi_sdk_python.egg-info/SOURCES.txt +0 -0
- {uapi_sdk_python-0.1.5 → uapi_sdk_python-0.1.13}/uapi_sdk_python.egg-info/dependency_links.txt +0 -0
- {uapi_sdk_python-0.1.5 → uapi_sdk_python-0.1.13}/uapi_sdk_python.egg-info/requires.txt +0 -0
- {uapi_sdk_python-0.1.5 → uapi_sdk_python-0.1.13}/uapi_sdk_python.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: uapi-sdk-python
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.13
|
|
4
4
|
Summary: Idiomatic UAPI SDK for Python
|
|
5
5
|
Author-email: UAPI <dev@uapis.cn>
|
|
6
6
|
Requires-Python: >=3.9
|
|
@@ -14,7 +14,7 @@ Requires-Dist: isort; extra == "dev"
|
|
|
14
14
|
|
|
15
15
|
# uapi-sdk-python
|
|
16
16
|
|
|
17
|
-

|
|
18
18
|
|
|
19
19
|
[](https://www.python.org/)
|
|
20
20
|
[](https://uapis.cn/)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# uapi-sdk-python
|
|
2
2
|
|
|
3
|
-

|
|
4
4
|
|
|
5
5
|
[](https://www.python.org/)
|
|
6
6
|
[](https://uapis.cn/)
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "uapi-sdk-python"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.13"
|
|
8
8
|
description = "Idiomatic UAPI SDK for Python"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -27,5 +27,3 @@ strict = true
|
|
|
27
27
|
|
|
28
28
|
[tool.isort]
|
|
29
29
|
profile = "black"
|
|
30
|
-
|
|
31
|
-
|
|
@@ -15,7 +15,8 @@ class _Config:
|
|
|
15
15
|
class _HTTP:
|
|
16
16
|
def __init__(self, cfg: _Config):
|
|
17
17
|
self._cfg = cfg
|
|
18
|
-
self._client = httpx.Client(timeout=cfg.timeout)
|
|
18
|
+
self._client = httpx.Client(timeout=cfg.timeout, trust_env=False)
|
|
19
|
+
self.last_response_meta: Optional[ResponseMeta] = None
|
|
19
20
|
|
|
20
21
|
def request(self, method: str, path: str, *, params: Dict[str, Any] | None = None, json: Any | None = None, headers: Dict[str, str] | None = None):
|
|
21
22
|
url = self._cfg.base_url.rstrip("/") + path
|
|
@@ -24,7 +25,10 @@ class _HTTP:
|
|
|
24
25
|
headers["Authorization"] = f"Bearer {self._cfg.token}"
|
|
25
26
|
r = self._client.request(method, url, params=params, json=json, headers=headers)
|
|
26
27
|
if r.status_code >= 400:
|
|
27
|
-
|
|
28
|
+
err = map_error(r)
|
|
29
|
+
self.last_response_meta = err.meta
|
|
30
|
+
raise err
|
|
31
|
+
self.last_response_meta = extract_meta(r.headers)
|
|
28
32
|
# try json else bytes
|
|
29
33
|
try:
|
|
30
34
|
return r.json()
|
|
@@ -90,6 +94,10 @@ class UapiClient:
|
|
|
90
94
|
self.zhi_neng_sou_suo = _zhi_neng_sou_suo
|
|
91
95
|
setattr(self, "智能搜索", _zhi_neng_sou_suo)
|
|
92
96
|
|
|
97
|
+
@property
|
|
98
|
+
def last_response_meta(self) -> Optional[ResponseMeta]:
|
|
99
|
+
return self._http.last_response_meta
|
|
100
|
+
|
|
93
101
|
|
|
94
102
|
class _ClipzyZaiXianJianTieBanApi:
|
|
95
103
|
def __init__(self, http: _HTTP):
|
|
@@ -428,12 +436,7 @@ class _ImageApi:
|
|
|
428
436
|
这个接口会获取 Bing 搜索引擎当天全球同步的每日壁纸,并直接以图片形式返回。你可以用它来做应用的启动页、网站背景,或者任何需要每日更新精美图片的地方。
|
|
429
437
|
|
|
430
438
|
## 使用须知
|
|
431
|
-
|
|
432
|
-
> [!NOTE]
|
|
433
|
-
> **响应格式是图片**
|
|
434
|
-
> 请注意,此接口成功时直接返回图片二进制数据(通常为 `image/jpeg`),而非 JSON 格式。请确保客户端能够正确处理。
|
|
435
|
-
|
|
436
|
-
我们内置了备用方案:如果从必应官方获取图片失败,系统会尝试返回一张预存的高质量风景图,以保证服务的稳定性。
|
|
439
|
+
此接口成功时直接返回图片二进制数据,通常是 `image/jpeg`,不是 JSON 格式。接入时请按图片响应来处理。
|
|
437
440
|
"""
|
|
438
441
|
params = {}
|
|
439
442
|
body = {}
|
|
@@ -443,7 +446,7 @@ class _ImageApi:
|
|
|
443
446
|
return self._http.request("GET", path, params=params, json=body if body else None)
|
|
444
447
|
|
|
445
448
|
def get_image_motou(self, **kwargs):
|
|
446
|
-
r"""
|
|
449
|
+
r"""生成摸摸头GIF (QQ号)
|
|
447
450
|
想在线rua一下好友的头像吗?这个趣味接口可以满足你。
|
|
448
451
|
|
|
449
452
|
## 功能概述
|
|
@@ -471,16 +474,7 @@ class _ImageApi:
|
|
|
471
474
|
无论是网址、文本还是联系方式,通通可以变成一个二维码!这是一个非常灵活的二维码生成工具。
|
|
472
475
|
|
|
473
476
|
## 功能概述
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
## 使用须知
|
|
477
|
-
|
|
478
|
-
> [!IMPORTANT]
|
|
479
|
-
> **关键参数 `format`**
|
|
480
|
-
> 此参数决定了成功响应的内容类型和结构,请务必根据你的需求选择并正确处理响应:
|
|
481
|
-
> - **`image`** (默认): 直接返回 `image/png` 格式的图片二进制数据,适合在 `<img>` 标签中直接使用。
|
|
482
|
-
> - **`json`**: 返回一个包含 Base64 Data URI 的 JSON 对象,适合需要在前端直接嵌入CSS或HTML的场景。
|
|
483
|
-
> - **`json_url`**: 返回一个包含图片临时URL的JSON对象,适合需要图片链接的场景。
|
|
477
|
+
你提供一段文本内容,我们为你生成对应的二维码图片。你可以自定义尺寸、前景色、背景色,还支持透明背景,并选择不同的返回格式以适应不同场景。
|
|
484
478
|
"""
|
|
485
479
|
params = {}
|
|
486
480
|
body = {}
|
|
@@ -494,6 +488,15 @@ class _ImageApi:
|
|
|
494
488
|
if "query" == "query" and "format" in kwargs:
|
|
495
489
|
params["format"] = kwargs["format"]
|
|
496
490
|
|
|
491
|
+
if "query" == "query" and "transparent" in kwargs:
|
|
492
|
+
params["transparent"] = kwargs["transparent"]
|
|
493
|
+
|
|
494
|
+
if "query" == "query" and "fgcolor" in kwargs:
|
|
495
|
+
params["fgcolor"] = kwargs["fgcolor"]
|
|
496
|
+
|
|
497
|
+
if "query" == "query" and "bgcolor" in kwargs:
|
|
498
|
+
params["bgcolor"] = kwargs["bgcolor"]
|
|
499
|
+
|
|
497
500
|
path = "/api/v1/image/qrcode"
|
|
498
501
|
|
|
499
502
|
return self._http.request("GET", path, params=params, json=body if body else None)
|
|
@@ -589,7 +592,7 @@ class _ImageApi:
|
|
|
589
592
|
return self._http.request("POST", path, params=params, json=body if body else None)
|
|
590
593
|
|
|
591
594
|
def post_image_motou(self, **kwargs):
|
|
592
|
-
r"""
|
|
595
|
+
r"""生成摸摸头GIF
|
|
593
596
|
除了使用QQ头像,你还可以通过上传自己的图片或提供图片URL来制作独一无二的摸摸头GIF。
|
|
594
597
|
|
|
595
598
|
## 功能概述
|
|
@@ -619,13 +622,47 @@ class _ImageApi:
|
|
|
619
622
|
|
|
620
623
|
return self._http.request("POST", path, params=params, json=body if body else None)
|
|
621
624
|
|
|
625
|
+
def post_image_nsfw(self, **kwargs):
|
|
626
|
+
r"""图片敏感检测
|
|
627
|
+
这是一个图片内容审核接口,自动识别图片中的违规内容并返回处理建议。
|
|
628
|
+
|
|
629
|
+
## 功能概述
|
|
630
|
+
上传图片文件或提供图片URL,接口会自动分析图片内容,返回是否违规、风险等级和处理建议。适合对接到用户上传流程中,实现自动化内容审核。
|
|
631
|
+
|
|
632
|
+
## 返回字段说明
|
|
633
|
+
- **is_nsfw**: 是否判定为违规内容,`true` 表示违规,`false` 表示正常
|
|
634
|
+
- **nsfw_score**: 违规内容置信度,0-1 之间,越高表示越可能违规
|
|
635
|
+
- **normal_score**: 正常内容置信度,0-1 之间,与 nsfw_score 互补
|
|
636
|
+
- **suggestion**: 处理建议
|
|
637
|
+
- `pass`: 内容正常,可以直接放行
|
|
638
|
+
- `review`: 存在风险,建议转人工复核
|
|
639
|
+
- `block`: 高风险内容,建议直接拦截
|
|
640
|
+
- **risk_level**: 风险等级
|
|
641
|
+
- `low`: 低风险
|
|
642
|
+
- `medium`: 中风险
|
|
643
|
+
- `high`: 高风险
|
|
644
|
+
- **label**: 内容标签,`nsfw` 或 `normal`
|
|
645
|
+
- **confidence**: 模型对当前判断的整体置信度
|
|
646
|
+
- **inference_time_ms**: 模型推理耗时,单位毫秒
|
|
647
|
+
"""
|
|
648
|
+
params = {}
|
|
649
|
+
body = {}
|
|
650
|
+
|
|
651
|
+
|
|
652
|
+
if "file" in kwargs:
|
|
653
|
+
body["file"] = kwargs["file"]
|
|
654
|
+
|
|
655
|
+
if "url" in kwargs:
|
|
656
|
+
body["url"] = kwargs["url"]
|
|
657
|
+
|
|
658
|
+
path = "/api/v1/image/nsfw"
|
|
659
|
+
|
|
660
|
+
return self._http.request("POST", path, params=params, json=body if body else None)
|
|
661
|
+
|
|
622
662
|
def post_image_speechless(self, **kwargs):
|
|
623
663
|
r"""生成你们怎么不说话了表情包
|
|
624
664
|
你们怎么不说话了?是不是都在偷偷玩Uapi,求求你们不要玩Uapi了
|
|
625
665
|
|
|
626
|
-
## 效果展示
|
|
627
|
-

|
|
628
|
-
|
|
629
666
|
## 使用须知
|
|
630
667
|
- **响应格式**:接口成功时直接返回 `image/png` 格式的二进制数据。
|
|
631
668
|
- **文字内容**:至少需要提供 `top_text`(上方文字)或 `bottom_text`(下方文字)之一。
|
|
@@ -715,6 +752,91 @@ class _MiscApi:
|
|
|
715
752
|
|
|
716
753
|
return self._http.request("GET", path, params=params, json=body if body else None)
|
|
717
754
|
|
|
755
|
+
def get_misc_district(self, **kwargs):
|
|
756
|
+
r"""Adcode 国内外行政区域查询
|
|
757
|
+
一个接口,覆盖全球 243 个国家、中国省/市/区/街道四级行政区划,支持关键词搜索、行政编码查询、坐标反查三种查询模式(必须至少传入一种查询参数)。
|
|
758
|
+
|
|
759
|
+
## 功能概述
|
|
760
|
+
根据用户输入的搜索条件快速查找行政区域信息。例如:中国 > 山东省 > 济南市 > 历下区 > 舜华路街道。
|
|
761
|
+
|
|
762
|
+
无需注册、无需密钥,直接调用即可获取结构化的行政区域数据。支持三种查询方式:
|
|
763
|
+
- 传 `adcode`,按行政编码精确查询,同时返回下级区划列表
|
|
764
|
+
- 传 `lat` + `lng`,坐标反查附近地点
|
|
765
|
+
- 传 `keywords`,按关键词搜索,支持中英文
|
|
766
|
+
|
|
767
|
+
## 中国与国际数据差异
|
|
768
|
+
中国数据包含 `adcode`、`citycode` 等字段,支持省/市/区/街道四级逐级查询;国际城市数据不含这些字段,但额外提供 `population`(人口)和 `timezone`(时区)。
|
|
769
|
+
|
|
770
|
+
> [!NOTE]
|
|
771
|
+
> 部分城市(如东莞、文昌)没有区县层级,市级下方直接显示街道。街道级别的 `adcode` 返回的是所属区县的 `adcode`。
|
|
772
|
+
"""
|
|
773
|
+
params = {}
|
|
774
|
+
body = {}
|
|
775
|
+
|
|
776
|
+
if "query" == "query" and "keywords" in kwargs:
|
|
777
|
+
params["keywords"] = kwargs["keywords"]
|
|
778
|
+
|
|
779
|
+
if "query" == "query" and "adcode" in kwargs:
|
|
780
|
+
params["adcode"] = kwargs["adcode"]
|
|
781
|
+
|
|
782
|
+
if "query" == "query" and "lat" in kwargs:
|
|
783
|
+
params["lat"] = kwargs["lat"]
|
|
784
|
+
|
|
785
|
+
if "query" == "query" and "lng" in kwargs:
|
|
786
|
+
params["lng"] = kwargs["lng"]
|
|
787
|
+
|
|
788
|
+
if "query" == "query" and "level" in kwargs:
|
|
789
|
+
params["level"] = kwargs["level"]
|
|
790
|
+
|
|
791
|
+
if "query" == "query" and "country" in kwargs:
|
|
792
|
+
params["country"] = kwargs["country"]
|
|
793
|
+
|
|
794
|
+
if "query" == "query" and "limit" in kwargs:
|
|
795
|
+
params["limit"] = kwargs["limit"]
|
|
796
|
+
|
|
797
|
+
path = "/api/v1/misc/district"
|
|
798
|
+
|
|
799
|
+
return self._http.request("GET", path, params=params, json=body if body else None)
|
|
800
|
+
|
|
801
|
+
def get_misc_holiday_calendar(self, **kwargs):
|
|
802
|
+
r"""查询节假日与万年历
|
|
803
|
+
查询指定日期、月份或年份的万年历与节假日信息。
|
|
804
|
+
|
|
805
|
+
## 功能概述
|
|
806
|
+
这个接口支持三种查询方式:按天(`date`)、按月(`month`)和按年(`year`)。调用时三者选一个传入即可。
|
|
807
|
+
|
|
808
|
+
如果你只关心某一类事件,可以通过 `holiday_type` 进行筛选,例如只看法定休假/调休、公历节日、农历节日或节气。
|
|
809
|
+
|
|
810
|
+
在 `date` 模式下,传 `include_nearby=true` 可以额外返回该日期前后最近的节日;返回数量由 `nearby_limit` 控制,默认 7,最大 30。
|
|
811
|
+
"""
|
|
812
|
+
params = {}
|
|
813
|
+
body = {}
|
|
814
|
+
|
|
815
|
+
if "query" == "query" and "date" in kwargs:
|
|
816
|
+
params["date"] = kwargs["date"]
|
|
817
|
+
|
|
818
|
+
if "query" == "query" and "month" in kwargs:
|
|
819
|
+
params["month"] = kwargs["month"]
|
|
820
|
+
|
|
821
|
+
if "query" == "query" and "year" in kwargs:
|
|
822
|
+
params["year"] = kwargs["year"]
|
|
823
|
+
|
|
824
|
+
if "query" == "query" and "timezone" in kwargs:
|
|
825
|
+
params["timezone"] = kwargs["timezone"]
|
|
826
|
+
|
|
827
|
+
if "query" == "query" and "holiday_type" in kwargs:
|
|
828
|
+
params["holiday_type"] = kwargs["holiday_type"]
|
|
829
|
+
|
|
830
|
+
if "query" == "query" and "include_nearby" in kwargs:
|
|
831
|
+
params["include_nearby"] = kwargs["include_nearby"]
|
|
832
|
+
|
|
833
|
+
if "query" == "query" and "nearby_limit" in kwargs:
|
|
834
|
+
params["nearby_limit"] = kwargs["nearby_limit"]
|
|
835
|
+
|
|
836
|
+
path = "/api/v1/misc/holiday-calendar"
|
|
837
|
+
|
|
838
|
+
return self._http.request("GET", path, params=params, json=body if body else None)
|
|
839
|
+
|
|
718
840
|
def get_misc_hotboard(self, **kwargs):
|
|
719
841
|
r"""查询热榜
|
|
720
842
|
想快速跟上网络热点?这个接口让你一网打尽各大主流平台的实时热榜/热搜!
|
|
@@ -722,17 +844,19 @@ class _MiscApi:
|
|
|
722
844
|
## 功能概述
|
|
723
845
|
你只需要指定一个平台类型,就能获取到该平台当前的热榜数据列表。每个热榜条目都包含标题、热度值和原始链接。非常适合用于制作信息聚合类应用或看板。
|
|
724
846
|
|
|
725
|
-
##
|
|
726
|
-
|
|
847
|
+
## 三种使用模式
|
|
848
|
+
|
|
849
|
+
### 默认模式
|
|
850
|
+
只传 `type` 参数,返回该平台当前的实时热榜。
|
|
851
|
+
|
|
852
|
+
### 时光机模式
|
|
853
|
+
传 `type` + `time` 参数,返回最接近指定时间的热榜快照。如果不可用或无数据,会返回空。
|
|
727
854
|
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
| 视频/社区 | bilibili(哔哩哔哩弹幕网), acfun(A站弹幕视频网站), weibo(新浪微博热搜), zhihu(知乎热榜), zhihu-daily(知乎日报热榜), douyin(抖音热榜), kuaishou(快手热榜), douban-movie(豆瓣电影榜单), douban-group(豆瓣小组话题), tieba(百度贴吧热帖), hupu(虎扑热帖), miyoushe(米游社话题榜), ngabbs(NGA游戏论坛热帖), v2ex(V2EX技术社区热帖), 52pojie(吾爱破解热帖), hostloc(全球主机交流论坛), coolapk(酷安热榜) |
|
|
731
|
-
| 新闻/资讯 | baidu(百度热搜), thepaper(澎湃新闻热榜), toutiao(今日头条热榜), qq-news(腾讯新闻热榜), sina(新浪热搜), sina-news(新浪新闻热榜), netease-news(网易新闻热榜), huxiu(虎嗅网热榜), ifanr(爱范儿热榜) |
|
|
732
|
-
| 技术/IT | sspai(少数派热榜), ithome(IT之家热榜), ithome-xijiayi(IT之家·喜加一栏目), juejin(掘金社区热榜), jianshu(简书热榜), guokr(果壳热榜), 36kr(36氪热榜), 51cto(51CTO热榜), csdn(CSDN博客热榜), nodeseek(NodeSeek 技术社区), hellogithub(HelloGitHub 项目推荐) |
|
|
733
|
-
| 游戏 | lol(英雄联盟热帖), genshin(原神热榜), honkai(崩坏3热榜), starrail(星穹铁道热榜) |
|
|
734
|
-
| 其他 | weread(微信读书热门书籍), weatheralarm(天气预警信息), earthquake(地震速报), history(历史上的今天) |
|
|
855
|
+
### 搜索模式
|
|
856
|
+
传 `type` + `keyword` + `time_start` + `time_end` 参数,在指定时间范围内搜索包含关键词的热榜条目。可选传 `limit` 限制返回数量。
|
|
735
857
|
|
|
858
|
+
### 数据源列表
|
|
859
|
+
传 `sources=true`,返回所有支持历史数据的平台列表。
|
|
736
860
|
"""
|
|
737
861
|
params = {}
|
|
738
862
|
body = {}
|
|
@@ -740,10 +864,53 @@ class _MiscApi:
|
|
|
740
864
|
if "query" == "query" and "type" in kwargs:
|
|
741
865
|
params["type"] = kwargs["type"]
|
|
742
866
|
|
|
867
|
+
if "query" == "query" and "time" in kwargs:
|
|
868
|
+
params["time"] = kwargs["time"]
|
|
869
|
+
|
|
870
|
+
if "query" == "query" and "keyword" in kwargs:
|
|
871
|
+
params["keyword"] = kwargs["keyword"]
|
|
872
|
+
|
|
873
|
+
if "query" == "query" and "time_start" in kwargs:
|
|
874
|
+
params["time_start"] = kwargs["time_start"]
|
|
875
|
+
|
|
876
|
+
if "query" == "query" and "time_end" in kwargs:
|
|
877
|
+
params["time_end"] = kwargs["time_end"]
|
|
878
|
+
|
|
879
|
+
if "query" == "query" and "limit" in kwargs:
|
|
880
|
+
params["limit"] = kwargs["limit"]
|
|
881
|
+
|
|
882
|
+
if "query" == "query" and "sources" in kwargs:
|
|
883
|
+
params["sources"] = kwargs["sources"]
|
|
884
|
+
|
|
743
885
|
path = "/api/v1/misc/hotboard"
|
|
744
886
|
|
|
745
887
|
return self._http.request("GET", path, params=params, json=body if body else None)
|
|
746
888
|
|
|
889
|
+
def get_misc_lunartime(self, **kwargs):
|
|
890
|
+
r"""查询农历时间
|
|
891
|
+
需要在指定时区下查看某个时间点的农历信息?这个接口可以直接返回完整结果。
|
|
892
|
+
|
|
893
|
+
## 功能概述
|
|
894
|
+
支持传入 Unix 时间戳(秒或毫秒)和 IANA 时区名,返回公历时间、星期、农历年月日、干支、生肖、节气与节日信息。不传 `ts` 时默认使用当前时间,不传 `timezone` 时默认 `Asia/Shanghai`。
|
|
895
|
+
|
|
896
|
+
## 时区说明
|
|
897
|
+
- 支持标准 IANA 时区,例如 `Asia/Shanghai`、`Asia/Tokyo`
|
|
898
|
+
- 也支持别名:`Shanghai`、`Beijing`
|
|
899
|
+
- 时区非法时返回 400 并提示 `invalid timezone: xxx`
|
|
900
|
+
"""
|
|
901
|
+
params = {}
|
|
902
|
+
body = {}
|
|
903
|
+
|
|
904
|
+
if "query" == "query" and "ts" in kwargs:
|
|
905
|
+
params["ts"] = kwargs["ts"]
|
|
906
|
+
|
|
907
|
+
if "query" == "query" and "timezone" in kwargs:
|
|
908
|
+
params["timezone"] = kwargs["timezone"]
|
|
909
|
+
|
|
910
|
+
path = "/api/v1/misc/lunartime"
|
|
911
|
+
|
|
912
|
+
return self._http.request("GET", path, params=params, json=body if body else None)
|
|
913
|
+
|
|
747
914
|
def get_misc_phoneinfo(self, **kwargs):
|
|
748
915
|
r"""查询手机归属地
|
|
749
916
|
想知道一个手机号码来自哪里?是移动、联通还是电信?这个接口可以告诉你答案。
|
|
@@ -823,7 +990,7 @@ graph TD
|
|
|
823
990
|
> [!WARNING]
|
|
824
991
|
> **接口已过时**:这个接口已被新的 `/convert/unixtime` 取代。新接口功能更强大,支持双向转换。我们建议你迁移到新接口。
|
|
825
992
|
|
|
826
|
-
[
|
|
993
|
+
[➡️ 前往新版接口文档](/docs/api-reference/get-convert-unixtime)
|
|
827
994
|
"""
|
|
828
995
|
params = {}
|
|
829
996
|
body = {}
|
|
@@ -839,9 +1006,6 @@ graph TD
|
|
|
839
1006
|
r"""获取支持的快递公司列表
|
|
840
1007
|
不确定系统支持哪些快递公司?这个接口返回完整的支持列表。
|
|
841
1008
|
|
|
842
|
-
> [!VIP]
|
|
843
|
-
> 本API目前处于**限时免费**阶段,我们鼓励开发者集成和测试。未来,它将转为付费API,为用户提供更稳定和强大的服务。
|
|
844
|
-
|
|
845
1009
|
## 功能概述
|
|
846
1010
|
获取系统当前支持的所有快递公司列表,包括每家公司的标准编码(code)和中文名称(name)。
|
|
847
1011
|
|
|
@@ -861,9 +1025,6 @@ graph TD
|
|
|
861
1025
|
r"""识别快递公司
|
|
862
1026
|
不确定手里的快递单号属于哪家快递公司?这个接口专门做识别,不查物流。
|
|
863
1027
|
|
|
864
|
-
> [!VIP]
|
|
865
|
-
> 本API目前处于**限时免费**阶段,我们鼓励开发者集成和测试。未来,它将转为付费API,为用户提供更稳定和强大的服务。
|
|
866
|
-
|
|
867
1028
|
## 功能概述
|
|
868
1029
|
输入快递单号,系统会根据单号规则快速识别出最可能的快递公司。如果存在多个可能的匹配结果,还会在 `alternatives` 字段中返回备选项,供你参考选择。
|
|
869
1030
|
|
|
@@ -886,15 +1047,15 @@ graph TD
|
|
|
886
1047
|
r"""查询快递物流信息
|
|
887
1048
|
买了东西想知道快递到哪儿了?这个接口帮你实时追踪物流状态。
|
|
888
1049
|
|
|
889
|
-
> [!VIP]
|
|
890
|
-
> 本API目前处于**限时免费**阶段,我们鼓励开发者集成和测试。未来,它将转为付费API,为用户提供更稳定和强大的服务。
|
|
891
|
-
|
|
892
1050
|
## 功能概述
|
|
893
|
-
|
|
1051
|
+
提供一个快递单号,系统会自动识别快递公司并返回完整的物流轨迹信息。这个接口目前可以查询中通、圆通、韵达、申通、极兔、京东、EMS、德邦等主流快递公司的物流信息。
|
|
894
1052
|
|
|
895
1053
|
## 使用须知
|
|
1054
|
+
目前暂不支持顺丰快递单号的物流查询。
|
|
1055
|
+
|
|
896
1056
|
- **自动识别**:不知道是哪家快递?系统会根据单号规则自动识别快递公司(推荐使用)
|
|
897
1057
|
- **手动指定**:如果已知快递公司,可以传递 `carrier_code` 参数,查询速度会更快
|
|
1058
|
+
- **手机尾号验证**:部分快递公司需要验证收件人手机尾号才能查询详细物流,如果返回 `暂无物流信息`,建议尝试传入 `phone` 参数
|
|
898
1059
|
- **查询时效**:物流信息实时查询,响应时间通常在1-2秒内
|
|
899
1060
|
"""
|
|
900
1061
|
params = {}
|
|
@@ -906,23 +1067,38 @@ graph TD
|
|
|
906
1067
|
if "query" == "query" and "carrier_code" in kwargs:
|
|
907
1068
|
params["carrier_code"] = kwargs["carrier_code"]
|
|
908
1069
|
|
|
1070
|
+
if "query" == "query" and "phone" in kwargs:
|
|
1071
|
+
params["phone"] = kwargs["phone"]
|
|
1072
|
+
|
|
909
1073
|
path = "/api/v1/misc/tracking/query"
|
|
910
1074
|
|
|
911
1075
|
return self._http.request("GET", path, params=params, json=body if body else None)
|
|
912
1076
|
|
|
913
1077
|
def get_misc_weather(self, **kwargs):
|
|
914
1078
|
r"""查询天气
|
|
915
|
-
|
|
1079
|
+
出门前,查一下天气总是个好习惯。这个接口为你提供精准、实时的天气数据,支持国内和国际城市。
|
|
916
1080
|
|
|
917
1081
|
## 功能概述
|
|
918
|
-
|
|
1082
|
+
这个接口支持三种查询方式:
|
|
1083
|
+
- 可以传 `adcode`,按行政区编码查询(优先级最高)
|
|
1084
|
+
- 可以传 `city`,按城市名称查询,支持中文(`北京`)和英文(`Tokyo`)
|
|
1085
|
+
- 两个都不传时,按客户端 IP 自动定位查询
|
|
919
1086
|
|
|
920
|
-
|
|
921
|
-
- **参数优先级**:当你同时提供了 `city` (城市名) 和 `adcode` (城市编码) 两个参数时,系统会 **优先使用 `adcode`** 进行查询,因为它更精确。
|
|
922
|
-
- **查询范围**:为了保证查询的准确性,我们的服务仅支持标准的“省”、“市”、“区/县”级别的行政区划名称查询,不保证能查询到乡镇或具体地点。
|
|
1087
|
+
支持 `lang` 参数,可选 `zh`(默认)和 `en`,城市名翻译覆盖 7000+ 城市。
|
|
923
1088
|
|
|
924
|
-
##
|
|
925
|
-
-
|
|
1089
|
+
## 可选功能模块
|
|
1090
|
+
- `extended=true`:扩展气象字段(体感温度、能见度、气压、紫外线、空气质量及污染物分项数据)
|
|
1091
|
+
- `forecast=true`:多天预报(最多7天,会额外返回每天的最高温度、最低温度,以及日出日落、风速等详细数据)
|
|
1092
|
+
- `hourly=true`:逐小时预报(24小时)
|
|
1093
|
+
- `minutely=true`:分钟级降水预报(仅国内城市,精确到2分钟)
|
|
1094
|
+
- `indices=true`:18项生活指数(穿衣、紫外线、洗车、运动、花粉等)
|
|
1095
|
+
|
|
1096
|
+
## 天气字段说明
|
|
1097
|
+
`weather` 是天气现象文本,不是固定枚举。
|
|
1098
|
+
|
|
1099
|
+
常见值包括:晴、多云、阴、小雨、中雨、大雨、雷阵雨、小雪、中雪、大雪、雨夹雪、雾、霾、沙尘。
|
|
1100
|
+
|
|
1101
|
+
如果你的业务需要稳定的天气分类,建议使用 `weather_code` 进行映射。完整的天气图标代码请参考[天气图标代码表](#enum-list)。
|
|
926
1102
|
"""
|
|
927
1103
|
params = {}
|
|
928
1104
|
body = {}
|
|
@@ -936,11 +1112,20 @@ graph TD
|
|
|
936
1112
|
if "query" == "query" and "extended" in kwargs:
|
|
937
1113
|
params["extended"] = kwargs["extended"]
|
|
938
1114
|
|
|
1115
|
+
if "query" == "query" and "forecast" in kwargs:
|
|
1116
|
+
params["forecast"] = kwargs["forecast"]
|
|
1117
|
+
|
|
1118
|
+
if "query" == "query" and "hourly" in kwargs:
|
|
1119
|
+
params["hourly"] = kwargs["hourly"]
|
|
1120
|
+
|
|
1121
|
+
if "query" == "query" and "minutely" in kwargs:
|
|
1122
|
+
params["minutely"] = kwargs["minutely"]
|
|
1123
|
+
|
|
939
1124
|
if "query" == "query" and "indices" in kwargs:
|
|
940
1125
|
params["indices"] = kwargs["indices"]
|
|
941
1126
|
|
|
942
|
-
if "query" == "query" and "
|
|
943
|
-
params["
|
|
1127
|
+
if "query" == "query" and "lang" in kwargs:
|
|
1128
|
+
params["lang"] = kwargs["lang"]
|
|
944
1129
|
|
|
945
1130
|
path = "/api/v1/misc/weather"
|
|
946
1131
|
|
|
@@ -1042,10 +1227,10 @@ class _NetworkApi:
|
|
|
1042
1227
|
|
|
1043
1228
|
def get_network_ipinfo(self, **kwargs):
|
|
1044
1229
|
r"""查询 IP
|
|
1045
|
-
想知道一个IP
|
|
1230
|
+
想知道一个IP地址或域名来自地球的哪个角落?这个接口可以帮你定位它。你可以使用默认数据源,也可以指定 `source=commercial` 参数来查询更详细的商业级IP归属信息。
|
|
1046
1231
|
|
|
1047
1232
|
## 功能概述
|
|
1048
|
-
提供一个公网IPv4、IPv6
|
|
1233
|
+
提供一个公网IPv4、IPv6地址或域名,我们会查询并返回它的地理位置(国家、省份、城市)、经纬度、以及所属的运营商(ISP)和自治系统(ASN)信息。这在网络安全分析、访问来源统计等领域非常有用。
|
|
1049
1234
|
|
|
1050
1235
|
当使用 `source=commercial` 参数时,接口将调用高性能商业API,提供更精确的市、区、运营商、时区、海拔等信息。请注意,商业查询的响应时间可能会稍长。
|
|
1051
1236
|
"""
|
|
@@ -1064,7 +1249,7 @@ class _NetworkApi:
|
|
|
1064
1249
|
|
|
1065
1250
|
def get_network_myip(self, **kwargs):
|
|
1066
1251
|
r"""查询我的 IP
|
|
1067
|
-
想知道你自己的出口公网IP
|
|
1252
|
+
想知道你自己的出口公网IP是多少吗?这个接口就是你的“网络身份证”。你可以使用默认数据源,也可以指定 `source=commercial` 参数来查询更详细的商业级IP归属信息。
|
|
1068
1253
|
|
|
1069
1254
|
## 功能概述
|
|
1070
1255
|
调用此接口,它会返回你(即发起请求的客户端)的公网IP地址,并附带与 `/network/ipinfo` 接口相同的地理位置和网络归属信息。非常适合用于在网页上向用户展示他们自己的IP和地理位置。
|
|
@@ -1141,9 +1326,6 @@ class _NetworkApi:
|
|
|
1141
1326
|
|
|
1142
1327
|
## 功能概述
|
|
1143
1328
|
提供一个URL,我们会向它发起一个请求,并返回其HTTP响应状态码。这是一种简单而有效的服务可用性监控方法。
|
|
1144
|
-
|
|
1145
|
-
> [!TIP]
|
|
1146
|
-
> **性能优化**:为了提高效率并减少对目标服务器的负载,我们实际发送的是 `HEAD` 请求,而不是 `GET` 请求。`HEAD` 请求只会获取响应头,而不会下载整个页面内容,因此速度更快。
|
|
1147
1329
|
"""
|
|
1148
1330
|
params = {}
|
|
1149
1331
|
body = {}
|
|
@@ -1266,30 +1448,28 @@ class _RandomApi:
|
|
|
1266
1448
|
> 如果你需要更精确地控制图片类型,请使用 `/image/random/{category}/{type}` 接口。
|
|
1267
1449
|
|
|
1268
1450
|
### 支持的主类别与子类别
|
|
1269
|
-
- **
|
|
1451
|
+
- **acg**(二次元动漫)
|
|
1452
|
+
- pc
|
|
1453
|
+
- mb
|
|
1454
|
+
- **外部图床精选/混合动漫**
|
|
1455
|
+
- **landscape**: 风景图。
|
|
1456
|
+
- **anime**: 混合了UapiPro服务器的acg和外部图床的general_anime分类下的图片。
|
|
1457
|
+
- **pc_wallpaper**: 电脑壁纸。
|
|
1458
|
+
- **mobile_wallpaper**: 手机壁纸。
|
|
1459
|
+
- **general_anime**: 动漫图。
|
|
1460
|
+
- **ai_drawing**: AI绘画。
|
|
1461
|
+
- **其他分类**
|
|
1462
|
+
- **bq**(表情包/趣图)
|
|
1463
|
+
- eciyuan
|
|
1464
|
+
- ikun
|
|
1465
|
+
- xiongmao
|
|
1466
|
+
- waiguoren
|
|
1467
|
+
- maomao
|
|
1270
1468
|
- **furry**(福瑞)
|
|
1271
1469
|
- z4k
|
|
1272
1470
|
- szs8k
|
|
1273
1471
|
- s4k
|
|
1274
1472
|
- 4k
|
|
1275
|
-
- **bq**(表情包/趣图)
|
|
1276
|
-
- youshou
|
|
1277
|
-
- xiongmao
|
|
1278
|
-
- waiguoren
|
|
1279
|
-
- maomao
|
|
1280
|
-
- ikun
|
|
1281
|
-
- eciyuan
|
|
1282
|
-
- **acg**(二次元动漫)
|
|
1283
|
-
- pc
|
|
1284
|
-
- mb
|
|
1285
|
-
- **外部图床精选图片**
|
|
1286
|
-
- **ai_drawing**: AI绘画。
|
|
1287
|
-
- **general_anime**: 动漫图。
|
|
1288
|
-
- **landscape**: 风景图。
|
|
1289
|
-
- **mobile_wallpaper**: 手机壁纸。
|
|
1290
|
-
- **pc_wallpaper**: 电脑壁纸。
|
|
1291
|
-
- **混合动漫**
|
|
1292
|
-
- **anime**: 混合了UapiPro服务器的acg和外部图床的general_anime分类下的图片。
|
|
1293
1473
|
|
|
1294
1474
|
> [!NOTE]
|
|
1295
1475
|
> 默认全局随机(未指定category参数)时,不会包含ikun和AI绘画(ai_drawing)类别的图片。
|
|
@@ -1479,7 +1659,11 @@ class _SocialApi:
|
|
|
1479
1659
|
通过视频的 `oid`(通常就是视频的`aid`),你可以分页获取该视频的评论区内容。你可以指定排序方式和分页参数,来精确地获取你需要的数据。
|
|
1480
1660
|
|
|
1481
1661
|
## 参数说明
|
|
1482
|
-
- **`sort` (排序方式)
|
|
1662
|
+
- **`sort` (排序方式)**
|
|
1663
|
+
- `0` 或 `time`:按时间排序
|
|
1664
|
+
- `1` 或 `like`:按点赞排序
|
|
1665
|
+
- `2` 或 `reply`:按回复数排序
|
|
1666
|
+
- `3` 或 `hot`(也支持 `hottest`、`最热`):按最热排序
|
|
1483
1667
|
|
|
1484
1668
|
## 响应体字段说明
|
|
1485
1669
|
- **`hots` (热门评论)**: 仅在请求第一页时,可能会返回热门评论列表。其结构与 `replies` 中的对象一致。
|
|
@@ -1551,10 +1735,7 @@ class _SocialApi:
|
|
|
1551
1735
|
|
|
1552
1736
|
def get_social_qq_groupinfo(self, **kwargs):
|
|
1553
1737
|
r"""查询 QQ 群信息
|
|
1554
|
-
想在你的应用里展示QQ
|
|
1555
|
-
|
|
1556
|
-
> [!VIP]
|
|
1557
|
-
> 本API目前处于**限时免费**阶段,我们鼓励开发者集成和测试。未来,它将转为付费API,为用户提供更稳定和强大的服务。
|
|
1738
|
+
想在你的应用里展示QQ群信息?这个接口让你轻松获取群名称、群头像、群简介、成员数量等详细公开信息。
|
|
1558
1739
|
|
|
1559
1740
|
## 功能概述
|
|
1560
1741
|
你只需要提供一个QQ群号(5-12位纯数字),接口就会返回该群的完整公开信息。我们会先验证群号的有效性,确保返回的数据准确可靠。接口响应速度快,数据结构清晰,非常适合集成到各类应用场景中。
|
|
@@ -1594,9 +1775,6 @@ class _SocialApi:
|
|
|
1594
1775
|
r"""查询 QQ 信息
|
|
1595
1776
|
这是一个功能丰富的QQ用户信息查询接口,能够获取QQ用户的详细公开信息。
|
|
1596
1777
|
|
|
1597
|
-
> [!VIP]
|
|
1598
|
-
> 我们在近日优化了此接口,速度应该会更加快了。
|
|
1599
|
-
|
|
1600
1778
|
## 功能概述
|
|
1601
1779
|
通过QQ号查询用户的详细信息,包括基础资料、等级信息、VIP状态等。返回的信息丰富全面,适合用于用户画像分析、社交应用集成等场景。
|
|
1602
1780
|
|
|
@@ -2067,7 +2245,7 @@ class _TranslateApi:
|
|
|
2067
2245
|
|
|
2068
2246
|
def get_ai_translate_languages(self, **kwargs):
|
|
2069
2247
|
r"""AI翻译配置
|
|
2070
|
-
获取AI
|
|
2248
|
+
获取AI智能翻译服务支持的完整语言列表、翻译风格选项、上下文场景选项以及性能指标信息。
|
|
2071
2249
|
"""
|
|
2072
2250
|
params = {}
|
|
2073
2251
|
body = {}
|
|
@@ -2078,21 +2256,18 @@ class _TranslateApi:
|
|
|
2078
2256
|
|
|
2079
2257
|
def post_ai_translate(self, **kwargs):
|
|
2080
2258
|
r"""AI智能翻译
|
|
2081
|
-
这是一个商业级的AI
|
|
2082
|
-
|
|
2083
|
-
> [!VIP]
|
|
2084
|
-
> 本API目前处于**限时免费**阶段,我们鼓励开发者深度集成和测试。未来,它将转为付费API,为用户提供更稳定、更智能的翻译服务。
|
|
2259
|
+
这是一个商业级的AI智能翻译服务,采用最新的神经网络翻译技术和大语言模型,提供远超传统机器翻译的质量。
|
|
2085
2260
|
|
|
2086
2261
|
## 功能概述
|
|
2087
2262
|
|
|
2088
|
-
-
|
|
2263
|
+
- **单文本翻译**: 专注处理单条文本翻译,适合需要高质量译文的业务场景。
|
|
2089
2264
|
- **多风格适配**: 提供随意口语化、专业商务、学术正式、文学艺术四种翻译风格,能够根据不同场景需求调整翻译的语言风格和表达方式。
|
|
2090
2265
|
- **上下文感知**: 支持通用、商务、技术、医疗、法律、市场营销、娱乐、教育、新闻等九种专业领域的上下文翻译,确保术语准确性和表达地道性。
|
|
2091
|
-
- **高质量保证**: 内置质量评估系统,对每次翻译结果进行流畅度、准确度、完整性评分,并提供置信度分数和替代翻译建议。
|
|
2092
|
-
- **智能解释**: 提供关键词组翻译注释、文化背景说明和语法结构分析,帮助用户理解翻译逻辑和文化差异。
|
|
2093
|
-
- **高效批量**: 批量翻译支持最多50条文本,总计10万字符,配备智能并发控制(1-10并发)和失败重试机制。
|
|
2094
|
-
- **快速模式**: 提供快速模式选项,在保证95%+准确率的前提下,响应时间缩短至800ms内,适合实时翻译和聊天应用。
|
|
2095
2266
|
- **格式保留**: 智能识别并保持原文的格式结构,包括换行、缩进、特殊符号等,确保翻译后的文本保持良好的可读性。
|
|
2267
|
+
|
|
2268
|
+
## 支持的语言
|
|
2269
|
+
|
|
2270
|
+
我们支持超过100种语言的互译,详见下方参数列表。
|
|
2096
2271
|
"""
|
|
2097
2272
|
params = {}
|
|
2098
2273
|
body = {}
|
|
@@ -2104,12 +2279,6 @@ class _TranslateApi:
|
|
|
2104
2279
|
if "context" in kwargs:
|
|
2105
2280
|
body["context"] = kwargs["context"]
|
|
2106
2281
|
|
|
2107
|
-
if "fast_mode" in kwargs:
|
|
2108
|
-
body["fast_mode"] = kwargs["fast_mode"]
|
|
2109
|
-
|
|
2110
|
-
if "max_concurrency" in kwargs:
|
|
2111
|
-
body["max_concurrency"] = kwargs["max_concurrency"]
|
|
2112
|
-
|
|
2113
2282
|
if "preserve_format" in kwargs:
|
|
2114
2283
|
body["preserve_format"] = kwargs["preserve_format"]
|
|
2115
2284
|
|
|
@@ -2122,9 +2291,6 @@ class _TranslateApi:
|
|
|
2122
2291
|
if "text" in kwargs:
|
|
2123
2292
|
body["text"] = kwargs["text"]
|
|
2124
2293
|
|
|
2125
|
-
if "texts" in kwargs:
|
|
2126
|
-
body["texts"] = kwargs["texts"]
|
|
2127
|
-
|
|
2128
2294
|
path = "/api/v1/ai/translate"
|
|
2129
2295
|
|
|
2130
2296
|
return self._http.request("POST", path, params=params, json=body if body else None)
|
|
@@ -2200,25 +2366,23 @@ class _WebparseApi:
|
|
|
2200
2366
|
|
|
2201
2367
|
def get_web_tomarkdown_async_status(self, **kwargs):
|
|
2202
2368
|
r"""转换任务状态
|
|
2203
|
-
|
|
2369
|
+
提交了网页转 Markdown 任务后,想知道处理进度和结果?用这个接口来查询。
|
|
2204
2370
|
|
|
2205
2371
|
## 功能概述
|
|
2372
|
+
通过任务 ID 查询转换任务的当前状态、处理进度和最终结果。任务结果缓存 30 分钟,期间可重复查询。
|
|
2206
2373
|
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
任务有五种状态:等待处理(pending)时进度为0%;处理中(processing)时进度在10-90%之间;已完成(completed)时进度为100%并返回Markdown内容;失败(failed)时会返回错误信息;超时(timeout)表示任务处理时间超过60秒已被取消。建议采用指数退避策略进行轮询,初始延迟1秒,每次延迟增加20%,最大延迟5秒。当状态为已完成、失败或超时时停止轮询。
|
|
2210
|
-
|
|
2211
|
-
系统会自动管理任务生命周期,单个任务最长处理时间为60秒,任务结果保存30分钟后自动清理,每5分钟清理一次过期任务。
|
|
2374
|
+
## 任务状态
|
|
2212
2375
|
|
|
2213
|
-
|
|
2376
|
+
| 状态 | 说明 |
|
|
2377
|
+
|------|------|
|
|
2378
|
+
| `pending` | 等待处理 |
|
|
2379
|
+
| `processing` | 处理中 |
|
|
2380
|
+
| `completed` | 已完成,可获取结果 |
|
|
2381
|
+
| `failed` | 失败 |
|
|
2382
|
+
| `timeout` | 超时(超过 60 秒) |
|
|
2214
2383
|
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
| `pending` | 等待处理 | 0% | 立即开始轮询 |
|
|
2218
|
-
| `processing` | 处理中 | 10-90% | 每2-5秒轮询一次 |
|
|
2219
|
-
| `completed` | 已完成 | 100% | 停止轮询,获取结果 |
|
|
2220
|
-
| `failed` | 失败 | 100% | 停止轮询,查看错误信息 |
|
|
2221
|
-
| `timeout` | 超时 | 100% | 停止轮询,任务已取消 |
|
|
2384
|
+
> [!NOTE]
|
|
2385
|
+
> 建议每 2-5 秒轮询一次,当状态为 `completed`、`failed` 或 `timeout` 时停止轮询。
|
|
2222
2386
|
"""
|
|
2223
2387
|
params = {}
|
|
2224
2388
|
body = {}
|
|
@@ -2235,10 +2399,10 @@ class _WebparseApi:
|
|
|
2235
2399
|
|
|
2236
2400
|
def get_webparse_extractimages(self, **kwargs):
|
|
2237
2401
|
r"""提取网页图片
|
|
2238
|
-
|
|
2402
|
+
想批量获取一个网页上的所有图片链接?这个接口帮你搞定。
|
|
2239
2403
|
|
|
2240
2404
|
## 功能概述
|
|
2241
|
-
|
|
2405
|
+
提供一个网页 URL,返回该页面中所有图片的链接列表。适合用于图片采集、素材下载等场景。
|
|
2242
2406
|
"""
|
|
2243
2407
|
params = {}
|
|
2244
2408
|
body = {}
|
|
@@ -2251,11 +2415,11 @@ class _WebparseApi:
|
|
|
2251
2415
|
return self._http.request("GET", path, params=params, json=body if body else None)
|
|
2252
2416
|
|
|
2253
2417
|
def get_webparse_metadata(self, **kwargs):
|
|
2254
|
-
r"""
|
|
2255
|
-
|
|
2418
|
+
r"""提取网页元数据
|
|
2419
|
+
想在应用里做链接预览卡片?这个接口帮你一键获取网页的标题、描述、图标等信息。
|
|
2256
2420
|
|
|
2257
2421
|
## 功能概述
|
|
2258
|
-
|
|
2422
|
+
提供一个网页 URL,返回该页面的元数据,包括标题、描述、关键词、Favicon、Open Graph 信息等。非常适合用于生成链接预览卡片或做 SEO 分析。
|
|
2259
2423
|
"""
|
|
2260
2424
|
params = {}
|
|
2261
2425
|
body = {}
|
|
@@ -2269,20 +2433,13 @@ class _WebparseApi:
|
|
|
2269
2433
|
|
|
2270
2434
|
def post_web_tomarkdown_async(self, **kwargs):
|
|
2271
2435
|
r"""网页转 Markdown
|
|
2272
|
-
|
|
2436
|
+
想把一个网页的内容转成干净的 Markdown 文本?这个异步接口可以帮你搞定,特别适合处理大型或复杂的网页。
|
|
2273
2437
|
|
|
2274
2438
|
## 功能概述
|
|
2275
2439
|
|
|
2276
|
-
|
|
2277
|
-
>本API目前处于**限时免费**阶段,我们鼓励开发者集成和测试。未来,它将转为付费API,为用户提供更稳定和强大的服务。
|
|
2278
|
-
|
|
2279
|
-
UAPI Pro平台推出的异步网页转Markdown API能够将任意网页URL转换为结构清晰、格式优美的Markdown文本。提交任务后立即返回任务ID,不会阻塞客户端等待。您可以通过任务ID实时查询转换进度和处理状态,支持长达60秒的处理时间,轻松应对大型网站、需要JS渲染的单页应用等复杂页面。任务结果会缓存30分钟,期间可重复查询,过期任务自动清理无需手动管理。
|
|
2280
|
-
|
|
2281
|
-
此API采用先进算法,自动识别并抓取网页主体内容,精准剔除广告、导航栏、页眉页脚等无关元素。完美保留原文的格式,包括标题、列表、代码块、表格、引用、图片等,并输出为兼容性强的GitHub Flavored Markdown (GFM) 格式。同时会自动解析并提取文章标题、作者、发布日期、站点名称等关键元数据,并将其格式化为标准的YAML Front Matter,方便后续处理和CMS集成。
|
|
2440
|
+
提交一个网页 URL,我们会自动抓取主体内容,剔除广告、导航栏等干扰元素,并转换为 Markdown 格式。同时会提取标题、作者、发布日期等元数据,生成 YAML Front Matter。
|
|
2282
2441
|
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
调用本接口提交URL转换任务后,会立即获得一个唯一的任务ID。随后使用任务ID调用查询接口,获取任务状态和进度。任务完成后,从查询接口的响应中获取Markdown内容。
|
|
2442
|
+
任务提交后会立即返回任务 ID,你可以用它来查询处理进度和结果。单个任务最长处理 60 秒,结果缓存 30 分钟。
|
|
2286
2443
|
"""
|
|
2287
2444
|
params = {}
|
|
2288
2445
|
body = {}
|
|
@@ -2316,28 +2473,17 @@ class _MinGanCiShiBieApi:
|
|
|
2316
2473
|
|
|
2317
2474
|
def post_sensitive_word_analyze(self, **kwargs):
|
|
2318
2475
|
r"""分析敏感词
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
> [!VIP]
|
|
2322
|
-
> 本API基于先进的分析模型,提供三级缓存策略和并发处理能力。
|
|
2476
|
+
分析单个或多个关键词的敏感程度,返回标准化风险标签与置信度结果。
|
|
2323
2477
|
|
|
2324
2478
|
## 功能概述
|
|
2325
2479
|
|
|
2326
2480
|
- **模型驱动**: 使用先进的分析模型进行语义分析。
|
|
2327
2481
|
- **高性能**: 采用三级缓存策略(持久化存储 → 统一缓存 → 模型分析),确保高频请求的响应速度。
|
|
2328
2482
|
- **并发支持**: 支持批量并发处理,单次最多可分析100个关键词。
|
|
2329
|
-
-
|
|
2330
|
-
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
返回的 `s` 字段包含三个维度的风险评分,范围均为0.0至1.0:
|
|
2335
|
-
|
|
2336
|
-
- **s[0] - 色情风险**: 评估内容涉及色情信息的程度。
|
|
2337
|
-
- **s[1] - 辱骂/仇恨言论风险**: 评估内容是否包含侮辱性或仇恨性言论。
|
|
2338
|
-
- **s[2] - 暴力/威胁风险**: 评估内容是否涉及暴力或威胁信息。
|
|
2339
|
-
|
|
2340
|
-
风险等级可参考:0.0-0.3为低风险,0.3-0.7为中等风险,0.7-1.0为高风险。
|
|
2483
|
+
- **输入限制**: 单条关键词最多 1,000 字符,总字符数最多 20,000。
|
|
2484
|
+
- **标准标签**: 返回 `label` 字段,明确区分 `sensitive` 与 `normal`。
|
|
2485
|
+
- **分类清晰**: 返回 `category` 字段,用于标识具体风险类别。
|
|
2486
|
+
- **置信度输出**: 返回 `confidence` 字段,范围为0.0到1.0。
|
|
2341
2487
|
|
|
2342
2488
|
## 响应字段说明
|
|
2343
2489
|
|
|
@@ -2345,11 +2491,9 @@ class _MinGanCiShiBieApi:
|
|
|
2345
2491
|
|------|------|------|
|
|
2346
2492
|
| `results` | array | 分析结果对象的数组。 |
|
|
2347
2493
|
| `results[].k` | string | 您在请求中提供的原始关键词。 |
|
|
2348
|
-
| `results[].
|
|
2349
|
-
| `results[].
|
|
2350
|
-
| `results[].
|
|
2351
|
-
| `results[].t` | array[string] | 根据分析结果为关键词附加的分类标签,便于进行程序化处理和过滤。 |
|
|
2352
|
-
| `results[].d` | string | 对整体分析结果的一句简短总结,适合直接展示给用户或记录在日志中。 |
|
|
2494
|
+
| `results[].label` | string | 核心判断字段:`sensitive`(敏感)、`normal`(正常)。 |
|
|
2495
|
+
| `results[].category` | string | 风险分类:`safe`(安全)、`threat`(威胁)、`porn`(色情)、`fraud`(欺诈)、`insult`(辱骂)。 |
|
|
2496
|
+
| `results[].confidence` | number | 当前分类的置信度,范围0.0到1.0。 |
|
|
2353
2497
|
| `total` | integer | 本次请求成功分析的关键词总数。 |
|
|
2354
2498
|
|
|
2355
2499
|
"""
|
|
@@ -2433,9 +2577,6 @@ UAPI Pro Search 是一个智能搜索引擎,采用机器学习算法对搜索
|
|
|
2433
2577
|
- **时间范围过滤**: 支持按天/周/月/年过滤结果
|
|
2434
2578
|
- **站内搜索**: 支持 `site:` 操作符,在指定网站内搜索
|
|
2435
2579
|
- **文件类型过滤**: 支持 `filetype:` 操作符,快速找到 PDF、Word 等特定格式文件
|
|
2436
|
-
|
|
2437
|
-
> [!VIP]
|
|
2438
|
-
> 本API目前处于**限时免费**阶段,我们鼓励开发者集成和测试。未来,它将转为付费API,为用户提供更稳定和强大的服务。
|
|
2439
2580
|
|
|
2440
2581
|
"""
|
|
2441
2582
|
params = {}
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from dataclasses import dataclass, field
|
|
3
|
+
from typing import Any, Dict, Mapping, Optional
|
|
4
|
+
import httpx
|
|
5
|
+
|
|
6
|
+
@dataclass
|
|
7
|
+
class RateLimitPolicyEntry:
|
|
8
|
+
name: str
|
|
9
|
+
quota: Optional[int] = None
|
|
10
|
+
unit: Optional[str] = None
|
|
11
|
+
window_seconds: Optional[int] = None
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
class RateLimitStateEntry:
|
|
15
|
+
name: str
|
|
16
|
+
remaining: Optional[int] = None
|
|
17
|
+
unit: Optional[str] = None
|
|
18
|
+
reset_after_seconds: Optional[int] = None
|
|
19
|
+
|
|
20
|
+
@dataclass
|
|
21
|
+
class ResponseMeta:
|
|
22
|
+
request_id: Optional[str] = None
|
|
23
|
+
retry_after_seconds: Optional[int] = None
|
|
24
|
+
debit_status: Optional[str] = None
|
|
25
|
+
credits_requested: Optional[int] = None
|
|
26
|
+
credits_charged: Optional[int] = None
|
|
27
|
+
credits_pricing: Optional[str] = None
|
|
28
|
+
active_quota_buckets: Optional[int] = None
|
|
29
|
+
stop_on_empty: Optional[bool] = None
|
|
30
|
+
rate_limit_policy_raw: Optional[str] = None
|
|
31
|
+
rate_limit_raw: Optional[str] = None
|
|
32
|
+
rate_limit_policies: Dict[str, RateLimitPolicyEntry] = field(default_factory=dict)
|
|
33
|
+
rate_limits: Dict[str, RateLimitStateEntry] = field(default_factory=dict)
|
|
34
|
+
balance_limit_cents: Optional[int] = None
|
|
35
|
+
balance_remaining_cents: Optional[int] = None
|
|
36
|
+
quota_limit_credits: Optional[int] = None
|
|
37
|
+
quota_remaining_credits: Optional[int] = None
|
|
38
|
+
visitor_quota_limit_credits: Optional[int] = None
|
|
39
|
+
visitor_quota_remaining_credits: Optional[int] = None
|
|
40
|
+
raw_headers: Dict[str, str] = field(default_factory=dict)
|
|
41
|
+
|
|
42
|
+
class UapiError(Exception):
|
|
43
|
+
code: str
|
|
44
|
+
status: int
|
|
45
|
+
message: str
|
|
46
|
+
details: Any
|
|
47
|
+
payload: Any
|
|
48
|
+
meta: Optional[ResponseMeta]
|
|
49
|
+
|
|
50
|
+
def __init__(
|
|
51
|
+
self,
|
|
52
|
+
code: str,
|
|
53
|
+
status: int,
|
|
54
|
+
message: str,
|
|
55
|
+
details: Any = None,
|
|
56
|
+
payload: Any = None,
|
|
57
|
+
meta: Optional[ResponseMeta] = None,
|
|
58
|
+
):
|
|
59
|
+
super().__init__(f"[{status}] {code}: {message}")
|
|
60
|
+
self.code = code
|
|
61
|
+
self.status = status
|
|
62
|
+
self.message = message
|
|
63
|
+
self.details = details
|
|
64
|
+
self.payload = payload
|
|
65
|
+
self.meta = meta
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class ApiErrorError(UapiError):
|
|
69
|
+
"""上游/内部错误 (API_ERROR)"""
|
|
70
|
+
DEFAULT_STATUS = 502
|
|
71
|
+
|
|
72
|
+
class AvatarNotFoundError(UapiError):
|
|
73
|
+
"""头像未找到 (AVATAR_NOT_FOUND)"""
|
|
74
|
+
DEFAULT_STATUS = 404
|
|
75
|
+
|
|
76
|
+
class ConversionFailedError(UapiError):
|
|
77
|
+
"""转换失败 (CONVERSION_FAILED)"""
|
|
78
|
+
DEFAULT_STATUS = 400
|
|
79
|
+
|
|
80
|
+
class FileOpenErrorError(UapiError):
|
|
81
|
+
"""文件打开错误 (FILE_OPEN_ERROR)"""
|
|
82
|
+
DEFAULT_STATUS = 500
|
|
83
|
+
|
|
84
|
+
class FileRequiredError(UapiError):
|
|
85
|
+
"""文件必需 (FILE_REQUIRED)"""
|
|
86
|
+
DEFAULT_STATUS = 400
|
|
87
|
+
|
|
88
|
+
class InsufficientCreditsError(UapiError):
|
|
89
|
+
"""账户积分不足 (INSUFFICIENT_CREDITS)"""
|
|
90
|
+
DEFAULT_STATUS = 402
|
|
91
|
+
|
|
92
|
+
class InternalServerErrorError(UapiError):
|
|
93
|
+
"""服务器内部错误 (INTERNAL_SERVER_ERROR)"""
|
|
94
|
+
DEFAULT_STATUS = 500
|
|
95
|
+
|
|
96
|
+
class InvalidParameterError(UapiError):
|
|
97
|
+
"""请求参数错误 (INVALID_PARAMETER)"""
|
|
98
|
+
DEFAULT_STATUS = 400
|
|
99
|
+
|
|
100
|
+
class InvalidParamsError(UapiError):
|
|
101
|
+
"""无效参数 (INVALID_PARAMS)"""
|
|
102
|
+
DEFAULT_STATUS = 400
|
|
103
|
+
|
|
104
|
+
class NotFoundError(UapiError):
|
|
105
|
+
"""资源不存在 (NOT_FOUND)"""
|
|
106
|
+
DEFAULT_STATUS = 404
|
|
107
|
+
|
|
108
|
+
class NoMatchError(UapiError):
|
|
109
|
+
"""无匹配 (NO_MATCH)"""
|
|
110
|
+
DEFAULT_STATUS = 404
|
|
111
|
+
|
|
112
|
+
class NoTrackingDataError(UapiError):
|
|
113
|
+
"""无物流数据 (NO_TRACKING_DATA)"""
|
|
114
|
+
DEFAULT_STATUS = 404
|
|
115
|
+
|
|
116
|
+
class PhoneInfoFailedError(UapiError):
|
|
117
|
+
"""手机号信息查询失败 (PHONE_INFO_FAILED)"""
|
|
118
|
+
DEFAULT_STATUS = 500
|
|
119
|
+
|
|
120
|
+
class RecognitionFailedError(UapiError):
|
|
121
|
+
"""识别失败 (RECOGNITION_FAILED)"""
|
|
122
|
+
DEFAULT_STATUS = 404
|
|
123
|
+
|
|
124
|
+
class RequestEntityTooLargeError(UapiError):
|
|
125
|
+
"""错误 (REQUEST_ENTITY_TOO_LARGE)"""
|
|
126
|
+
DEFAULT_STATUS = 413
|
|
127
|
+
|
|
128
|
+
class ServiceBusyError(UapiError):
|
|
129
|
+
"""请求过于频繁 (SERVICE_BUSY)"""
|
|
130
|
+
DEFAULT_STATUS = 429
|
|
131
|
+
|
|
132
|
+
class TimezoneNotFoundError(UapiError):
|
|
133
|
+
"""时区未找到 (TIMEZONE_NOT_FOUND)"""
|
|
134
|
+
DEFAULT_STATUS = 404
|
|
135
|
+
|
|
136
|
+
class UnauthorizedError(UapiError):
|
|
137
|
+
"""请求未授权 (UNAUTHORIZED)"""
|
|
138
|
+
DEFAULT_STATUS = 401
|
|
139
|
+
|
|
140
|
+
class UnsupportedCarrierError(UapiError):
|
|
141
|
+
"""不支持的承运商 (UNSUPPORTED_CARRIER)"""
|
|
142
|
+
DEFAULT_STATUS = 404
|
|
143
|
+
|
|
144
|
+
class UnsupportedFormatError(UapiError):
|
|
145
|
+
"""格式不支持 (UNSUPPORTED_FORMAT)"""
|
|
146
|
+
DEFAULT_STATUS = 400
|
|
147
|
+
|
|
148
|
+
class VisitorMonthlyQuotaExhaustedError(UapiError):
|
|
149
|
+
"""访客月度免费额度已用尽 (VISITOR_MONTHLY_QUOTA_EXHAUSTED)"""
|
|
150
|
+
DEFAULT_STATUS = 429
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def _default_code(status: int) -> str:
|
|
154
|
+
if status == 400:
|
|
155
|
+
return "INVALID_PARAMETER"
|
|
156
|
+
if status == 401:
|
|
157
|
+
return "UNAUTHORIZED"
|
|
158
|
+
if status == 402:
|
|
159
|
+
return "INSUFFICIENT_CREDITS"
|
|
160
|
+
if status == 404:
|
|
161
|
+
return "NOT_FOUND"
|
|
162
|
+
if status == 413:
|
|
163
|
+
return "REQUEST_ENTITY_TOO_LARGE"
|
|
164
|
+
if status == 429:
|
|
165
|
+
return "SERVICE_BUSY"
|
|
166
|
+
if status >= 500:
|
|
167
|
+
return "INTERNAL_SERVER_ERROR"
|
|
168
|
+
return "API_ERROR"
|
|
169
|
+
|
|
170
|
+
def _parse_int(value: Optional[str]) -> Optional[int]:
|
|
171
|
+
if value is None:
|
|
172
|
+
return None
|
|
173
|
+
try:
|
|
174
|
+
return int(value)
|
|
175
|
+
except (TypeError, ValueError):
|
|
176
|
+
return None
|
|
177
|
+
|
|
178
|
+
def _parse_bool(value: Optional[str]) -> Optional[bool]:
|
|
179
|
+
if value is None:
|
|
180
|
+
return None
|
|
181
|
+
lowered = value.strip().lower()
|
|
182
|
+
if lowered == "true":
|
|
183
|
+
return True
|
|
184
|
+
if lowered == "false":
|
|
185
|
+
return False
|
|
186
|
+
return None
|
|
187
|
+
|
|
188
|
+
def _unquote(value: str) -> str:
|
|
189
|
+
text = value.strip()
|
|
190
|
+
if len(text) >= 2 and text[0] == '"' and text[-1] == '"':
|
|
191
|
+
return text[1:-1]
|
|
192
|
+
return text
|
|
193
|
+
|
|
194
|
+
def _parse_structured_items(raw: Optional[str]) -> list[tuple[str, Dict[str, str]]]:
|
|
195
|
+
if not raw:
|
|
196
|
+
return []
|
|
197
|
+
items: list[tuple[str, Dict[str, str]]] = []
|
|
198
|
+
for chunk in [part.strip() for part in raw.split(",") if part.strip()]:
|
|
199
|
+
segments = [segment.strip() for segment in chunk.split(";") if segment.strip()]
|
|
200
|
+
if not segments:
|
|
201
|
+
continue
|
|
202
|
+
name = _unquote(segments[0])
|
|
203
|
+
params: Dict[str, str] = {}
|
|
204
|
+
for segment in segments[1:]:
|
|
205
|
+
if "=" not in segment:
|
|
206
|
+
continue
|
|
207
|
+
key, value = segment.split("=", 1)
|
|
208
|
+
params[key.strip()] = _unquote(value)
|
|
209
|
+
items.append((name, params))
|
|
210
|
+
return items
|
|
211
|
+
|
|
212
|
+
def extract_meta(headers: Mapping[str, str]) -> ResponseMeta:
|
|
213
|
+
raw_headers = {str(key).lower(): str(value) for key, value in headers.items()}
|
|
214
|
+
rate_limit_policies: Dict[str, RateLimitPolicyEntry] = {}
|
|
215
|
+
rate_limits: Dict[str, RateLimitStateEntry] = {}
|
|
216
|
+
|
|
217
|
+
for name, params in _parse_structured_items(raw_headers.get("ratelimit-policy")):
|
|
218
|
+
rate_limit_policies[name] = RateLimitPolicyEntry(
|
|
219
|
+
name=name,
|
|
220
|
+
quota=_parse_int(params.get("q")),
|
|
221
|
+
unit=params.get("uapi-unit"),
|
|
222
|
+
window_seconds=_parse_int(params.get("w")),
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
for name, params in _parse_structured_items(raw_headers.get("ratelimit")):
|
|
226
|
+
rate_limits[name] = RateLimitStateEntry(
|
|
227
|
+
name=name,
|
|
228
|
+
remaining=_parse_int(params.get("r")),
|
|
229
|
+
unit=params.get("uapi-unit"),
|
|
230
|
+
reset_after_seconds=_parse_int(params.get("t")),
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
return ResponseMeta(
|
|
234
|
+
request_id=raw_headers.get("x-request-id"),
|
|
235
|
+
retry_after_seconds=_parse_int(raw_headers.get("retry-after")),
|
|
236
|
+
debit_status=raw_headers.get("uapi-debit-status"),
|
|
237
|
+
credits_requested=_parse_int(raw_headers.get("uapi-credits-requested")),
|
|
238
|
+
credits_charged=_parse_int(raw_headers.get("uapi-credits-charged")),
|
|
239
|
+
credits_pricing=raw_headers.get("uapi-credits-pricing"),
|
|
240
|
+
active_quota_buckets=_parse_int(raw_headers.get("uapi-quota-active-buckets")),
|
|
241
|
+
stop_on_empty=_parse_bool(raw_headers.get("uapi-stop-on-empty")),
|
|
242
|
+
rate_limit_policy_raw=raw_headers.get("ratelimit-policy"),
|
|
243
|
+
rate_limit_raw=raw_headers.get("ratelimit"),
|
|
244
|
+
rate_limit_policies=rate_limit_policies,
|
|
245
|
+
rate_limits=rate_limits,
|
|
246
|
+
balance_limit_cents=rate_limit_policies.get("billing-balance").quota if "billing-balance" in rate_limit_policies else None,
|
|
247
|
+
balance_remaining_cents=rate_limits.get("billing-balance").remaining if "billing-balance" in rate_limits else None,
|
|
248
|
+
quota_limit_credits=rate_limit_policies.get("billing-quota").quota if "billing-quota" in rate_limit_policies else None,
|
|
249
|
+
quota_remaining_credits=rate_limits.get("billing-quota").remaining if "billing-quota" in rate_limits else None,
|
|
250
|
+
visitor_quota_limit_credits=rate_limit_policies.get("visitor-quota").quota if "visitor-quota" in rate_limit_policies else None,
|
|
251
|
+
visitor_quota_remaining_credits=rate_limits.get("visitor-quota").remaining if "visitor-quota" in rate_limits else None,
|
|
252
|
+
raw_headers=raw_headers,
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
def _pick_details(data: Any) -> Any:
|
|
256
|
+
if not isinstance(data, dict):
|
|
257
|
+
return None
|
|
258
|
+
if "details" in data:
|
|
259
|
+
return data["details"]
|
|
260
|
+
if "quota" in data:
|
|
261
|
+
return data["quota"]
|
|
262
|
+
if "docs" in data:
|
|
263
|
+
return data["docs"]
|
|
264
|
+
return None
|
|
265
|
+
|
|
266
|
+
def map_error(r: httpx.Response) -> UapiError:
|
|
267
|
+
code = None
|
|
268
|
+
msg = r.text
|
|
269
|
+
data: Any = None
|
|
270
|
+
try:
|
|
271
|
+
data = r.json()
|
|
272
|
+
code = data.get("code") or data.get("error") or data.get("errCode") or _default_code(r.status_code)
|
|
273
|
+
msg = data.get("message") or data.get("errMsg") or msg
|
|
274
|
+
except Exception:
|
|
275
|
+
code = _default_code(r.status_code)
|
|
276
|
+
status = r.status_code
|
|
277
|
+
meta = extract_meta(r.headers)
|
|
278
|
+
cls = _class_by_code(code, status)
|
|
279
|
+
return cls(code, status, msg, _pick_details(data), data, meta)
|
|
280
|
+
|
|
281
|
+
def _class_by_code(code: str, status: int):
|
|
282
|
+
c = (code or "").upper()
|
|
283
|
+
mapping = {
|
|
284
|
+
|
|
285
|
+
"API_ERROR": ApiErrorError,
|
|
286
|
+
|
|
287
|
+
"AVATAR_NOT_FOUND": AvatarNotFoundError,
|
|
288
|
+
|
|
289
|
+
"CONVERSION_FAILED": ConversionFailedError,
|
|
290
|
+
|
|
291
|
+
"FILE_OPEN_ERROR": FileOpenErrorError,
|
|
292
|
+
|
|
293
|
+
"FILE_REQUIRED": FileRequiredError,
|
|
294
|
+
|
|
295
|
+
"INSUFFICIENT_CREDITS": InsufficientCreditsError,
|
|
296
|
+
|
|
297
|
+
"INTERNAL_SERVER_ERROR": InternalServerErrorError,
|
|
298
|
+
|
|
299
|
+
"INVALID_PARAMETER": InvalidParameterError,
|
|
300
|
+
|
|
301
|
+
"INVALID_PARAMS": InvalidParamsError,
|
|
302
|
+
|
|
303
|
+
"NOT_FOUND": NotFoundError,
|
|
304
|
+
|
|
305
|
+
"NO_MATCH": NoMatchError,
|
|
306
|
+
|
|
307
|
+
"NO_TRACKING_DATA": NoTrackingDataError,
|
|
308
|
+
|
|
309
|
+
"PHONE_INFO_FAILED": PhoneInfoFailedError,
|
|
310
|
+
|
|
311
|
+
"RECOGNITION_FAILED": RecognitionFailedError,
|
|
312
|
+
|
|
313
|
+
"REQUEST_ENTITY_TOO_LARGE": RequestEntityTooLargeError,
|
|
314
|
+
|
|
315
|
+
"SERVICE_BUSY": ServiceBusyError,
|
|
316
|
+
|
|
317
|
+
"TIMEZONE_NOT_FOUND": TimezoneNotFoundError,
|
|
318
|
+
|
|
319
|
+
"UNAUTHORIZED": UnauthorizedError,
|
|
320
|
+
|
|
321
|
+
"UNSUPPORTED_CARRIER": UnsupportedCarrierError,
|
|
322
|
+
|
|
323
|
+
"UNSUPPORTED_FORMAT": UnsupportedFormatError,
|
|
324
|
+
|
|
325
|
+
"VISITOR_MONTHLY_QUOTA_EXHAUSTED": VisitorMonthlyQuotaExhaustedError,
|
|
326
|
+
|
|
327
|
+
}
|
|
328
|
+
return mapping.get(c) or ({
|
|
329
|
+
400: InvalidParameterError,
|
|
330
|
+
401: UnauthorizedError,
|
|
331
|
+
402: InsufficientCreditsError,
|
|
332
|
+
404: NotFoundError,
|
|
333
|
+
429: ServiceBusyError,
|
|
334
|
+
500: InternalServerErrorError,
|
|
335
|
+
}.get(status) or UapiError)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: uapi-sdk-python
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.13
|
|
4
4
|
Summary: Idiomatic UAPI SDK for Python
|
|
5
5
|
Author-email: UAPI <dev@uapis.cn>
|
|
6
6
|
Requires-Python: >=3.9
|
|
@@ -14,7 +14,7 @@ Requires-Dist: isort; extra == "dev"
|
|
|
14
14
|
|
|
15
15
|
# uapi-sdk-python
|
|
16
16
|
|
|
17
|
-

|
|
18
18
|
|
|
19
19
|
[](https://www.python.org/)
|
|
20
20
|
[](https://uapis.cn/)
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
from typing import Any, Dict, Optional
|
|
3
|
-
import httpx
|
|
4
|
-
|
|
5
|
-
class UapiError(Exception):
|
|
6
|
-
code: str
|
|
7
|
-
status: int
|
|
8
|
-
message: str
|
|
9
|
-
details: Optional[Dict[str, Any]]
|
|
10
|
-
|
|
11
|
-
def __init__(self, code: str, status: int, message: str, details: Optional[Dict[str, Any]] = None):
|
|
12
|
-
super().__init__(f"[{status}] {code}: {message}")
|
|
13
|
-
self.code = code
|
|
14
|
-
self.status = status
|
|
15
|
-
self.message = message
|
|
16
|
-
self.details = details
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class ApiErrorError(UapiError):
|
|
20
|
-
"""上游/内部错误 (API_ERROR)"""
|
|
21
|
-
DEFAULT_STATUS = 502
|
|
22
|
-
|
|
23
|
-
class AvatarNotFoundError(UapiError):
|
|
24
|
-
"""头像未找到 (AVATAR_NOT_FOUND)"""
|
|
25
|
-
DEFAULT_STATUS = 404
|
|
26
|
-
|
|
27
|
-
class ConversionFailedError(UapiError):
|
|
28
|
-
"""转换失败 (CONVERSION_FAILED)"""
|
|
29
|
-
DEFAULT_STATUS = 400
|
|
30
|
-
|
|
31
|
-
class FileOpenErrorError(UapiError):
|
|
32
|
-
"""文件打开错误 (FILE_OPEN_ERROR)"""
|
|
33
|
-
DEFAULT_STATUS = 500
|
|
34
|
-
|
|
35
|
-
class FileRequiredError(UapiError):
|
|
36
|
-
"""文件必需 (FILE_REQUIRED)"""
|
|
37
|
-
DEFAULT_STATUS = 400
|
|
38
|
-
|
|
39
|
-
class InternalServerErrorError(UapiError):
|
|
40
|
-
"""服务器内部错误 (INTERNAL_SERVER_ERROR)"""
|
|
41
|
-
DEFAULT_STATUS = 500
|
|
42
|
-
|
|
43
|
-
class InvalidParameterError(UapiError):
|
|
44
|
-
"""请求参数错误 (INVALID_PARAMETER)"""
|
|
45
|
-
DEFAULT_STATUS = 400
|
|
46
|
-
|
|
47
|
-
class InvalidParamsError(UapiError):
|
|
48
|
-
"""无效参数 (INVALID_PARAMS)"""
|
|
49
|
-
DEFAULT_STATUS = 400
|
|
50
|
-
|
|
51
|
-
class NotFoundError(UapiError):
|
|
52
|
-
"""资源不存在 (NOT_FOUND)"""
|
|
53
|
-
DEFAULT_STATUS = 404
|
|
54
|
-
|
|
55
|
-
class NoMatchError(UapiError):
|
|
56
|
-
"""无匹配 (NO_MATCH)"""
|
|
57
|
-
DEFAULT_STATUS = 404
|
|
58
|
-
|
|
59
|
-
class NoTrackingDataError(UapiError):
|
|
60
|
-
"""无物流数据 (NO_TRACKING_DATA)"""
|
|
61
|
-
DEFAULT_STATUS = 404
|
|
62
|
-
|
|
63
|
-
class PhoneInfoFailedError(UapiError):
|
|
64
|
-
"""手机号信息查询失败 (PHONE_INFO_FAILED)"""
|
|
65
|
-
DEFAULT_STATUS = 500
|
|
66
|
-
|
|
67
|
-
class RecognitionFailedError(UapiError):
|
|
68
|
-
"""识别失败 (RECOGNITION_FAILED)"""
|
|
69
|
-
DEFAULT_STATUS = 404
|
|
70
|
-
|
|
71
|
-
class RequestEntityTooLargeError(UapiError):
|
|
72
|
-
"""错误 (REQUEST_ENTITY_TOO_LARGE)"""
|
|
73
|
-
DEFAULT_STATUS = 413
|
|
74
|
-
|
|
75
|
-
class ServiceBusyError(UapiError):
|
|
76
|
-
"""请求过于频繁 (SERVICE_BUSY)"""
|
|
77
|
-
DEFAULT_STATUS = 429
|
|
78
|
-
|
|
79
|
-
class TimezoneNotFoundError(UapiError):
|
|
80
|
-
"""时区未找到 (TIMEZONE_NOT_FOUND)"""
|
|
81
|
-
DEFAULT_STATUS = 404
|
|
82
|
-
|
|
83
|
-
class UnauthorizedError(UapiError):
|
|
84
|
-
"""请求未授权 (UNAUTHORIZED)"""
|
|
85
|
-
DEFAULT_STATUS = 401
|
|
86
|
-
|
|
87
|
-
class UnsupportedCarrierError(UapiError):
|
|
88
|
-
"""不支持的承运商 (UNSUPPORTED_CARRIER)"""
|
|
89
|
-
DEFAULT_STATUS = 404
|
|
90
|
-
|
|
91
|
-
class UnsupportedFormatError(UapiError):
|
|
92
|
-
"""格式不支持 (UNSUPPORTED_FORMAT)"""
|
|
93
|
-
DEFAULT_STATUS = 400
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
def map_error(r: httpx.Response) -> UapiError:
|
|
97
|
-
code = None
|
|
98
|
-
msg = r.text
|
|
99
|
-
try:
|
|
100
|
-
data = r.json()
|
|
101
|
-
code = data.get("code") or data.get("error") or data.get("errCode") or "API_ERROR"
|
|
102
|
-
msg = data.get("message") or data.get("errMsg") or msg
|
|
103
|
-
details = data.get("details")
|
|
104
|
-
except Exception:
|
|
105
|
-
details = None
|
|
106
|
-
status = r.status_code
|
|
107
|
-
cls = _class_by_code(code, status)
|
|
108
|
-
return cls(code, status, msg, details)
|
|
109
|
-
|
|
110
|
-
def _class_by_code(code: str, status: int):
|
|
111
|
-
c = (code or "").upper()
|
|
112
|
-
mapping = {
|
|
113
|
-
|
|
114
|
-
"API_ERROR": ApiErrorError,
|
|
115
|
-
|
|
116
|
-
"AVATAR_NOT_FOUND": AvatarNotFoundError,
|
|
117
|
-
|
|
118
|
-
"CONVERSION_FAILED": ConversionFailedError,
|
|
119
|
-
|
|
120
|
-
"FILE_OPEN_ERROR": FileOpenErrorError,
|
|
121
|
-
|
|
122
|
-
"FILE_REQUIRED": FileRequiredError,
|
|
123
|
-
|
|
124
|
-
"INTERNAL_SERVER_ERROR": InternalServerErrorError,
|
|
125
|
-
|
|
126
|
-
"INVALID_PARAMETER": InvalidParameterError,
|
|
127
|
-
|
|
128
|
-
"INVALID_PARAMS": InvalidParamsError,
|
|
129
|
-
|
|
130
|
-
"NOT_FOUND": NotFoundError,
|
|
131
|
-
|
|
132
|
-
"NO_MATCH": NoMatchError,
|
|
133
|
-
|
|
134
|
-
"NO_TRACKING_DATA": NoTrackingDataError,
|
|
135
|
-
|
|
136
|
-
"PHONE_INFO_FAILED": PhoneInfoFailedError,
|
|
137
|
-
|
|
138
|
-
"RECOGNITION_FAILED": RecognitionFailedError,
|
|
139
|
-
|
|
140
|
-
"REQUEST_ENTITY_TOO_LARGE": RequestEntityTooLargeError,
|
|
141
|
-
|
|
142
|
-
"SERVICE_BUSY": ServiceBusyError,
|
|
143
|
-
|
|
144
|
-
"TIMEZONE_NOT_FOUND": TimezoneNotFoundError,
|
|
145
|
-
|
|
146
|
-
"UNAUTHORIZED": UnauthorizedError,
|
|
147
|
-
|
|
148
|
-
"UNSUPPORTED_CARRIER": UnsupportedCarrierError,
|
|
149
|
-
|
|
150
|
-
"UNSUPPORTED_FORMAT": UnsupportedFormatError,
|
|
151
|
-
|
|
152
|
-
}
|
|
153
|
-
return mapping.get(c) or ( {400: InvalidParameterError, 401: UnauthorizedError, 404: NotFoundError, 429: ServiceBusyError, 500: InternalServerErrorError}.get(status) or UapiError )
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{uapi_sdk_python-0.1.5 → uapi_sdk_python-0.1.13}/uapi_sdk_python.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|