首页 > 解决方案 > Python Selenium - browser.find_element_by_class_name - 有时返回错误?

问题描述

我是 Python 的新手——通过“自动化无聊的东西”——Al Swigart。

我已经编写了一个脚本来玩“ https://gabrielecirulli.github.io/2048 ”上的“2048”瓷砖游戏。几次移动后,瓷砖游戏将“最大化”并弹出“游戏结束!” 我还没有弄清楚如何阅读 - 所以我已经实现了逻辑,在每 4 个动作之后读取分数,确定分数是否停止增加,如果是,游戏结束!

我发现的是我阅读分数的声明,有时会返回错误。我不知道为什么它要么正常工作,要么不工作。为什么它有时会返回错误?!?

我把它放在一个 try/except 块中,所以如果我得到一个错误,我会计算它。有时是几个,有时是大约一半的时间。

我将不胜感激任何帮助或建议。

谢谢。

output...
Evolutions: 40   oldScore1308    newScore: 1736
Evolutions: 41   oldScore1736    newScore: 1736
GAME OVER!
Good Game.

Final Score:
Evolutions: 41   OldScore1736    NewScore: 1736   Errors:23
Pausing before program closes.  Hit enter to continue.

代码:

#! python


import webbrowser
from selenium import webdriver
from selenium.webdriver.common.keys import Keys  # import Keys to send special keys
from selenium.common.exceptions import NoSuchElementException
import time


def opensite():
    # open browser
    global browser  # stop chrome window from closing by itself.
    browser = webdriver.Chrome()
    browser.get("https://gabrielecirulli.github.io/2048")

    return browser


def botKeys():
    # function to send arrow keys to browser :up, right, down, left.
    w = 0.025  # time to wait between plays
    try:
        element = browser.find_element_by_tag_name("body")

        gameOn = True
        counter = 0
        oldScore = 0
        error = 0

        while gameOn == True:

            counter += 1

            # Send keys to move pieces
            time.sleep(w)
            element.send_keys(Keys.UP)

            time.sleep(w)
            element.send_keys(Keys.RIGHT)

            time.sleep(w)
            element.send_keys(Keys.DOWN)

            time.sleep(w)
            element.send_keys(Keys.LEFT)

            # check the score.  Keep track of it to determine if GAME OVER!
            try:
                newScore = browser.find_element_by_class_name(
                    "score-container"
                )  # get the object with the score.
                newScore = int(
                    newScore.text
                )  # read the text of the object, which is the score in a string.  Convert it to an integer.

                print(
                    f"Evolutions: {counter}   oldScore{oldScore}    newScore: {newScore}"
                )
                if oldScore != newScore:
                    oldScore = newScore
                else:  # old and new are the same, game over
                    print(f"GAME OVER!\nGood Game.")
                    print(f"\nFinal Score:")
                    print(
                        f"Evolutions: {counter}   OldScore{oldScore}    NewScore: {newScore}   Errors:{error}"
                    )
                    gameOn = False

            except ValueError:
                error += 1  # count value errors, but that's all.

    except NoSuchElementException:
        print("Could not find element")

    input("Pausing before program closes.  Hit enter to continue.")


def main():

    # TODO  open the site
    driver = opensite()
    # TODO  send keystrokes
    botKeys()
    driver.close()


if __name__ == "__main__":
    main()

标签: pythonseleniumweb-scraping

解决方案


如果显示错误

except ValueError as ex:
    error += 1
    print(ex)

然后你看看有什么问题

invalid literal for int() with base 10: '3060\n+20'

问题是有时它会显示3060带有添加到 result 的点的结果+20

当您将其拆分\n并获取第一个元素时,它可以正常工作

newScore = int(
    newScore.text.split('\n')[0]
)

认识到Game Over你需要

game_over = driver.find_element_by_class_name("game-over")  # 

但是当没有类时它会引发错误,game-over所以我会使用find_elementss在 word 末尾find_elements)来获取空列表而不是引发错误。

顺便说一句:我更改了一些名称,因为PEP 8 -- Python 代码样式指南


from selenium import webdriver
from selenium.webdriver.common.keys import Keys  # import Keys to send special keys
from selenium.common.exceptions import NoSuchElementException
import time


def opensite():
    driver = webdriver.Chrome()
    driver.get("https://gabrielecirulli.github.io/2048")
    return driver


def bot_keys(driver):
    '''Function to send arrow keys to browser :up, right, down, left.'''

    wait = 0.025  # time to wait between plays

    try:
        element = driver.find_element_by_tag_name("body")

        game_on = True
        counter = 0
        old_score = 0
        new_score = 0
        error = 0

        while game_on:

            counter += 1

            # Send keys to move pieces
            time.sleep(wait)
            element.send_keys(Keys.UP)

            time.sleep(wait)
            element.send_keys(Keys.RIGHT)

            time.sleep(wait)
            element.send_keys(Keys.DOWN)

            time.sleep(wait)
            element.send_keys(Keys.LEFT)

            # check the score.  Keep track of it to determine if GAME OVER!
            try:

                new_score = driver.find_element_by_class_name("score-container")  # get the object with the score.

                new_score = int(new_score.text.split('\n')[0])  # read the text of the object, which is the score in a string.  Convert it to an integer.

                print(f"Evolutions: {counter:5} | Old Score: {old_score:5} | New Score: {new_score:5}")

                old_score = new_score

                game_over = driver.find_elements_by_class_name("game-over")  # get the object with the score.
                #print('game_over:', len(game_over))

                if game_over:
                    print("\nGAME OVER!\n")
                    print("Final Score:")
                    print(f"Evolutions: {counter:5} | New Score: {new_score:5} | Errors: {error}")
                    game_on = False

            except ValueError as ex:
                print('ex:', ex)
                error += 1  # count value errors, but that's all.

    except NoSuchElementException:
        print("Could not find element")

    input("\nPausing before program closes.  Hit enter to continue.")


def main():
    driver = opensite()
    bot_keys(driver)
    driver.close()


if __name__ == "__main__":
    main()

也许下一步是使用Gym(或类似的东西)来使用Reinforcement Learning( Machine Learning, Artificial Intelligence)


推荐阅读