如何在更长的时间内“发送密钥”到画布元素?

Sab*_* 錆兎 6 python selenium canvas selenium-webdriver keyboard-python

我的目标:

我正在尝试制作一个 python 机器人来赢得chrome 的恐龙游戏

游戏允许两种类型的跳跃:

  • 短距离跳跃
  • 跳远

使用main_body.send_keys(Keys.SPACE)(如下面的代码所示)给出了短跳转。

我的问题:

我很难执行跳远。

我的做法:

目前,对于跳远,我正在使用该Keyboard库:

keyboard.press(keyboard.KEY_UP)

不幸的是,这要求浏览器窗口始终处于焦点。稍后,我希望无头地运行这个程序,所以这种方法行不通。

或者:

我试过ActionChains

ActionChains(driver) \
.key_down(Keys.SPACE) \
.pause(0.2) \
.key_up(Keys.SPACE) \
.perform()
Run Code Online (Sandbox Code Playgroud)

但这最终会滚动整个页面。并且没有达到预期的目的。

我只是希望直接将这些操作“发送”到画布元素,而不是在整个页面上执行它们...

我希望做这样的事情

main_body.key_down(Keys.SPACE) 
time.sleep(0.2)
main_body.key_up(Keys.SPACE) 
Run Code Online (Sandbox Code Playgroud)

虽然这当然会给我这个错误:AttributeError: 'FirefoxWebElement' object has no attribute 'key_down'因为canvas没有属性key_downkey_up.

这是一个 MCVE:

注意在代码中,恐龙会不断跳跃,但这不是重点,这只是为了检查跳跃的高度而不是赢得比赛。

main_body.key_down(Keys.SPACE) 
time.sleep(0.2)
main_body.key_up(Keys.SPACE) 
Run Code Online (Sandbox Code Playgroud)

请给别人注释掉代码,看看每种跳转的效果。

如果可能的话,建议一些其他的替代方法,在不使用Keyboard和不滚动整个页面的情况下进行跳远......

Mat*_*ati 4

不幸的是,我在该游戏中看不到跳跃的可重现行为。当我按向上或空格键时,我会随机看到短跳或长跳,因此我无法确定我的方法是否适合您。

然而,我认为,只需付出一点努力,您就可以创建一个适合您需求的活动。基本上,由于 Selenium 可以执行任意 javascript,因此我的方法是将 keydown 事件发送到 canvas 元素(使用 Firefox 77 进行测试)。

为每次迭代制作屏幕截图,以确保恐龙确实跳跃。

玩得开心。

from selenium.webdriver.firefox.options import Options as FirefoxOptions
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time

options = FirefoxOptions()
options.add_argument("--headless")
driver = webdriver.Firefox(options=options)
driver.get('https://chromedino.com/')

canvas = driver.find_element_by_css_selector('.runner-canvas')
main_body = driver.find_element_by_xpath("//html")

try:
    canvas.click()
except:
    main_body.send_keys(Keys.SPACE)

while True:
    driver.execute_script('''
    var keydownEvt = new KeyboardEvent('keydown', {
        altKey:false,
        altKey: false,
        bubbles: true,
        cancelBubble: false,
        cancelable: true,
        charCode: 0,
        code: "Space",
        composed: true,
        ctrlKey: false,
        currentTarget: null,
        defaultPrevented: true,
        detail: 0,
        eventPhase: 0,
        isComposing: false,
        isTrusted: true,
        key: " ",
        keyCode: 32,
        location: 0,
        metaKey: false,
        repeat: false,
        returnValue: false,
        shiftKey: false,
        type: "keydown",
        which: 32,
    });
    arguments[0].dispatchEvent(keydownEvt);
    ''', canvas)
    driver.get_screenshot_as_file('proof_%s.png' % int(time.time()))
    time.sleep(0.2)

driver.quit()
Run Code Online (Sandbox Code Playgroud)

  • 为了获得有效的事件,我只是将 keydown 事件添加到 Firefox 控制台中的随机元素,然后附加一个转储该事件的函数。重复的“altKey”无疑是复制粘贴的垃圾。也许您不需要该事件的每个属性,您可以自己尝试并检查您想要使用的目标浏览器。 (2认同)