文件内容
sub-skills/semantic-search-news/scripts/handler.py
#!/usr/bin/env python3
"""语义搜索新闻(market.ft.tech)"""
import argparse
import json
import sys
import urllib.error
import urllib.parse
import urllib.request
from datetime import datetime, timedelta, timezone
SAFE_URLOPENER = urllib.request.build_opener()
BASE_URL = "https://market.ft.tech"
BEIJING_TZ = timezone(timedelta(hours=8))
def _normalize_to_beijing_iso(value: str) -> str:
"""
将输入时间规范为东八区 ISO 8601 字符串。
- 无时区:按东八区解释
- 有时区:统一转换到东八区
"""
raw = value.strip()
if not raw:
return raw
# 兼容 Z 结尾
if raw.endswith("Z"):
raw = raw[:-1] + "+00:00"
dt = datetime.fromisoformat(raw)
if dt.tzinfo is None:
dt = dt.replace(tzinfo=BEIJING_TZ)
else:
dt = dt.astimezone(BEIJING_TZ)
return dt.isoformat()
def main():
parser = argparse.ArgumentParser(description="语义搜索新闻")
parser.add_argument(
"--query",
required=True,
help="搜索文字,如:人工智能",
)
parser.add_argument(
"--limit",
type=int,
default=10,
help="返回条数,默认 10",
)
parser.add_argument(
"--year",
type=int,
default=None,
help="年份,仅支持当年,用于限定搜索范围;不传则由服务端决定",
)
parser.add_argument(
"--start_time",
default=None,
help="开始时间(含),ISO 8601,如 2026-03-01T00:00:00+08:00",
)
parser.add_argument(
"--end_time",
default=None,
help="结束时间(含),ISO 8601,如 2026-03-15T23:59:59+08:00",
)
args = parser.parse_args()
params = {"query": args.query, "limit": args.limit}
if args.year is not None:
params["year"] = args.year
try:
if args.start_time:
params["start_time"] = _normalize_to_beijing_iso(args.start_time)
if args.end_time:
params["end_time"] = _normalize_to_beijing_iso(args.end_time)
except ValueError as e:
print(f"时间格式错误:{e}", file=sys.stderr)
sys.exit(1)
url = BASE_URL + "/data/api/v1/market/data/semantic-search-news?" + urllib.parse.urlencode(params)
req = urllib.request.Request(url, method="GET")
try:
with SAFE_URLOPENER.open(req) as resp:
data = json.loads(resp.read().decode())
print(json.dumps(data, ensure_ascii=False, indent=2))
except urllib.error.HTTPError as e:
body = e.read().decode()
print(f"HTTP {e.code}: {body}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()