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
相关产品推荐
相关产品推荐

