首页 > 解决方案 > 如何将密钥“发送”到画布元素更长的时间?

问题描述

我的目标:

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

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

使用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()

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

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

我想做这样的事情

main_body.key_down(Keys.SPACE) 
time.sleep(0.2)
main_body.key_up(Keys.SPACE) 

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

这是一个 MCVE:

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

import keyboard
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains

driver = webdriver.Firefox()
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:
    #short jump
    main_body.send_keys(Keys.SPACE)

    #long jump
    ActionChains(driver) \
    .key_down(Keys.SPACE) \
    .pause(0.2) \
    .key_up(Keys.SPACE) \
    .perform()

    #long jump using keyboard:
    keyboard.press(keyboard.KEY_UP)

请为其他人注释掉代码,看看每种跳转的效果。

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

标签: pythonseleniumselenium-webdrivercanvaskeyboard-python

解决方案


不幸的是,我看不到该游戏中跳跃的可重现行为。当我按 UP o SPACE 时,我随机看到短跳或长跳,所以我不能确定我的方法是否适合你。

但是,我认为,只需稍加努力,您就可以创建一个适合您需求的合适活动。基本上,由于 Selenium 可以执行任意 javascript,我的方法是向 canvas 元素发送一个 keydown 事件(使用 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()

推荐阅读