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

Kivy开发Selenium解析器时无限循环中无法更新Label如何解决

问题原因及修复点

  • 线程创建参数错误:你创建后台线程时直接调用了self.scanwebsite(name),会导致函数直接在主线程执行阻塞界面,应该传入函数引用和单独的参数
  • Kivy UI更新限制:所有UI相关的修改必须在主线程执行,后台线程直接修改StringProperty不会触发UI刷新,需要用Clock.schedule_once调度到主线程执行
  • Label未绑定属性:你初始化Label时仅赋值了初始text,没有和position属性绑定,属性更新后Label不会自动同步文本
  • Kivy主线程错误:Kivy的主渲染循环必须运行在主线程,不能单独开线程运行App.run()

修正后完整代码

import threading
import numpy as num

from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
from kivy.clock import Clock

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait

pages = num.arange(1, 70, 1)
firefox_options = webdriver.FirefoxOptions()
firefox_options.set_preference("permissions.default.image", 2)

class MyApp(App):
    position = StringProperty('Scan website')
    def __init__(self):
        super().__init__()
        self.label = Label(text = self.position)
        # 绑定position属性变化自动更新Label文本
        self.bind(position=lambda inst, val: setattr(self.label, 'text', val))
        self.input_data = TextInput(hint_text = 'Enter username to search for', multiline = False)
        self.input_data.bind(on_text_validate = self.on_enter)
        self.btn = Button(text = 'Scan')
        self.btn.bind(on_press = self.btn_pressed)
        # 扫描状态标记避免重复启动线程
        self.is_scanning = False

    def on_enter(self, *args):
        self.btn_pressed(self)

    def btn_pressed(self, *args):
        if self.is_scanning:
            return
        name = self.input_data.text.strip()
        if not name:
            return
        # 正确创建线程:传入函数引用,参数放在args元组中
        background = threading.Thread(target=self.scanwebsite, args=(name,), daemon=True)
        background.start()
        self.is_scanning = True

    # UI更新方法包装,调度到主线程执行
    def showpos(self, name, page):
        def update(_):
            self.position = f'User {name} is currently on page #{page}'
        Clock.schedule_once(update, 0)

    def build(self):
        box = BoxLayout(padding=20, orientation = 'vertical')
        box.add_widget(self.label)
        box.add_widget(self.input_data)
        box.add_widget(self.btn)
        return box

    def scanwebsite(self, name):
        with webdriver.Firefox(options=firefox_options) as driver:
            driver.get("https://website.com/")
            # 修正WebDriverWait用法,等待页面加载完成
            WebDriverWait(driver, 3).until(lambda d: d.execute_script('return document.readyState') == 'complete')
            browsertab = driver.current_window_handle
            try:
                accept_btn = driver.find_element(By.LINK_TEXT, "I ACCEPT")
                accept_btn.click()
            except:
                pass
            
            while True:
                for page in pages:
                    url = f"https://website.com/?page={page}" 
                    driver.switch_to.window(browsertab)
                    driver.get(url)
                    WebDriverWait(driver, 2).until(lambda d: d.execute_script('return document.readyState') == 'complete')
                    try:
                        driver.find_element(By.LINK_TEXT, name.lower())
                        self.showpos(name, page)
                        break
                    except:
                        pass
if __name__ == "__main__":
    # Kivy主循环必须运行在主线程,无需额外开线程
    MyApp().run()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 08:06:05