簡體   English   中英

如何將密鑰“發送”到 canvas 元件更長時間?

[英]How to “send keys” to a canvas element for longer duration?

我的目標:

我正在嘗試制作一個 python 機器人來贏得chrome 的恐龍游戲

游戲允許 2 種類型的跳躍:

  • 短跳
  • 跳遠

使用main_body.send_keys(Keys.SPACE) (如下面的代碼所示)可以進行短跳轉。

我的問題:

我在執行跳遠時遇到困難。

我的做法:

目前,對於跳遠,我正在使用Keyboard庫:

keyboard.press(keyboard.KEY_UP)

不幸的是,這需要瀏覽器 windows 始終處於焦點位置。 后來,我希望無頭運行這個程序,所以這種方法行不通。

或者:

我試過ActionChains

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

但這最終會滾動整個頁面。 並且沒有達到預期的目的。

我只是希望直接將這些操作“發送”到 canvas 元素,而不是在整個頁面上執行它們......

我想做這樣的事情

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 has no attribute 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且不滾動整個頁面的情況下進行跳遠的其他替代方法...

不幸的是,我看不到該游戲中跳躍的可重現行為。 當我按 UP o SPACE 時,我隨機看到短跳或長跳,所以我不能確定我的方法是否適合你。

但是,我認為,只需稍加努力,您就可以創建一個適合您需求的合適活動。 Basically, since Selenium can execute arbitrary javascript, my approach here is to send a keydown event to the canvas element (tested with 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()

你是如此接近。 不過有幾句話:

霸王龍

  • 在您的短跳轉代碼塊中,您不需要將Keys.SPACE發送到任何元素。
  • 在您的代碼塊中進行長跳,您也不需要將Keys.SPACE發送到任何元素,並且變量keyboard也沒有定義。

解決方案

作為一種解決方案,一旦您打開 url,您需要為canvas元素的visibility_of_element_located()誘導WebDriverWait ,您可以使用以下任一基於定位器策略的解決方案。


短跳

對於短跳,您可以使用:

driver.get("https://chromedino.com/")
WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "canvas.runner-canvas")))
while True:
    #short jump
    ActionChains(driver).key_down(Keys.SPACE).key_up(Keys.SPACE).perform()

我一直能夠得分69-72

快照:

短跳


0.2秒停頓的跳遠

對於帶有pause(0.2)的長跳,您可以使用:

driver.get("https://chromedino.com/")
WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "canvas.runner-canvas")))
while True:
    #short jump
    # ActionChains(driver).key_down(Keys.SPACE).key_up(Keys.SPACE).perform()

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

我一直能夠得分65

快照:

longjump_0.2


0.5秒停頓的跳遠

對於帶有pause(0.5)的長跳,您可以使用:

driver.get("https://chromedino.com/")
WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "canvas.runner-canvas")))
while True:
    #short jump
    # ActionChains(driver).key_down(Keys.SPACE).key_up(Keys.SPACE).perform()

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

我一直能夠得分57-60

快照:

longjump_0.5

這是一個簡單的解決方案 -

import keyboard

keyboard.press_and_release('space', 'space', 'space')

當我嘗試時它起作用了,所以應該起作用。 您可以增加和減少已寫入'space'的時間數量以增加或減少持續時間。

希望它有所幫助:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM