Selenium click()函数(貌似)没有随机单击框[无错误] [Python] [英] Selenium click() function (seemingly) randomly doesn't click the box [No errors][Python]

查看:79
本文介绍了Selenium click()函数(貌似)没有随机单击框[无错误] [Python]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是硒的新手,并且正在制作一个自动执行琐事的机器人.登录效果很好,大多数单击框也是如此,并转到下一个问题.

I am new to selenium and am making a bot to automatically do trivia. The login works great, and so do most of the clicking boxes and going to the next question.

随意地,他们不单击按钮,也不要单击以进行下一个循环.对于最后的问题(9个及以上),这种情况经常发生,但这可能是巧合.

Randomly they do not click the button, and also do not click for the next loop. This happens a lot towards the final questions (9 and over) but this could be coincidence.

非常令人困惑的是没有显示错误吗? 代码完成无误

The very confusing this is that there is no error shown? The code finishes without errors

有人知道为什么会这样吗?

Does anyone have any idea of why this is happening?

主要代码

from selenium import webdriver
from time import *
from data import *
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class TriviaBot():
    def __init__(self):
        self.driver = webdriver.Chrome()
        self.driver.get("https://www.freekigames.com/educational-trivia")
    def login(self):
        # selects and clicks the "Login/Sign Up" button on the home-page
        self.login_btn = self.driver.find_element_by_xpath('//*[@id="loginContainer"]/a')
        self.login_btn.click()

        sleep(2) # allows username + password box to load in

        self.driver.switch_to.frame(bot.driver.find_element_by_xpath('//*[@id="jPopFrame_content"]')) # switches to correct frame for login box

        # selects username-box and types in my username and then does the same for password
        self.username_box = self.driver.find_element_by_xpath('//*[@id="userName"]') #username
        self.username_box.send_keys(username)

        self.username_box = self.driver.find_element_by_xpath('//*[@id="password"]') #password
        self.username_box.send_keys(password)

        # selects login box and then clicks
        self.login_box = self.driver.find_element_by_xpath('//*[@id="bp_login"]')
        self.login_box.click()

        sleep(2) # allows main page to load again
    def AmericanPresidents(self):
        self.i = 0
        # sends browser to first trivia
        self.driver.get("https://www.freekigames.com/american-presidents-trivia")

        while True: #there are ? # of questions, so I loop it 12 times
            self.i += 1
            if self.i == 13:
                break
            print("run: "+str(self.i))

            # sets the variable to the current question so that the correct answer can be located through answer lists
            self.current_question = ((self.driver.find_element_by_xpath('//*[@id="quizContainer"]/div[2]')).text)

            #setting variables for boxes and their text values. The text can be corrolated to the button allowing the bot to click the correct answer

            self.button_1 = WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.XPATH,('/html//div[@id="quizContainer"]/div[@class="answersContainer"]/div[1]/span[@class="answerBox"]/a[@name="checkboxtag"]'))))
            self.text_1   = (self.driver.find_element_by_xpath('//*[@id="quizContainer"]/div[3]/div[1]/span[2]').text)


            self.button_2 = WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.XPATH,('/html//div[@id="quizContainer"]/div[@class="answersContainer"]/div[2]/span[@class="answerBox"]/a[@name="checkboxtag"]'))))
            self.text_2   = (self.driver.find_element_by_xpath('//*[@id="quizContainer"]/div[3]/div[2]/span[2]').text)


            self.button_3 = WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.XPATH,('/html//div[@id="quizContainer"]/div[@class="answersContainer"]/div[3]/span[@class="answerBox"]/a[@name="checkboxtag"]'))))
            self.text_3   = (self.driver.find_element_by_xpath('//*[@id="quizContainer"]/div[3]/div[3]/span[2]').text)


            self.button_4 = WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.XPATH,('/html//div[@id="quizContainer"]/div[@class="answersContainer"]/div[4]/span[@class="answerBox"]/a[@name="checkboxtag"]'))))
            self.text_4   = (self.driver.find_element_by_xpath('//*[@id="quizContainer"]/div[3]/div[4]/span[2]').text)


            for i in range(0, len(american_presidents)):
                if american_presidents[i]["question"] == self.current_question:
                    self.dataLine = i
            if self.text_1 == american_presidents[self.dataLine]["answer"]:
                self.button_1.click()
            if self.text_2 == american_presidents[self.dataLine]["answer"]:
                self.button_2.click()
            if self.text_3 == american_presidents[self.dataLine]["answer"]:
                self.button_3.click()
            if self.text_4 == american_presidents[self.dataLine]["answer"]:
                self.button_4.click()

            sleep(0.5) # to stop the code from beating itself. Going to quick

            # selects and clicks the "Next Question!" button
            nextquestion_btn = WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.XPATH,('//*[@id="nextQuestion"]'))))
            nextquestion_btn.click()
bot = TriviaBot()
bot.login()
bot.AmericanPresidents()

data.py

american_presidents = [
    {"question" : "Who was the 1st president of the United States?",
     "answer"   : "George Washington"},
    {"question" : "Who was the 2nd president of the United States?",
     "answer"   : "John Adams"},
    {"question" : "Who was the 3rd president of the United States?",
     "answer"   : "Thomas Jefferson"},
    {"question" : "Who was the 4th president of the United States?",
     "answer"   : "James Madison"},
    {"question" : "Who was the 5th president of the United States?",
     "answer"   : "James Monroe"},
    {"question" : "Who was the 6th president of the United States?",
     "answer"   : "John Quincy Adams"},
    {"question" : "Who was the 7th president of the United States?",
     "answer"   : "Andrew Jackson"},
    {"question" : "Who was the 8th president of the United States?",
     "answer"   : "Martin Van Buren"},
    {"question" : "Who was the 9th president of the United States?",
     "answer"   : "William Henry Harrison"},
    {"question" : "Who was the 10th president of the United States?",
     "answer"   : "John Tyler"},
    {"question" : "Who was the 11th president of the United States?",
     "answer"   : "James K. Polk"},
    {"question" : "Who was the 12th president of the United States?",
     "answer"   : "Zachary Taylor"},
    {"question" : "Who was the 13th president of the United States?",
     "answer"   : "Millard Fillmore"},
    {"question" : "Who was the 14th president of the United States?",
     "answer"   : "Franklin Pierce"},
    {"question" : "Who was the 15th president of the United States?",
     "answer"   : "James Buchanan"},
    {"question" : "Who was the 16th president of the United States?",
     "answer"   : "Abraham Lincoln"},
    {"question" : "Who was the 17th president of the United States?",
     "answer"   : "Andrew Johnson"},
    {"question" : "Who was the 18th president of the United States?",
     "answer"   : "Ulysses S. Grant"},
    {"question" : "Who was the 19th president of the United States?",
     "answer"   : "Rutherford B. Hayes"},
    {"question" : "Who was the 20th president of the United States?",
     "answer"   : "James A. Garfield"},
    {"question" : "Who was the 21st president of the United States?",
     "answer"   : "Chester A. Arthur"},
    {"question" : "Who was the 22nd president of the United States?",
     "answer"   : "Grover Cleveland"},
    {"question" : "Who was the 23rd president of the United States?",
     "answer"   : "Benjamin Harrison"},
    {"question" : "Who was the 24th president of the United States?",
     "answer"   : "Grover Cleveland"},
    {"question" : "Who was the 25th president of the United States?",
     "answer"   : "William McKinley"},
    {"question" : "Who was the 26th president of the United States?",
     "answer"   : "Theodore Roosevelt"},
    {"question" : "Who was the 27th president of the United States?",
     "answer"   : "William Howard Taft"},
    {"question" : "Who was the 28th president of the United States?",
     "answer"   : "Woodrow Wilson"},
    {"question" : "Who was the 29th president of the United States?",
     "answer"   : "Warren G. Harding"},
    {"question" : "Who was the 30th president of the United States?",
     "answer"   : "Clavin Coolidge"},
    {"question" : "Who was the 31st president of the United States?",
     "answer"   : "Herbert Hoover"},
    {"question" : "Who was the 32nd president of the United States?",
     "answer"   : "Frankin D. Roosevelt"},
    {"question" : "Who was the 33rd president of the United States?",
     "answer"   : "Harry S. Truman"},
    {"question" : "Who was the 34th president of the United States?",
     "answer"   : "Dwight D. Eisenhower"},
    {"question" : "Who was the 35th president of the United States?",
     "answer"   : "John F. Kennedy"},
    {"question" : "Who was the 36th president of the United States?",
     "answer"   : "Lyndon B. Johnson"},
    {"question" : "Who was the 37th president of the United States?",
     "answer"   : "Richard Nixon"},
    {"question" : "Who was the 38th president of the United States?",
     "answer"   : "Gerald Ford"},
    {"question" : "Who was the 39th president of the United States?",
     "answer"   : "Jimmy Carter"},
    {"question" : "Who was the 40th president of the United States?",
     "answer"   : "Ronald Reagan"},
    {"question" : "Who was the 41st president of the United States?",
     "answer"   : "George W. H. Bush"},
    {"question" : "Who was the 42nd president of the United States?",
     "answer"   : "Bill Clinton"},
    {"question" : "Who was the 43rd president of the United States?",
     "answer"   : "George W. Bush"},
    {"question" : "Who was the 44th president of the United States?",
     "answer"   : "Barack Obama"}

]

错误

Traceback (most recent call last):
  File ".\trivia-bot.py", line 83, in <module>
    bot.AmericanPresidents()
  File ".\trivia-bot.py", line 80, in AmericanPresidents
    nextquestion_btn.click()
  File "C:\Program Files\Python36\lib\site-packages\selenium\webdriver\remote\webelement.py", line 80, in click
    self._execute(Command.CLICK_ELEMENT)
  File "C:\Program Files\Python36\lib\site-packages\selenium\webdriver\remote\webelement.py", line 633, in _execute
    return self._parent.execute(command, params)
  File "C:\Program Files\Python36\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 321, in execute
    self.error_handler.check_response(response)
  File "C:\Program Files\Python36\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 242, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable
  (Session info: chrome=79.0.3945.130)

推荐答案

您没有看到错误的最可能原因是因为您使用的xpath实际上是在查找元素,但可能不是您想要的元素.该页面为每个问题加载了动画样式,您可以在完成搜索之前先进行搜索.您应该做的是使用等待元素的找到,并使用更特定于您需要的xpath.以下是有关等待的更多信息的链接: https://selenium-python.readthedocs.io/waits.html

The most likely reason you are not seeing an error is because your xpath's that you are using are actually finding elements, but possibly not the elements you intended. The page loads with an animation style for each question and you could be doing your searches before they are done. What you should be doing is using waits for the element to be found and using an xpath more specific to what you need. Here is a link to more info on waits: https://selenium-python.readthedocs.io/waits.html

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC   

self.button_1 = WebDriverWait(driver, 10).until(EC.presence_of_element_located(By.XPATH,'/html//div[@id="quizContainer"]/div[@class="answersContainer"]/div[1]/span[@class="answerBox"]/a[@name="checkboxtag"]))

对其余元素执行此操作.我还将使用这些定位器:

Do this for the rest of your elements. I would also use these locators:

#setting variables for boxes and their text values. The text can be corrolated to the button allowing the bot to click the correct answer
self.button_1 = (self.driver.find_element_by_xpath('/html//div[@id="quizContainer"]/div[@class="answersContainer"]/div[1]/span[@class="answerBox"]/a[@name="checkboxtag"]))
self.text_1   = (self.driver.find_element_by_xpath(/html//div[@id="quizContainer"]/div[@class="answersContainer"]/div[1]/span[@class="answerText"]).text)

self.button_2 = (self.driver.find_element_by_xpath(/html//div[@id="quizContainer"]/div[@class="answersContainer"]/div[2]/span[@class="answerBox"]/a[@name="checkboxtag"]))
self.text_2   = (self.driver.find_element_by_xpath(/html//div[@id="quizContainer"]/div[@class="answersContainer"]/div[2]/span[@class="answerText"]).text)

self.button_3 = (self.driver.find_element_by_xpath(/html//div[@id="quizContainer"]/div[@class="answersContainer"]/div[3]/span[@class="answerBox"]/a[@name="checkboxtag"]))
self.text_3   = (self.driver.find_element_by_xpath(/html//div[@id="quizContainer"]/div[@class="answersContainer"]/div[3]/span[@class="answerText"]).text)

self.button_4 = (self.driver.find_element_by_xpath(/html//div[@id="quizContainer"]/div[@class="answersContainer"]/div[4]/span[@class="answerBox"]/a[@name="checkboxtag"]))
self.text_4   = (self.driver.find_element_by_xpath(/html//div[@id="quizContainer"]/div[@class="answersContainer"]/div[4]/span[@class="answerText"]).text)

查找要单击的复选框的另一种方法是改用这些定位符:

Another option for finding the checkbox to click is to use these locators instead:

self.button_1 = WebDriverWait(driver, 10).until(EC.presence_of_element_located(By.XPATH, '/html//div[@id="quizContainer"]/div[@class="answersContainer"]/div[1]/span[@class="answerBox"]/input[@name="answers"]'))
self.button_2 = WebDriverWait(driver, 10).until(EC.presence_of_element_located(By.XPATH, '/html//div[@id="quizContainer"]/div[@class="answersContainer"]/div[2]/span[@class="answerBox"]/input[@name="answers"]'))
self.button_3 = WebDriverWait(driver, 10).until(EC.presence_of_element_located(By.XPATH, '/html//div[@id="quizContainer"]/div[@class="answersContainer"]/div[3]/span[@class="answerBox"]/input[@name="answers"]'))
self.button_4 = WebDriverWait(driver, 10).until(EC.presence_of_element_located(By.XPATH, '/html//div[@id="quizContainer"]/div[@class="answersContainer"]/div[4]/span[@class="answerBox"]/input[@name="answers"]'))

您的错误消息指向下一个问题按钮,并且该按钮不可交互.改用它:

Your error message refers to the next question button and it not being interactable. Use this instead:

 nextquestion_btn = WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.XPATH,('//*[@id="nextQuestion"]'))))

这篇关于Selenium click()函数(貌似)没有随机单击框[无错误] [Python]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆