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

Python Selenium无法点击iframe内Canvas中的Play按钮

问题:Selenium无法点击iframe内Canvas中的Play按钮

在使用Python Selenium时,无法点击iframe内canvas.rendererView中的“Play”按钮。检查页面元素时,找不到与该按钮关联的明确DOM元素,只有当鼠标悬停在目标按钮上时,canvas的style属性会从cursor: inherit变为cursor: pointer。尝试切换iframe后通过偏移量点击的代码,但没有成功。

页面HTML代码

<iframe id="frameTest" class="trudyiframe" src="/trudydaily/game.phtml?id=1YHiRMqN9D7rpkR0iyA9FDJrdDhEc%2Bbj2v7hhLa%2FlpI%3D&amp;slt=1&amp;ver=2020" name="frameTest" frameborder="0" marginwidth="0" marginheight="0" scrolling="auto" onload="" allowtransparency="true">
    <html><head>
            <title>Slots</title>
            <style>
                body {
                    padding: 0;
                }
                .rendererView {
                    margin: auto;
                    display: block;
                    width: 100%; 
                    height: auto; 

                }
                #closeButton{
                    position:absolute;
                    top:0;
                    right:0;
                    width:30;
                    height:30;
                    display: none;
 
                }

                @media screen and (max-width:576px) {
                    div#trudyContainer iframe,
                    div#tempcontent iframe{
                        height: 230px;
                    }
                }
            </style>
            <script src="/trudydaily/js/lib/pixi.js"></script>

            <script> var slt_check_trudy = 1; </script>

            <script src="/trudydaily/js/game.js?v=20200806"></script>
            <script src="https://images.neopets.com/js/jquery-1.7.1.min.js" type="text/javascript"></script>

<script>
$( document ).ready(function() {
            
            // Note moved into ready
            var ajaxurl = '/trudydaily/ajax/claimprize.php';
            var data = {
                'action': 'getslotstate','key': '1YHiRMqN9D7rpkR0iyA9FDJrdDhEc%2Bbj2v7hhLa%2FlpI%3D'};
            var resp;
            parent.$.post(ajaxurl, data, function (response) {
                resp = JSON.parse(response);
                if(resp.error == "") {
                    SlotsGame.LoadAssets(AssetLoadComplete, "https://images.neopets.com");
                } else {
                    parent.CloseSlotsGame(); // @todo restore this 2020?
                }
            });

            // 2020 H5 version: pass config object so we can switch context in game.js based on slt value. Original classic version included 3 different nearly duplicated .js files
            trudy_config = { "html5": "1",  "slt_check_trudy": "1"};
            SlotsGame.Initialize(trudy_config);

            function AssetLoadComplete(){
                SlotsGame.Start(resp);
            }

            function CloseGame(){
                parent.CloseSlotsGame(); //@todo restore this 2020
            };
});
</script>
    <link href="chrome-extension://nffaoalbilbmmfgbnbgppjihopabppdk/inject.css" type="text/css" rel="stylesheet"></head>
                <body marginwidth="0" marginheight="0" class="vsc-initialized"><a href="#" onclick="parent.CloseSlotsGame();">
            <img src="https://images.neopets.com/dailyslots/closebtn.png" id="closeButton">
        </a>
        
<canvas width="800" height="600" class="rendererView" style="cursor: inherit;"></canvas></body></html>
</iframe>

测试代码

from selenium import webdriver
from selenium.webdriver.support.select import Select
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
import time
driver.get('https://www.neopets.com/trudys_surprise.phtml')
time.sleep(4)
iframeElement = driver.find_element(By.ID, "frameTest")
driver.switch_to.frame("frameTest")
time.sleep(2)
action = webdriver.common.action_chains.ActionChains(driver)
action.move_to_element_with_offset(iframeElement, 527, 672).click()
time.sleep(30)
driver.switch_to.default_content()

解决方案

你的代码核心问题有两个:一是偏移量的参考元素错误,二是没有等待游戏资源完全加载导致点击时机不对。以下是修正后的方案:

修正后的代码

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver.get('https://www.neopets.com/trudys_surprise.phtml')

# 等待iframe加载完成并切换进去,替代固定sleep
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.ID, "frameTest")))

# 等待canvas元素出现,并等待游戏加载完成(通过cursor状态判断按钮可点击)
canvas = WebDriverWait(driver, 15).until(EC.presence_of_element_located((By.CLASS_NAME, "rendererView")))
WebDriverWait(driver, 15).until(lambda d: canvas.value_of_css_property("cursor") == "pointer")

# 以canvas为基准,点击Play按钮的相对偏移位置(需根据实际位置调整数值)
action = ActionChains(driver)
# 示例偏移量,你需要自己确认Play按钮在canvas内的准确坐标
action.move_to_element_with_offset(canvas, 400, 500).click().perform()

driver.switch_to.default_content()

关键修正点

  • 偏移参考元素修正:切换到iframe后,应该以内部的canvas元素作为偏移基准,而不是主页面中的iframe元素——move_to_element_with_offset的偏移量是相对于目标元素左上角的,之前用iframe会导致坐标计算错误。
  • 等待机制优化:用WebDriverWait替代固定time.sleep,确保iframe和canvas加载完成,并且通过监控cursor属性确认Play按钮已经处于可交互状态,避免过早点击。
  • 准确偏移量:你需要自己确认Play按钮在canvas内的准确坐标,可以通过浏览器开发者工具的元素定位功能,查看鼠标悬停在按钮上时的相对位置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 14:34:53