1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| async def enable_runtime(ws, session_id): """启用 Runtime 域""" return await cdp(ws, session_id, "Runtime.enable")
async def capture_exceptions(ws, session_id, duration=10): """捕获 JavaScript 运行时异常""" await enable_runtime(ws, session_id) exceptions = [] start = asyncio.get_event_loop().time() while (asyncio.get_event_loop().time() - start) < duration: try: msg = await asyncio.wait_for(ws.__anext__(), timeout=1) data = json.loads(msg) method = data.get("method", "") if method == "Runtime.exceptionThrown": exc = data["params"]["exceptionDetails"] exceptions.append({ "text": exc.get("text", ""), "url": exc.get("url", ""), "line": exc.get("lineNumber", 0), "column": exc.get("columnNumber", 0), "stack_trace": exc.get("stackTrace", {}), "exception": exc.get("exception", {}), }) print(f"[异常] {exc.get('text', '')}") elif method == "Runtime.consoleAPICalled": api_data = data["params"] args = [a.get("value", str(a.get("description", ""))) for a in api_data.get("args", [])] exceptions.append({ "type": "console_api", "level": api_data.get("type", ""), "text": " ".join(str(a) for a in args), "timestamp": api_data.get("timestamp", 0), "stack_trace": api_data.get("stackTrace", {}), }) except asyncio.TimeoutError: continue return exceptions
def format_exception(exc): """格式化异常信息""" text = exc.get("text", exc.get("text", "")) url = exc.get("url", "") line = exc.get("line", 0) stack = exc.get("stack_trace", {}) frames = stack.get("callFrames", []) result = f"[{exc.get('type', 'exception').upper()}] {text}\n" result += f" 位置: {url}:{line}\n" for frame in frames[:5]: result += f" at {frame.get('functionName', '(anonymous)')} " result += f"({frame.get('url', '')}:{frame.get('lineNumber', 0)})\n" return result
|