【问题标题】:Unable to Select Checkbox element Selenium Python无法选择复选框元素 Selenium Python
【发布时间】:2021-04-19 00:04:25
【问题描述】:

我正在尝试从此网站https://brainbooks.pk/newtest-system/free_mcqs.php 生成数据。形式是动态的。在表单中有四个下拉菜单。我可以选择前 3 个(董事会、班级和主题),然后是单元下拉最后一个。带有复选框的那个。我想循环并一一检查。我无法遍历单元元素。这是我的代码:

import time
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import Select, WebDriverWait
driver = webdriver.Chrome(ChromeDriverManager().install())
driver.get('https://brainbooks.pk/newtest-system/free_mcqs.php')
def get_options(driver, class_name):
    drop_down = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, class_name)))
    select = Select(drop_down)
    return select.options
board_option = driver.find_element_by_xpath('//*[@id="board_id"]/option[2]')
board_option.click()
time.sleep(0.5)
class_options = ['//*[@id="class_id"]/option[2]','//*[@id="class_id"]/option[3]','//*[@id="class_id"]/option[4]','//*[@id="class_id"]/option[5]']
for class_select in class_options:
    select_class = driver.find_element_by_xpath(class_select)
    print(select_class.text)
    select_class.click()
    if class_select == '//*[@id="class_id"]/option[2]':
        subject_options = get_options(driver, 'subject')
        for subj in subject_options[1:]:
            print(subj.text)
            subj.click()
            topic_options = get_options(driver, 'q_unit')
            time.sleep(1.5)
            for topic in topic_options:
                print(topic)
                topic.click()
                time.sleep(1.5)
                break
            break
        break
    break

编辑 1
break 是临时的。如果一个循环成功执行它们,我将删除它们并让脚本完全运行。
我尝试使用此代码"//input[@type='checkbox'][@data-chid='" + i+ "']" 循环复选框并收到此错误TypeError: 'WebElement' object is not iterable

import time
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import Select, WebDriverWait
driver = webdriver.Chrome(ChromeDriverManager().install())
driver.get('https://brainbooks.pk/newtest-system/free_mcqs.php')
def get_options(driver, class_name):
    drop_down = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, class_name)))
    select = Select(drop_down)
    return select.options
board_option = driver.find_element_by_xpath('//*[@id="board_id"]/option[2]')
board_option.click()
time.sleep(0.5)
class_options = ['//*[@id="class_id"]/option[2]','//*[@id="class_id"]/option[3]','//*[@id="class_id"]/option[4]','//*[@id="class_id"]/option[5]']
for class_select in class_options:
    select_class = driver.find_element_by_xpath(class_select)
    print(select_class.text)
    select_class.click()
    if class_select == '//*[@id="class_id"]/option[2]':
        subject_options = get_options(driver, 'subject')
        for subj in subject_options[1:]:
            print(subj.text)
            subj.click()
            topic_options = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, 'q_unit')))
            time.sleep(1.5)
            for topic in topic_options:
                select_topic = driver.find_element_by_xpath("//input[@type='checkbox'][@data-chid='" + topic + "']").click()
                print(select_topic.text)
                select_topic.click()
                time.sleep(1.5)
                break
            break
        break
    break

EDIT 2
1 次迭代之后它工作得非常好,我收到了这个错误 element not interactable

import time

import pyautogui
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import Select, WebDriverWait
from webdriver_manager.chrome import ChromeDriverManager

driver = webdriver.Chrome(ChromeDriverManager().install())
driver.get('https://brainbooks.pk/newtest-system/free_mcqs.php')
def get_options(driver, class_name):
    drop_down = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, class_name)))
    select = Select(drop_down)
    return select.options
board_option = driver.find_element_by_xpath('//*[@id="board_id"]/option[2]')
board_option.click()
time.sleep(0.5)
class_options = ['//*[@id="class_id"]/option[2]','//*[@id="class_id"]/option[3]','//*[@id="class_id"]/option[4]','//*[@id="class_id"]/option[5]']
for class_select in class_options:
    select_class = driver.find_element_by_xpath(class_select)
    select_class.click()
    time.sleep(2)
    if class_select == '//*[@id="class_id"]/option[2]':
        try:
            subject_options = get_options(driver, 'subject')
        except:
            select_class = driver.find_element_by_xpath('//*[@id="class_id"]/option[1]')
            select_class.click()
            select_class = driver.find_element_by_xpath(class_select)
            select_class.click()
            time.sleep(2)
        finally:
            subject_options = get_options(driver, 'subject')
        for subj in subject_options[1:]:
            print(subj.text)
            sub_name = subj.text
            subj.click()
            WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'mutliSelect')))

            units_container = driver.find_element_by_class_name("mutliSelect")
            topic_options = units_container.find_elements_by_xpath("//input[@type='checkbox']")
            time.sleep(1.5)
            for select_topic in topic_options:
                topic_name = select_topic.find_element_by_xpath("..")
                print(topic_name.text)
                select_topic.click()
                time.sleep(1.5)
                generate_button = (driver.find_element_by_xpath('/html/body/div[2]/div/div[2]/div[1]/div/div[1]/div/button[1]')).click()
                time.sleep(3)
                view_result_button = (driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div[1]/div/div[1]/div/button[3]')).click()
                #Saving Html Pages
                topic_title = topic_name.text
                topic_title = topic_title.replace(':', '-')
                topic_title = topic_title.replace('  ', ' ')
                save_file_name = sub_name+'-'+topic_title
                pyautogui.hotkey("ctrlleft", "s") # Saving File
                time.sleep(.5)
                pyautogui.press('f4') # Opening Address Bar
                time.sleep(.5)
                pyautogui.hotkey("ctrlleft", "a") # Selecting Previous Address
                time.sleep(.5)
                pyautogui.press('delete') # Removing Previous Address
                time.sleep(.5)
                pyautogui.write('C:\\Users\Ali Abdullah\Downloads\BrainFreeMCQS') # Entering New Address
                time.sleep(.5)
                pyautogui.press('enter')
                time.sleep(.5)
                pyautogui.click(496,342)
                time.sleep(.5)
                pyautogui.hotkey("ctrlleft", "a") # Selecting File Name
                time.sleep(.5)
                pyautogui.press('delete') # Deleting Previous File Name
                time.sleep(.5)
                pyautogui.write(save_file_name) # Entering New File Name
                time.sleep(.5)
                pyautogui.click(448,451) # Clicking Save

EDIT 3
当我尝试添加 pyguiauto 代码来保存完整的网页时。我用于 De Selecting Previous CheckBox 的 select_topic.click() 不起作用。 Error: 'WebElement' object is not iterable

import time
import pyautogui
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import Select, WebDriverWait
driver = webdriver.Chrome(ChromeDriverManager().install())
driver.get('https://brainbooks.pk/newtest-system/free_mcqs.php')
def get_options(driver, class_name):
    drop_down = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, class_name)))
    select = Select(drop_down)
    return select.options
board_option = driver.find_element_by_xpath('//*[@id="board_id"]/option[2]')
board_option.click()
time.sleep(0.5)
class_options = ['//*[@id="class_id"]/option[2]','//*[@id="class_id"]/option[3]','//*[@id="class_id"]/option[4]','//*[@id="class_id"]/option[5]']
for class_select in class_options:
    select_class = driver.find_element_by_xpath(class_select)
    print(select_class.text)
    select_class.click()
    time.sleep(3)
    if class_select == '//*[@id="class_id"]/option[2]':
        try:
            subject_options = get_options(driver, 'subject')
        except:
            select_class = driver.find_element_by_xpath('//*[@id="class_id"]/option[1]')
            select_class.click()
            select_class = driver.find_element_by_xpath(class_select)
            select_class.click()
            time.sleep(2)
        finally:
            subject_options = get_options(driver, 'subject')
        for subj in subject_options[1:]:
            print(subj.text)
            subj.click()
            time.sleep(3)
            WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'mutliSelect')))
            units_container = driver.find_element_by_class_name("mutliSelect")
            topic_options = units_container.find_elements_by_xpath("//input[@type='checkbox']")
            time.sleep(1.5)
            for select_topic in topic_options:
                topic_name = select_topic.find_element_by_xpath("..")
                print(topic_name.text)
                select_topic.click()
                time.sleep(1.5)
                generate_button = (driver.find_element_by_xpath('/html/body/div[2]/div/div[2]/div[1]/div/div[1]/div/button[1]')).click()
                time.sleep(3)
                select_topic.click() #De Selecting Previous CheckBox
                time.sleep(1)
                view_result_button = (driver.find_element_by_xpath('/html/body/div[3]/div/div[2]/div[1]/div/div[1]/div/button[3]')).click()

                # Saving Html Pages
                sub_name = subj.text
                topic_title = topic_name.text
                topic_title = topic_title.replace(':', '-')
                topic_title = topic_title.replace('  ', ' ')
                save_file_name = sub_name + '-' + topic_title
                time.sleep(1)
                pyautogui.hotkey("ctrlleft", "s")  # Saving File
                time.sleep(.5)
                pyautogui.press('f4')  # Opening Address Bar
                time.sleep(.5)
                pyautogui.hotkey("ctrlleft", "a")  # Selecting Previous Address
                time.sleep(.5)
                pyautogui.press('delete')  # Removing Previous Address
                time.sleep(.5)
                pyautogui.write('C:\\Users\Ali Abdullah\Downloads\BrainFreeMCQS')  # Entering New Address
                time.sleep(.5)
                pyautogui.press('enter')
                time.sleep(.5)
                pyautogui.click(496, 342)
                time.sleep(.5)
                pyautogui.hotkey("ctrlleft", "a")  # Selecting File Name
                time.sleep(.5)
                pyautogui.press('delete')  # Deleting Previous File Name
                time.sleep(.5)
                pyautogui.write(save_file_name)  # Entering New File Name
                time.sleep(.5)
                pyautogui.click(448, 451)  # Clicking Save
                time.sleep(1.5)



try:
    if driver is not None:
        driver.quit()
except Exception as e:
    print(e)

【问题讨论】:

  • class_options 是什么问题?
  • 首先,用英文添加您正在执行的操作的描述。其次,添加您看到的错误消息。三、为什么这么多break??
  • 表单中有四个下拉菜单。我可以选择前 3 个(董事会、班级和主题),然后是单元下拉最后一个。带有复选框的那个。我想循环浏览并一一检查

标签: python selenium selenium-webdriver


【解决方案1】:

代码的问题是,有时当您单击课程时,主题选择不会显示。所以,你试图点击一个不存在的元素。您还可以使用“mutliSelect”作为类名并使用该类名来获取所有复选框。这可能更强大,而不是获取所有复选框。因为这也将帮助您获取主题的名称。我还添加了一个 try except 块,因为在手动尝试时,有时选择课程后不会出现主题选择。所以我想了一个办法。

import time
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import Select, WebDriverWait
driver = webdriver.Chrome(ChromeDriverManager().install())
driver.get('https://brainbooks.pk/newtest-system/free_mcqs.php')
def get_options(driver, class_name):
    drop_down = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, class_name)))
    select = Select(drop_down)
    return select.options
board_option = driver.find_element_by_xpath('//*[@id="board_id"]/option[2]')
board_option.click()
time.sleep(0.5)
class_options = ['//*[@id="class_id"]/option[2]','//*[@id="class_id"]/option[3]','//*[@id="class_id"]/option[4]','//*[@id="class_id"]/option[5]']
for class_select in class_options:
    select_class = driver.find_element_by_xpath(class_select)
    print(select_class.text)
    select_class.click()
    time.sleep(3)
    if class_select == '//*[@id="class_id"]/option[2]':
        try:
            subject_options = get_options(driver, 'subject')
        except:
            select_class = driver.find_element_by_xpath('//*[@id="class_id"]/option[1]')
            select_class.click()
            select_class = driver.find_element_by_xpath(class_select)
            select_class.click()
            time.sleep(2)
        finally:
            subject_options = get_options(driver, 'subject')
        for subj in subject_options[1:]:
            print(subj.text)
            subj.click()
            time.sleep(3)
            WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'mutliSelect')))
            units_container = driver.find_element_by_class_name("mutliSelect")
            topic_options = units_container.find_elements_by_xpath("//input[@type='checkbox']")
            time.sleep(1.5)
            for select_topic in topic_options:
                topic_name = select_topic.find_element_by_xpath("..")
                print(topic_name.text)
                select_topic.click()
                time.sleep(1.5)
                break
            break
        break
    break


try:
    if driver is not None:
        driver.quit()
except Exception as e:
    print(e)

如果你使用 q_unit,它也会以同样的方式工作。由于您直接从 WebDriverWait 获取元素并使用 ID,因此假设只有一个具有 ID 的元素,因为这就是 WebriverWait 返回元素的方式。因此,您需要像这样使用它,而不是从 WebDriverWait 获取元素:

WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, 'q_unit')))
topic_options = driver.find_elements_by_id("q_unit")

并且要使用这种方法获取名称,它与我们上面所做的类似:

for select_topic in topic_options:
    topic_name = select_topic.find_element_by_xpath("..")
    print(topic_name.text)
    select_topic.click()
    time.sleep(1.5)

我从输入类型获取父元素,因为 li 包含文本而不是 input 标记。所以你获取文本的方式是行不通的。

此代码现在适用于所有主题。如果需要,请查看输出。

【讨论】:

  • 在我得到这个error element not interactable 之后,它在 1 次迭代中运行良好
  • 错误是什么,错误发生在哪里?也不要使用 xpaths 列表。尝试在代码执行过程中获取这些信息。
  • 选择下拉列表中的第二个复选框时发生错误。它会减慢脚本速度,这就是我这样做的原因
  • @Ali - 请检查我刚刚所做的编辑。我添加了输出和睡眠时间。
  • 另外,我看到您正在使用绝对 xpaths 来生成按钮。尝试使用这个://button[@onclick="generatePaper1()"]
【解决方案2】:

在 XPath 下使用,其中 data_child 值 i 是变体并循环遍历它。

driver.find_element_by_xpath("//input[@type='checkbox'][@data-chid='"+i+"']").click()

更新:data_id 不是按顺序排列的,因此它不会循环所有 Like Part 语法等。 这是我使用的对我有用的代码

public class BrainBooks {
    public static final String Board= "//select[@id='board_id']";
    public static final String Class= "//div[@style='display: block;']/select[@id='class_id']";
    public static final String Subject= "//select[@id='subject']";

   public void ClickAllTopic(String BoardName,String ClassName,String SubjectName){
        driver.findElement(By.xpath(Board)).dropdown().selectByVisibleText(BoardName);
        driver.findElement(By.xpath(Class)).dropdown().selectByVisibleText(ClassName);
        driver.findElement(By.xpath(Subject)).dropdown().selectByVisibleText(SubjectName);
        int TopicCnt= driver.findElements(By.id("q_unit")).size();
        for(int i=0;i<TopicCnt;i++){
            driver.findElements(By.id("q_unit")).get(i).click();
        }

    }
}

这又是 Java。但是要将您的代码更改为以下主题选项

driver.find_elements_by_id('q_unit')

在for循环中迭代如下

driver.find_elements_by_id('q_unit').get(topic).click()

【讨论】:

  • 错误TypeError: 'WebElement' object is not iterable我更新代码看看
  • @Ali:在尝试自己之后更新了我的答案。请检查
猜你喜欢
  • 2021-12-06
  • 2017-11-10
  • 1970-01-01
  • 1970-01-01
  • 2018-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-24
相关资源
最近更新 更多