Files
2026-07-22 09:51:31 +08:00

133 lines
4.2 KiB
Python
Executable File

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
教务同步只读 API 联调脚本(Python 3.7+,仅标准库)
调用两个业务接口并打印成功结果:
- GET /api/v1/students 学生基本信息(第 1 页)
- GET /api/v1/student-changes 学生异动(按年)
用法:
python test_jw_cx_api.py --prod
python test_jw_cx_api.py --base-url http://web.hzdyjsxy.cn:18081/jw-cx-api --year 2026
环境变量:JW_CX_BASE_URL、JW_CX_API_KEY
"""
from __future__ import print_function
import argparse
import json
import os
import sys
import time
import urllib.error
import urllib.parse
import urllib.request
HEADER_API_KEY = "X-Jw-Cx-Key"
DEFAULT_BASE_URL = "http://127.0.0.1:5050"
PROD_BASE_URL = "http://web.hzdyjsxy.cn:18081"
DEFAULT_API_KEY = "JWCX001"
def _get_json(url, api_key, timeout=120):
req = urllib.request.Request(url, method="GET")
req.add_header(HEADER_API_KEY, api_key)
with urllib.request.urlopen(req, timeout=timeout) as resp:
body = resp.read().decode("utf-8")
return resp.status, json.loads(body)
def _join_url(base, path):
return base.rstrip("/") + "/" + path.lstrip("/")
def fetch_students(base_url, api_key, page=1, page_size=10):
qs = urllib.parse.urlencode({"page": page, "page_size": page_size})
url = _join_url(base_url, "/api/v1/students?" + qs)
status, data = _get_json(url, api_key)
if status != 200 or data.get("code") != 200:
raise RuntimeError("学生基本信息接口失败: status=%s body=%s" % (status, data))
return data
def fetch_student_changes(base_url, api_key, year):
qs = urllib.parse.urlencode({"year": year})
url = _join_url(base_url, "/api/v1/student-changes?" + qs)
status, data = _get_json(url, api_key)
if status != 200 or data.get("code") != 200:
raise RuntimeError("学生异动接口失败: status=%s body=%s" % (status, data))
return data
def main():
parser = argparse.ArgumentParser(description="教务同步 API:获取学生信息与学生异动")
parser.add_argument("--base-url", default=None, help="API 根地址")
parser.add_argument("--prod", action="store_true", help="使用 %s" % PROD_BASE_URL)
parser.add_argument(
"--api-key",
default=os.environ.get("JW_CX_API_KEY", DEFAULT_API_KEY),
help="请求头 %s" % HEADER_API_KEY,
)
parser.add_argument(
"--year",
type=int,
default=None,
help="异动筛选年份,默认当前自然年",
)
parser.add_argument(
"--page-size",
type=int,
default=10,
help="学生基本信息每页条数,默认 10",
)
args = parser.parse_args()
if args.base_url:
base_url = args.base_url
elif args.prod:
base_url = PROD_BASE_URL
else:
base_url = os.environ.get("JW_CX_BASE_URL", DEFAULT_BASE_URL)
year = args.year if args.year is not None else time.localtime().tm_year
print("BASE_URL: %s" % base_url)
print("")
try:
students = fetch_students(base_url, args.api_key, page=1, page_size=args.page_size)
print("=== 学生基本信息 GET /api/v1/students ===")
print(
"total=%s page=%s/%s 本页=%s条"
% (
students.get("total"),
students.get("page"),
students.get("total_pages"),
len(students.get("data") or []),
)
)
if students.get("data"):
print("首条:", json.dumps(students["data"][0], ensure_ascii=False, indent=2))
print("")
changes = fetch_student_changes(base_url, args.api_key, year)
print("=== 学生异动 GET /api/v1/student-changes?year=%s ===" % year)
print("total=%s filter_year=%s" % (changes.get("total"), changes.get("filter_year")))
if changes.get("data"):
print("首条:", json.dumps(changes["data"][0], ensure_ascii=False, indent=2))
elif changes.get("total") == 0:
print("(当年无异动记录)")
except (urllib.error.URLError, urllib.error.HTTPError, RuntimeError, ValueError) as e:
print("调用失败: %s" % e, file=sys.stderr)
sys.exit(1)
print("")
print("调用成功")
sys.exit(0)
if __name__ == "__main__":
main()