[英]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_down
或key_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
快照:
對於帶有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
快照:
對於帶有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
快照:
這是一個簡單的解決方案 -
import keyboard
keyboard.press_and_release('space', 'space', 'space')
當我嘗試時它起作用了,所以應該起作用。 您可以增加和減少已寫入'space'
的時間數量以增加或減少持續時間。
希望它有所幫助:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.