Umutkgz/worldguessr-cheat

GitHub: Umutkgz/worldguessr-cheat

利用Playwright自动化提取WorldGuessr地理位置信息。

Stars: 5 | Forks: 1

``` ██╗ ██╗ ██████╗ ██████╗ ██╗ ██████╗ ██████╗ ██╗ ██╗███████╗███████╗███████╗██████╗ ██║ ██║██╔═══██╗██╔══██╗██║ ██╔══██╗██╔════╝ ██║ ██║██╔════╝██╔════╝██╔════╝██╔══██╗ ██║ █╗ ██║██║ ██║██████╔╝██║ ██║ ██║██║ ███╗██║ ██║█████╗ ███████╗███████╗██████╔╝ ██║███╗██║██║ ██║██╔══██╗██║ ██║ ██║██║ ██║██║ ██║██╔══╝ ╚════██║╚════██║██╔══██╗ ╚███╔███╔╝╚██████╔╝██║ ██║███████╗██████╔╝╚██████╔╝╚██████╔╝███████╗███████║███████║██║ ██║ ╚══╝╚══╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝╚══════╝╚══════╝╚═╝ ╚═╝ H U N T E R ``` **WorldGuessr 的自动地理位置提取与地图注入工具** [![Python](https://img.shields.io/badge/Python-3.10%2B-3776AB?style=flat-square&logo=python&logoColor=white)](https://www.python.org/) [![Playwright](https://img.shields.io/badge/Playwright-1.40%2B-2EAD33?style=flat-square&logo=playwright&logoColor=white)](https://playwright.dev/python/) [![License](https://img.shields.io/badge/License-MIT-yellow?style=flat-square)](LICENSE) [![Platform](https://img.shields.io/badge/Platform-Linux%20%7C%20macOS%20%7C%20Windows-lightgrey?style=flat-square)]() *实时拦截 Google Street View 元数据 · 提取 GPS 坐标 · 自动点击正确的地图位置*
## 工作原理 WorldGuessr 在加载每一轮时,会调用 Google 内部的 `GetMetadata` 端点,该端点会在用户与地图交互之前返回 Street View 位置的精确 GPS 坐标。此工具会拦截该响应,从嵌套的 JSON 中解析出坐标,并在 Leaflet 地图上的精确位置触发一个合成的点击事件。 ``` Browser opens worldguessr.com │ ▼ Playwright listens to every HTTP response │ ▼ (filters for GetMetadata only) Google API response arrives ──▶ strip XSSI prefix ──▶ parse JSON │ ▼ (recursive tree search) Coordinates extracted: lat, lng, country, address │ ▼ Injected JS fires map.fire('click', { latlng: L.latLng(lat, lng) }) │ ▼ Game registers correct guess ✓ ``` 无需屏幕抓取。无需像素计算。无需 OCR。游戏直接把答案交给了我们。 ## 功能 - **零延迟提取** — 坐标在网络层被捕获,甚至在 Street View 完全加载之前 - **与 Schema 无关的解析** — 采用递归模式匹配,而非硬编码的 JSON 路径;能够从容应对 Google API 格式变化 - **感知 XSSI** — 在解析前正确剔除 Google 的 `)]}'\n` 防滥用前缀 - **与像素无关的点击** — 直接使用 `L.LatLng`,因此缩放级别和平移状态无关紧要 - **预加载 JS Hooking** — 在任何页面脚本运行之前,通过 `Object.defineProperty` setter 陷阱捕获 Leaflet 的地图对象 - **双重 Hook 策略** — 同时使用 `addInitHook` 和重写 `prototype.initialize`,以实现跨版本 Leaflet 兼容 - **去重** — 防止在同一位置的重复 API 调用中触发多次点击 - **抗 Bot 检测启动** — 屏蔽 `navigator.webdriver` 特征,设置真实的 User-Agent ## 环境要求 - Python **3.10** 或更高版本 - 正常工作的显示环境(Linux 上的 X11,或 macOS/Windows 上的标准桌面) ## 安装说明 ### 1. 克隆仓库 ``` git clone https://github.com/Umutkgz/worldguessr-cheat/ cd worldguessr-hunter ``` ### 2. 创建虚拟环境(推荐) ``` python -m venv venv # Linux / macOS source venv/bin/activate # Windows venv\Scripts\activate ``` ### 3. 安装 Python 依赖 ``` pip install -r requirements.txt ``` `requirements.txt`: ``` playwright>=1.40.0 ``` ### 4. 安装 Playwright 的 Chromium 浏览器 ``` playwright install chromium ``` ### 5.(仅限 Linux)安装系统依赖 ``` playwright install-deps chromium ``` ## 使用方法 ``` python hunter.py ``` 将会打开一个 Chromium 窗口并导航至 `https://worldguessr.com`。正常开始游戏即可 —— 脚本会在后台静默运行,并在每一轮加载时自动点击地图上的正确位置。 **如需停止:**关闭浏览器窗口,或在终端中按 `Ctrl+C`。 ### 终端中的输出信息 ``` ╔════════════════════════════════ ══════════╗ ║ WorldGuessr Hunter ║ ╚════════════════════════════════ ══════════╝ To stop: Ctrl+C ═══════════════════ ═════════════════════════════════ 📍 LOCATION DETECTED ════════════════════════════ ════════════════════════ Coordinates: 41.015137, 28.979530 Country: TR Address: Sultanahmet, Istanbul ═══════════════════════════ ═════════════════════════ ✅ Clicked! ``` ## 在 Headless 服务器上运行 (Linux) 如果你在没有物理显示器的服务器上运行此程序,你需要一个虚拟帧缓冲区 (virtual framebuffer): ``` # 安装 Xvfb sudo apt-get install xvfb # 启动虚拟显示器 Xvfb :1 -screen 0 1280x800x24 & # 设置 DISPLAY 并运行 DISPLAY=:1 python hunter.py ``` 脚本会通过 `os.environ.setdefault` 自动将 `DISPLAY=:1` 设置为后备值,但你仍需事先运行 Xvfb。 ## 项目结构 ``` worldguessr-hunter/ ├── hunter.py # Main script ├── requirements.txt # Python dependencies ├── README.md └── LICENSE ``` ### `hunter.py` 中的核心组件 | 组件 | 描述 | |-----------|-------------| | `extract_json()` | 在解析 JSON 之前,剔除 API 响应中 Google 的 XSSI 前缀 (`)]}'`) | | `find_coords()` | 递归搜索嵌套的 JSON,查找 `[None, None, lat, lng]` 坐标签名 | | `find_country()` | 递归查找 ISO 3166-1 alpha-2 国家代码(2 个字符的大写字符串) | | `find_addresses()` | 收集响应树中找到的所有 `[address_string, locale_code]` 键值对 | | `INIT_SCRIPT` | 在页面加载前注入的 JavaScript;通过陷阱拦截 `window.L` 赋值,以 hook Leaflet 的地图构造函数 | | `CLICK_JS` | JavaScript 模板,用于在 Leaflet 地图上的指定坐标处触发合成的 `click` 事件 | | `inject_click()` | Python 包装器,使用真实坐标格式化 `CLICK_JS` 并通过 `page.evaluate()` 执行 | | `on_response()` | Playwright 响应事件处理器;统筹整个提取与点击的 pipeline | | `main()` | 使用防 Bot 检测标志启动浏览器,注册 hook,并导航至游戏页面 | ## 技术说明 ### 为什么对 Leaflet 使用 `Object.defineProperty`? Leaflet 将其实例存储在模块局部变量中,无法从 `window` 访问。脚本没有使用 `setInterval` 进行轮询,而是在 `window.L` 上安装了一个属性陷阱,这样当 Leaflet 加载并将其自身分配给全局对象的那一刻,我们就能同步拦截它,并在任何页面代码运行之前 hook 进 `L.Map.prototype`。 ### 为什么使用两种 hook 方法? `addInitHook` 是 Leaflet 官方的插件 API;重写 `prototype.initialize` 是一种更底层的后备方案。不同的 Leaflet 构建版本在次要版本之间可能会有不同的行为。同时使用这两种方法可以确保至少有一个能够触发。 ### 为什么使用 `L.LatLng` 而不是像素坐标? 将 GPS 坐标转换为屏幕像素需要知道当前的地图缩放级别和中心点,而这两者随时都可能发生变化。直接向 `map.fire('click', ...)` 提供 `latlng` 彻底绕过了这个问题;Leaflet 的事件系统向处理器传递的是地理坐标,而不是像素位置。 ### 为什么要剔除 `)]}'\n`? Google 在内部 API 的 JSON 响应前加上这段字符串,以防止 [XSSI 攻击](https://owasp.org/www-project-web-security-testing-guide/v41/4-Web_Application_Security_Testing/11-Client_Side_Testing/13-Testing_for_Cross_Site_Script_Inclusion)。浏览器的 `fetch()` 调用会接收到完整文本,并在解析前将其剔除。我们在这里手动复现了这一步骤。 ## 故障排除 **浏览器打开了但没有反应** `GetMetadata` 的 URL 匹配模式可能已经改变。打开浏览器的开发者工具 (DevTools) → Network 标签页,开始一局游戏,并查找对 `maps.googleapis.com` 的请求。如有必要,请更新 `on_response()` 中的 URL 过滤字符串。 **终端中出现 `NO_MAP`** Leaflet hook 未能及时捕获地图对象。这可能是因为游戏的地图在 `add_init_script` 运行之前就已经初始化了 —— 这种情况不太可能发生,但在极快的网络连接下是有可能的。尝试在 `page.goto()` 之前添加一个简短的 `await asyncio.sleep(0.5)`。 **`ModuleNotFoundError: playwright`** 请确保在运行脚本之前激活了你的虚拟环境: ``` source venv/bin/activate # Linux/macOS venv\Scripts\activate # Windows ``` **`Error: browserType.launch: Executable doesn't exist`** 再次运行 `playwright install chromium`。可能是浏览器二进制文件未能正确下载。 **在 Linux 上:`error while loading shared libraries`** 运行 `playwright install-deps chromium` 来安装缺失的系统库。 ## 免责声明 本项目仅供教育和研究目的使用 —— 专门用于演示浏览器自动化、网络拦截和 JavaScript runtime hooking 技术。请负责任地使用。在在线多人游戏中运行自动化脚本可能会违反这些游戏的服务条款。 ## 许可证 MIT — 详情请参阅 [LICENSE](LICENSE)。
使用 [Playwright](https://playwright.dev/python/) 构建 · 好奇心驱动
标签:Playwright, Python, 地理定位, 无后门, 游戏外挂, 网络调试, 自动化