Как «отправить ключи» элементу холста на более длительный срок? - PullRequest
5 голосов
/ 21 июня 2020

Моя цель:

Я пытаюсь создать python бота, чтобы выиграть игру chrome .

Игра допускает 2 типа прыжков:

  • короткие прыжки
  • длинные прыжки

Использование main_body.send_keys(Keys.SPACE) (как показано в коде ниже) дает короткие прыжки.

Моя проблема:

У меня проблемы с выполнением длинных прыжков.

Мой подход:

В настоящее время для прыжков в длину я использую библиотеку Keyboard:

keyboard.press(keyboard.KEY_UP)

Это, к сожалению, требует, чтобы браузер windows был все время в фокусе. Позже я sh запустил эту программу без подключения к голове, поэтому этот подход не сработает.

В качестве альтернативы:

Я пробовал ActionChains:

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

Но это заканчивается прокруткой всей страницы. И не выполняет намеченную цель.

Я просто sh «отправляю» эти действия непосредственно элементу холста, вместо того, чтобы выполнять их на всей странице ...

Я sh, чтобы сделать что-то вроде этого :

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_down или key_up.

Вот MCVE:

ПРИМЕЧАНИЕ : В коде динозавр будет продолжать прыгать, но не в этом суть, это просто для того, чтобы проверить высоту прыжков, а не для победы в игре. код для других.

Если возможно, предложите другой альтернативный способ сделать прыжок в длину без использования Keyboard и без прокрутки всей страницы ...

Ответы [ 3 ]

2 голосов
/ 20 июля 2020

Вы были так близки. Однако несколько слов:

  • The T-RexDinosaur внутри T-Rex Chrome Dino Game анимируется только внутри
  • Элемент управления, т.е. нажатие клавиши пробел , не нужно отправлять в холст , но его можно запускать только с клавиатуры.

T-RexDino

  • In your code block for short jumps you don't need to send Keys.SPACE to any element.
  • In your code block for long jumps as well you don't need to send Keys.SPACE to any element and the variable keyboard wasn't defined as well.

Solution

As a solution once you open the url you need to induce WebDriverWait для visibility_of_element_located() элемента canvas , и вы можете использовать любое из следующих решений на основе стратегии Locator .

Короткие прыжки

Для коротких прыжков вы можете использовать:

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

Снимок:

shortjump


Long Jumps with 0.2 seconds pause

For long jumps with pause(0.2) you can use:

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

I was consistently able to score 65

Snapshot:

longjump_0.2


Long Jumps with 0.5 seconds pause

For long jumps with pause(0.5) you can use:

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

I was consistently able to score 57-60

Snapshot:

longjump_0.5

2 голосов
/ 19 июля 2020

К сожалению, я не вижу воспроизводимого поведения прыжков в этой игре. Когда я нажимаю ВВЕРХ или ПРОБЕЛ, я случайно вижу короткие или длинные прыжки, поэтому я не могу быть уверен, сработает ли мой подход для вас.

Однако я думаю, что с небольшим усилием вы могли бы создать подходящее мероприятие, которое будет соответствовать вашим потребностям. По сути, поскольку Selenium может выполнять произвольные javascript, мой подход заключается в отправке события нажатия клавиши на элемент холста (проверено с помощью 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()
0 голосов
/ 20 июля 2020

Вот простое решение -

import keyboard

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

Это сработало, когда я попробовал, так что должно работать. Вы можете увеличивать и уменьшать количество записанных записей 'space', чтобы увеличить или уменьшить продолжительность записи.

Надеюсь, это помогло :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...