You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何提取PHP游戏网站动态HTML中的地雷位置?

获取PHP地雷游戏实时地雷位置并模拟点击

问题背景

  • 目标为PHP开发的地雷游戏,页面HTML随用户操作动态更新
  • 点击方块触发POST请求,地雷位置仅在提现或踩中地雷时才会显示
  • 需要在点击方块前实时获取地雷位置的tile id,并模拟安全方块点击
  • 代码需适配游戏胜负后HTML结构变化的情况
  • 此前使用requests编写的代码无效,核心原因是无法处理动态渲染的HTML(仅能处理静态网络请求)

无效的requests尝试代码

import requests
import time

def configure_game_params():
    game_params = {
        "access-token": "39fa080b862e50c48c11a5a5f5a8034f53e1f7d76fb9fa5c4675fed1f1f482450c",
        "fp-userSeed": "SnuPVeYLOWKNACMDK12dyoEIooUuXm4iCLSwDprUta3FuRtHST74O3HRrz4qA0J7",
        "gameAccess": "true",
        "isClientSeedSet": "false",  # Set to "true" or "false" as needed
        "user-email": "njongomagagula@gmail.com",
        "mines_bet": "0.00074249",  # Replace with your actual value
        "color-scheme": "dark",
        "selectedCurrency": "DGB",
    }
    return game_params

def construct_request_headers():
    headers = {
        "Content-Type": "application/json",
        "Accept": "application/json",
        "Authorization": "Bearer ae1ece19d806d9e6630429bac2cfb2f4a406b6ddc0a37af0856635880cb73d7e",
    }
    return headers

def make_api_request(url, payload, headers, retries=3):
    for _ in range(retries):
        try:
            response = requests.post(url, json=payload, headers=headers)
            if response.status_code == 200:
                return response
            elif response.status_code == 429:
                print("Rate limit exceeded. Retrying after backoff.")
                time.sleep(2 ** _)
            else:
                print(f"Error: {response.status_code} - {response.text}")
        except requests.RequestException as e:
            print(f"Error: {e}")
    return None

# Configure game parameters
game_params = configure_game_params()

# Construct the request headers
headers = construct_request_headers()

# Mock the "busted" status in the request payload
request_payload = {
    "status": "BUSTED",
    **game_params,
}

# Make the API request with retries and backoff
response = make_api_request("https://api.faucetpay.io/mines/sweep", request_payload, headers)

# Handle response
if response:
    mine_locations = response.json().get("data", {}).get("mine_locations")
    if mine_locations:
        print("Mine locations:", mine_locations)
    else:
        print("No mine locations found.")
else:
    print("Failed to retrieve mine locations.")

解决方案:使用动态浏览器自动化工具

由于页面依赖JavaScript动态渲染内容,requests这类HTTP库无法执行JS,必须使用能模拟真实浏览器行为的工具(如Selenium、Playwright),它们可以加载完整页面、执行JS并获取动态更新的DOM内容。

基于Selenium的实现示例

安装依赖

pip install selenium webdriver-manager

代码实现

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time

# 初始化Chrome浏览器,规避反爬检测
options = webdriver.ChromeOptions()
# 可选:启用无头模式(不显示浏览器窗口)
# options.add_argument("--headless=new")
options.add_argument("--disable-blink-features=AutomationControlled")
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)

driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)

# 加载游戏页面并设置会话Cookie(从浏览器开发者工具复制真实Cookie)
driver.get("https://你的游戏页面URL")  # 替换为实际游戏地址

# 添加会话必要Cookie
cookies = [
    {"name": "access-token", "value": "39fa080b862e50c48c11a5a5f5a8034f53e1f7d76fb9fa5c4675fed1f1f482450c"},
    {"name": "fp-userSeed", "value": "SnuPVeYLOWKNACMDK12dyoEIooUuXm4iCLSwDprUta3FuRtHST74O3HRrz4qA0J7"},
    # 补充其他从浏览器复制的必要Cookie
]
for cookie in cookies:
    driver.add_cookie(cookie)

# 刷新页面以应用Cookie
driver.refresh()

def get_mine_locations():
    """从动态DOM或全局JS变量中提取地雷位置的tile id"""
    try:
        # 尝试从隐藏DOM元素获取(示例:带data-mine属性的元素)
        mine_tiles = WebDriverWait(driver, 10).until(
            EC.presence_of_all_elements_located((By.CSS_SELECTOR, "[data-mine='true']"))
        )
        return [tile.get_attribute("id") for tile in mine_tiles]
    except:
        # 若隐藏元素不可用,尝试读取全局JS变量(需替换为游戏实际变量名)
        return driver.execute_script("return window.mineLocations;")

def click_safe_tiles(mine_ids):
    """点击所有非地雷的方块,中途检测游戏是否结束"""
    all_tiles = WebDriverWait(driver, 10).until(
        EC.presence_of_all_elements_located((By.CSS_SELECTOR, ".game-tile"))  # 替换为实际tile选择器
    )
    for tile in all_tiles:
        tile_id = tile.get_attribute("id")
        if tile_id not in mine_ids:
            try:
                tile.click()
                time.sleep(0.2)  # 控制点击速度,避免触发反爬
                if check_game_end():
                    break
            except:
                continue

def check_game_end():
    """检测游戏是否因胜负结束"""
    try:
        # 替换为实际胜负提示元素的选择器
        WebDriverWait(driver, 3).until(
            EC.presence_of_element_located((By.CSS_SELECTOR, ".game-over, .game-success"))
        )
        return True
    except:
        return False

def reset_game():
    """游戏结束后重置,开始新一局"""
    try:
        # 替换为实际重置按钮的选择器
        reset_btn = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable((By.CSS_SELECTOR, ".btn-reset-game"))
        )
        reset_btn.click()
        # 等待新一局界面加载完成
        WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.CSS_SELECTOR, ".game-tile"))
        )
    except:
        # 重置按钮不可用时,刷新页面
        driver.refresh()

# 主循环:持续进行游戏
while True:
    # 等待游戏界面加载完成
    WebDriverWait(driver, 15).until(
        EC.presence_of_element_located((By.CSS_SELECTOR, ".game-tile"))
    )
    # 获取地雷位置
    mine_ids = get_mine_locations()
    if not mine_ids:
        print("未获取到地雷位置,2秒后重试...")
        time.sleep(2)
        continue
    print(f"已获取地雷位置:{mine_ids}")
    # 点击安全方块
    click_safe_tiles(mine_ids)
    # 游戏结束则重置
    if check_game_end():
        print("游戏结束,正在重置...")
        reset_game()
        time.sleep(3)

关键注意事项

  • 元素选择器替换:使用浏览器开发者工具(F12)查看游戏页面的tile、胜负提示、重置按钮的实际CSS选择器或XPath,替换代码中的占位符
  • 全局JS变量提取:多数游戏会将地雷位置等关键数据存储在全局JS变量中,可在浏览器控制台输入window查看变量名,替换代码中的window.mineLocations
  • 反爬规避:代码中已添加禁用自动化检测的配置,若仍被识别,可尝试添加随机等待时间、模拟人类点击轨迹
  • 会话保持:确保Cookie与浏览器中的一致,否则无法维持登录状态进入游戏

为什么之前的requests代码无效

游戏的地雷位置大概率是在客户端通过JavaScript生成或渲染的,并不会提前通过API接口返回;或者接口需要特定的游戏状态(如正在进行中)才会返回数据,模拟"BUSTED"状态的请求不符合服务器的校验逻辑,因此无法获取有效数据。

内容的提问来源于stack exchange,提问作者Njongo Magagula

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 02:07:42