cdp_click_start.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. """Dump ALL children of ready_start (full list) and click the actual 启动 part."""
  2. import asyncio
  3. import json
  4. import sys
  5. import httpx
  6. import websockets
  7. async def main():
  8. async with httpx.AsyncClient(timeout=5) as c:
  9. r = await c.get("http://127.0.0.1:9222/json/list")
  10. det = next((t for t in r.json() if "gameDetail" in t.get("url", "")), None)
  11. if not det:
  12. print("no gameDetail")
  13. return 1
  14. async with websockets.connect(det["webSocketDebuggerUrl"], max_size=10**7) as ws:
  15. mid = 0
  16. async def ev(expr):
  17. nonlocal mid
  18. mid += 1
  19. await ws.send(json.dumps({"id": mid, "method": "Runtime.evaluate",
  20. "params": {"expression": expr, "returnByValue": True}}))
  21. while True:
  22. m = json.loads(await ws.recv())
  23. if m.get("id") == mid:
  24. return m.get("result", {}).get("result", {}).get("value")
  25. async def click(x, y):
  26. nonlocal mid
  27. mid += 1
  28. await ws.send(json.dumps({"id": mid, "method": "Input.dispatchMouseEvent",
  29. "params": {"type": "mousePressed", "x": x, "y": y, "button": "left", "clickCount": 1, "buttons": 1}}))
  30. await asyncio.sleep(0.07)
  31. mid += 1
  32. await ws.send(json.dumps({"id": mid, "method": "Input.dispatchMouseEvent",
  33. "params": {"type": "mouseReleased", "x": x, "y": y, "button": "left", "clickCount": 1, "buttons": 0}}))
  34. while True:
  35. m = json.loads(await ws.recv())
  36. if m.get("id") == mid:
  37. return
  38. info = await ev("""
  39. (function() {
  40. const btn = document.querySelector('.ready_start');
  41. if (!btn) return JSON.stringify([]);
  42. const kids = [];
  43. btn.querySelectorAll('*').forEach(k => {
  44. const kr = k.getBoundingClientRect();
  45. if (kr.width > 20 && kr.height > 8) {
  46. kids.push({cls: (k.className || '').toString().slice(0, 32),
  47. text: (k.innerText || '').trim().slice(0, 15),
  48. x: Math.round(kr.x + kr.width/2), y: Math.round(kr.y + kr.height/2)});
  49. }
  50. });
  51. return JSON.stringify(kids);
  52. })()
  53. """)
  54. kids = json.loads(info or "[]")
  55. print("=== ready_start ALL children ===")
  56. for k in kids:
  57. print(f" '{k['text']}' cls={k['cls']} @({k['x']},{k['y']})")
  58. # pick the element whose class/text looks like the actual start button
  59. target = None
  60. for k in kids:
  61. cls = k["cls"].lower()
  62. if "start" in cls or "btn" in cls or "launch" in cls or "go" in cls:
  63. if "select" not in cls and "mode" not in cls:
  64. target = k
  65. break
  66. if not target:
  67. # bottom-most child (the button is usually below the selector rows)
  68. if kids:
  69. target = max(kids, key=lambda k: k["y"])
  70. if not target:
  71. print("no target found")
  72. return 1
  73. print(f"\nTARGET: '{target['text']}' cls={target['cls']} @({target['x']},{target['y']})")
  74. print("clicking...")
  75. await click(target["x"], target["y"])
  76. await asyncio.sleep(4)
  77. # what happened?
  78. url = await ev("location.href")
  79. print(f"url: {url[:80]}")
  80. modal = await ev("""
  81. (function() {
  82. const m = document.querySelector('.ant-modal, [class*=modal], [class*=dialog], [class*=downloader]');
  83. return m ? (m.innerText || '').slice(0, 100) : null;
  84. })()
  85. """)
  86. print(f"modal/dialog: {modal}")
  87. return 0
  88. sys.exit(asyncio.run(main()))