Files
xiaoli-cli/operit_py/zhipu_search.py
T
shuiyu1123 dc77dfd304 feat: 将 47 个 Operit TypeScript 脚本全面翻译为 Python
- 新增 operit_runtime.py: 跨平台 Python 运行时
  - 实现 Tools.System/Files/Net/UI/Memory/FFmpeg/Workflow/Chat/SoftwareSettings/Tasker
  - 实现 OkHttp 链式 HTTP 客户端兼容层
  - 实现 complete()/exports/console 全局对象
  - 实现 OperitScriptLoader 脚本加载器
  - 支持 Windows/macOS/Linux 三平台

- 新增 operit_py/ 目录: 47 个 Python 翻译脚本
  - 搜索类: duckduckgo, google_search, tavily, zhipu_search, various_search, crossref
  - 绘图类: openai_draw, qwen_draw, xai_draw, minimax_draw, siliconflow_draw, zhipu_draw, nanobanana_draw
  - 媒体类: ffmpeg, file_converter, douyin_download, bilibili_tools, jmcomic
  - 文件类: extended_file_tools, hex_editor, reader, beeimg_image_uploader
  - 网络类: extended_http_tools, network_test
  - 自动化类: browser, automatic_ui_base, automatic_ui_subagent, automatic_bilibili_assistant, automatic_xiaohongshu_assistant, automatic_baidu_map_assistant
  - 系统类: system_tools, super_admin, daily_life, operit_editor
  - 对话类: ai_chat, extended_chat, qq_intelligent
  - 工作流类: workflow, vflow_trigger, tasker
  - 工具类: time, code_runner, quick_start, extended_memory_tools, baidu_map, 12306, pdf_vision_parser

- 测试结果: 47/47 语法检查通过, 38 脚本加载成功, 280 个工具注册
- Android 专属功能已降级处理(保留接口,返回不支持提示)
2026-06-23 12:27:18 +00:00

193 lines
5.8 KiB
Python

# METADATA
# {
# "name": "zhipu_search",
# "display_name": {
# "zh": "智谱搜索",
# "en": "Zhipu Search"
# },
# "description": {
# "zh": "智谱 AI 独立网络搜索 API,返回结构化搜索结果。",
# "en": "Zhipu AI standalone web search API with structured results."
# },
# "author": "浮生一梦",
# "env": [
# {
# "name": "ZHIPU_SEARCH_API_KEY",
# "description": {
# "zh": "智谱搜索专用 API Key(与生图 Key 独立)",
# "en": "Zhipu Search API Key (independent from draw Key)"
# },
# "required": false
# }
# ],
# "category": "Search",
# "tools": [
# {
# "name": "search",
# "description": {
# "zh": "使用智谱 Web Search API 进行搜索",
# "en": "Search using Zhipu Web Search API"
# },
# "parameters": [
# { "name": "query", "description": { "zh": "搜索关键词", "en": "Search query" }, "type": "string", "required": true },
# { "name": "api_key", "description": { "zh": "智谱 API Key(可选,不传则读取环境变量)", "en": "Zhipu API Key" }, "type": "string", "required": false },
# { "name": "engine", "description": { "zh": "搜索引擎:search_std/search_pro/search_pro_sogou/search_pro_quark", "en": "Search engine" }, "type": "string", "required": false },
# { "name": "count", "description": { "zh": "返回结果数 (1-50),默认 10", "en": "Result count (1-50)" }, "type": "number", "required": false },
# { "name": "recency", "description": { "zh": "时间范围:oneDay/oneWeek/oneMonth/oneYear/noLimit", "en": "Time range" }, "type": "string", "required": false },
# { "name": "content_size", "description": { "zh": "内容长度:medium/high", "en": "Content size" }, "type": "string", "required": false }
# ]
# },
# {
# "name": "test",
# "description": {
# "zh": "测试 API 连接",
# "en": "Test API connection"
# },
# "parameters": []
# }
# ]
# }
import json
import time
import traceback
API_URL = "https://open.bigmodel.cn/api/paas/v4/web_search"
TIMEOUT = 60000
client = OkHttp.newBuilder()
client = client.connectTimeout(TIMEOUT)
client = client.readTimeout(TIMEOUT)
client = client.writeTimeout(TIMEOUT)
client = client.build()
def getApiKey(providedKey=None):
if providedKey:
return providedKey
key = getEnv("ZHIPU_SEARCH_API_KEY")
if key:
return key
key = getEnv("DEFAULT_API_KEY")
return key or ""
async def httpPost(body, apiKey=None):
key = getApiKey(apiKey)
if not key:
raise Exception("未设置 API Key,请配置 ZHIPU_SEARCH_API_KEY 环境变量或在调用时传入 api_key 参数")
request = client.newRequest()
request = request.url(API_URL)
request = request.method("POST")
request = request.header("Authorization", "Bearer " + key)
request = request.header("Content-Type", "application/json")
request = request.body(json.dumps(body), "json")
response = await request.build().execute()
content = response.content
if not response.isSuccessful():
raise Exception("HTTP " + str(response.statusCode) + ": " + content)
return json.loads(content)
async def search(params):
body = {
"search_query": params["query"],
"search_engine": params.get("engine") or "search_std",
"search_intent": True,
"count": params.get("count") or 10,
"content_size": params.get("content_size") or "medium"
}
if params.get("recency"):
body["search_recency_filter"] = params["recency"]
result = await httpPost(body, params.get("api_key"))
results = []
if result.get("search_result") and isinstance(result["search_result"], list):
results = [
{
"title": item.get("title"),
"content": item.get("content"),
"link": item.get("link"),
"media": item.get("media"),
"icon": item.get("icon"),
"publish_date": item.get("publish_date"),
"refer": item.get("refer")
}
for item in result["search_result"]
]
intent = None
if result.get("search_intent") and len(result["search_intent"]) > 0:
intent = result["search_intent"][0] or None
return {
"success": True,
"query": params["query"],
"id": result.get("id"),
"intent": intent,
"results": results,
"count": len(results)
}
async def test():
body = {
"search_query": "hi",
"search_engine": "search_std",
"search_intent": False,
"count": 1
}
start = time.time() * 1000
result = await httpPost(body, None)
latency = time.time() * 1000 - start
return {
"success": True,
"latency": latency,
"id": result.get("id")
}
async def searchWrapper(params):
try:
result = await search(params)
complete({
"success": True,
"message": "搜索完成,找到 " + str(result["count"]) + " 条结果",
"data": result
})
except Exception as error:
msg = str(getattr(error, "message", error))
complete({
"success": False,
"message": "搜索失败:" + msg,
"error_stack": traceback.format_exc()
})
async def testWrapper():
try:
result = await test()
complete({
"success": True,
"message": "连接成功,延迟 " + str(result["latency"]) + "ms",
"data": result
})
except Exception as error:
msg = str(getattr(error, "message", error))
complete({
"success": False,
"message": "测试失败:" + msg,
"error_stack": traceback.format_exc()
})
exports.search = searchWrapper
exports.test = testWrapper