import json, urllib.request, urllib.error BASE = "https://job.youthome.com.cn/api/v1" def req(method, path, token=None, body=None): url = BASE + path data = json.dumps(body).encode() if body is not None else None r = urllib.request.Request(url, data=data, method=method) r.add_header("Content-Type", "application/json") if token: r.add_header("Authorization", "Bearer " + token) try: with urllib.request.urlopen(r, timeout=20) as resp: raw = resp.read().decode() status = resp.status except urllib.error.HTTPError as e: raw = e.read().decode(errors="replace") status = e.code except Exception as e: return None, str(e), None try: j = json.loads(raw) except Exception: return status, raw[:200], None return status, j, raw # 1) login s, j, _ = req("POST", "/auth/password/login", body={"phone": "19900009021", "password": "ZhilaiTest!2026#A"}) token = (j or {}).get("data", {}).get("accessToken") if j else None print("LOGIN:", s, "hasToken=", bool(token), "role=", (j or {}).get("data", {}).get("role"), "expiresIn=", (j or {}).get("data", {}).get("en")) print("="*100) # 2) validate ID-less GET endpoints (student token) idless = [ ("GET", "/jobs", "fetchJobList(ALIGNED)"), ("GET", "/offers/compare", "fetchOfferCompareData(ALIGNED)"), ("GET", "/profile/me", "fetchUserProfile(ALIGNED)"), ("GET", "/conversations", "fetchConversations(WRONG->REAL /conversations)"), ("GET", "/notifications", "fetchNotifications(WRONG->REAL /notifications)"), ("GET", "/notifications/unread-count", "bonus real"), ("GET", "/interviews/me", "fetchInterviews(WRONG->REAL /interviews/me)"), ("GET", "/jobs/favorites", "fetchFavorites(WRONG->REAL /jobs/favorites)"), ("GET", "/profile/me/career-progress", "fetchJobProgress(WRONG->REAL /profile/me/career-progress)"), ("GET", "/profile/me/preferences", "fetchJobPreference(WRONG->REAL /profile/me/preferences)"), ("GET", "/profile/me/resume", "fetchResume(WRONG->REAL /profile/me/resume)"), ("GET", "/profile/me/candidate-scoring", "bonus real"), ("GET", "/applications/me", "bonus real /applications/me"), ("GET", "/assessments/me", "bonus real /assessments/me"), ("GET", "/abilities/me", "bonus real /abilities/me"), ] for m, p, label in idless: s, j, _ = req(m, p, token) code = (j or {}).get("code") if isinstance(j, dict) else None data = (j or {}).get("data") dtype = type(data).__name__ keys = list(data.keys())[:12] if isinstance(data, dict) else (f"len={len(data)}" if isinstance(data, list) else None) print(f"{m:4} {p:42} [{label}]") print(f" http={s} code={code} data_type={dtype} sample={keys}") print("="*100) # 3) ID-needing endpoints: best-effort with placeholder id (status ambiguous if 404) idneed = [ ("GET", "/jobs/1", "fetchJobDetail(ALIGNED) needs jobId"), ("GET", "/jobs/1/reviews", "fetchEmployeeReviews(ALIGNED)"), ("GET", "/jobs/1/competition-ranking", "fetchRankData(WRONG->REAL)"), ("GET", "/jobs/1/match", "fetchMatchResult alt"), ("GET", "/conversations/1", "fetchConversation(WRONG->REAL /conversations/{id})"), ("GET", "/applications/1/match", "fetchMatchResult(WRONG->REAL)"), ("GET", "/company/candidates/1", "fetchCandidateDetail(WRONG->REAL, ENTERPRISE role)"), ("GET", "/interviews/1/score", "fetchInterviewScore(WRONG->REAL)"), ] for m, p, label in idneed: s, j, _ = req(m, p, token) code = (j or {}).get("code") if isinstance(j, dict) else None msg = (j or {}).get("message") if isinstance(j, dict) else None print(f"{m:4} {p:42} [{label}] http={s} code={code} msg={msg}")