"""抖音直播间页面临时解析主播昵称(仅供控制台展示,可能随页面改版失效)。""" from __future__ import annotations import re import urllib.error import urllib.request from typing import Any _UA = ( "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " "(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" ) def _norm_douyin_live_url(url: str) -> str: u = (url or "").strip() if not u: return "" u = u.split("#")[0].strip() if u.startswith("http://"): u = "https://" + u[7:] if not u.startswith("https://"): u = "https://" + u return u def _room_id_from_url(url: str) -> str: m = re.search(r"live\.douyin\.com/([a-zA-Z0-9_-]+)", url, re.I) return m.group(1) if m else "" def fetch_douyin_anchor_name(url: str) -> dict[str, Any]: u = _norm_douyin_live_url(url) if not re.search(r"douyin\.com", u, re.I): return {"ok": False, "error": "非抖音链接", "url": url, "room_id": "", "anchor_name": ""} rid = _room_id_from_url(u) if not rid: return {"ok": False, "error": "无法解析房间号", "url": url, "room_id": "", "anchor_name": ""} try: req = urllib.request.Request(u, headers={"User-Agent": _UA, "Accept": "text/html,*/*"}) with urllib.request.urlopen(req, timeout=12) as resp: html = resp.read().decode("utf-8", errors="ignore") except urllib.error.HTTPError as e: return {"ok": False, "error": f"HTTP {e.code}", "url": u, "room_id": rid, "anchor_name": ""} except Exception as e: return {"ok": False, "error": str(e), "url": u, "room_id": rid, "anchor_name": ""} name = "" for pat in ( r'"nickname"\s*:\s*"([^"\\]+)"', r'"nickName"\s*:\s*"([^"\\]+)"', r'"owner"\s*:\s*\{[^}]*"nickname"\s*:\s*"([^"\\]+)"', ): m = re.search(pat, html) if m: name = m.group(1).strip() break if not name: m2 = re.search(r"主播[::]\s*([^\s<\"]{1,40})", html) if m2: name = m2.group(1).strip() return { "ok": True, "url": u, "room_id": rid, "anchor_name": name or "", "error": "" if name else "未解析到昵称", }