You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Selenium稳定定位元素以创建Kahoot填空题测验?

Selenium自动创建Kahoot填空题的元素定位问题解决

问题说明

使用Selenium从电子表格自动生成Kahoot填空题测验时,大部分功能正常,但在以下两处代码执行时不稳定,频繁抛出「找不到Web元素」的错误:

  • 第87-91行:添加新的填空题
  • 第98-101行:输入题目内容和答案

核心原因是页面元素加载存在延迟,当前使用的隐式等待无法精准适配动态元素的加载时机,需要改用显式等待确保元素可交互后再执行操作。

解决思路

显式等待通过WebDriverWait配合expected_conditions(EC)模块,针对特定元素设置等待条件(如元素可点击、可见、可输入),直到元素满足条件或超时。相比全局生效的隐式等待,显式等待更灵活精准,适合处理动态加载的页面元素。

需替换问题代码中的driver.implicitly_wait(),针对每个关键元素设置显式等待:

  1. 等待「添加题目」按钮可点击后再点击
  2. 等待「填空题类型」按钮可点击后再点击
  3. 等待题目输入框可交互后再输入内容
  4. 等待答案输入框可交互后再输入内容

修改后的关键代码片段

# 替换原问题中的循环代码部分
for index, row in quiz.iterrows():
    # 等待并点击「添加题目」按钮
    add_question_btn = WebDriverWait(driver, 10).until(
        EC.element_to_be_clickable((By.CSS_SELECTOR, 'button[data-functional-selector="add-question-button"]'))
    )
    add_question_btn.click()

    # 等待并点击「填空题」类型按钮
    answer_type_btn = WebDriverWait(driver, 10).until(
        EC.element_to_be_clickable((By.CSS_SELECTOR, 'button[data-functional-selector="create-button__open-ended"]'))
    )
    answer_type_btn.click()

    # 获取题目和答案内容
    question_input = row['Question']
    answer_input = row['Answer']

    # 等待题目输入框可输入,然后输入内容
    question_text = WebDriverWait(driver, 10).until(
        EC.element_to_be_clickable((By.CSS_SELECTOR, 'p[data-placeholder="Start typing your question"]'))
    )
    question_text.send_keys(question_input)

    # 等待答案输入框可输入,然后输入内容
    answer_text = WebDriverWait(driver, 10).until(
        EC.element_to_be_clickable((By.CSS_SELECTOR, 'input[placeholder="Type an answer"]'))
    )
    answer_text.send_keys(answer_input)

完整修改后的代码

import pandas as pd
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

import openpyxl

# 读取电子表格
df = pd.read_excel('1000 of the most common Spanish Nouns.xlsx')

# 账号信息
email = 'email'
password = 'password'

folder_name = input('Folder Name: ')
quiz_question_length = int(input('Length of each quiz: '))

# 初始化浏览器驱动
driver = webdriver.Chrome()

# 打开Kahoot登录页
driver.get('https://create.kahoot.it/auth/login')

# 输入账号密码
driver.implicitly_wait(10)
driver.find_element(By.ID, 'username').send_keys(f"{email}")
driver.find_element(By.ID, 'password').send_keys(f"{password}")

# 处理Cookie弹窗
try:
    driver.find_element(By.CSS_SELECTOR, 'button[id="onetrust-pc-btn-handler"]').click()
    driver.find_element(By.CSS_SELECTOR, 'button[class="ot-pc-refuse-all-handler"]').click()
    print('跳过Cookie弹窗')
except:
    print('无Cookie弹窗')

# 点击登录按钮
driver.find_element(By.CSS_SELECTOR, 'button[id="login-submit-btn"]').click()

# 等待跳转至创建页面
WebDriverWait(driver, 30).until(EC.url_contains("create.kahoot.it"))

# 处理引导弹窗
try:
    driver.find_element(By.CSS_SELECTOR, 'button[aria-label="Next"]').click()
    driver.find_element(By.CSS_SELECTOR, 'button[aria-label="Next"]').click()
    driver.find_element(By.CSS_SELECTOR, 'a[class="btn btn--text"]').click()
    print('跳过引导弹窗')
except:
    print('无引导弹窗')

# 进入库页面
driver.implicitly_wait(10)
driver.find_element(By.CSS_SELECTOR, 'a[data-functional-selector="side-bar-link__library"]').click()

# 创建新文件夹
driver.find_element(By.CSS_SELECTOR, 'button[data-functional-selector="library_side-bar_create-folder"]').click()
driver.find_element(By.CSS_SELECTOR, 'input[placeholder="New folder"]').send_keys(f'{folder_name}', Keys.ENTER)

# 拆分数据为多个测验
quizzes = []
for i in range(0, len(df), quiz_question_length):
    quizzes.append(df.iloc[i:i + quiz_question_length])

# 批量创建测验
for quiz in quizzes:
    # 创建新Kahoot
    driver.implicitly_wait(10)
    driver.find_element(By.CSS_SELECTOR,
                        'button[class="button__Button-sc-c6mvr2-0 iwRYhY create-button__PrimaryButton-sc-1wmq7f8-0 jaZrfx"]').click()
    driver.find_element(By.CSS_SELECTOR, 'button[aria-label="Create new Kahoot."]').click()

    # 选择空白模板
    driver.find_element(By.CSS_SELECTOR, 'button[class="styles__FlowOptionInnerContainer-sc-hcxgxq-2 gmFgAG"]').click()
    driver.find_element(By.CSS_SELECTOR, 'button[class="flat-button__FlatButton-sc-6uljam-0 iEWtrJ"]').click()

    # 关闭主题面板
    driver.find_element(By.CSS_SELECTOR, 'button[aria-label="Close Themes panel"]').click()

    # 逐个添加填空题
    for index, row in quiz.iterrows():
        # 等待并点击「添加题目」按钮
        add_question_btn = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable((By.CSS_SELECTOR, 'button[data-functional-selector="add-question-button"]'))
        )
        add_question_btn.click()

        # 等待并点击「填空题」类型按钮
        answer_type_btn = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable((By.CSS_SELECTOR, 'button[data-functional-selector="create-button__open-ended"]'))
        )
        answer_type_btn.click()

        # 获取题目和答案
        question_input = row['Question']
        answer_input = row['Answer']

        # 等待题目输入框可交互并输入内容
        question_text = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable((By.CSS_SELECTOR, 'p[data-placeholder="Start typing your question"]'))
        )
        question_text.send_keys(question_input)

        # 等待答案输入框可交互并输入内容
        answer_text = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable((By.CSS_SELECTOR, 'input[placeholder="Type an answer"]'))
        )
        answer_text.send_keys(answer_input)

测试用DataFrame示例

df = pd.DataFrame({
    'Question': ['la explosión', 'el apellido', 'la conferencia', 'la intensidad', 'el paquete'],
    'Answer': ['explosion', 'last name', 'conference', 'intensity', 'package']
})

内容的提问来源于stack exchange,提问作者Richmond Nguyen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 18:15:03