在无限循环期间更新kivy解析器应用程序中的标签



我想为我的selenium解析器应用程序添加gui,选择了Kivy,但它不会更新标签文本。我找到了StringProperty解决方案和Threading来解决无限循环的问题,但没有成功。我需要这样的循环,因为应用程序应该不断地旋转网站页面,搜索用户名,并说明它在哪个页面找到。请检查我的代码并更正我,因为我说错了:D我试着为while循环制作后台线程,为整个kivy应用程序制作前台线程。这是我得到的

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 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)
global browsertab
class MyApp(App):
position = StringProperty('Scan website')
def __init__(self):
super().__init__()
self.label = Label(text = self.position)
self.input_data = TextInput(hint_text = 'Enter username to serach 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)
def on_enter(self, *args):
self.btn_pressed(self)
def btn_pressed(self, *args):
name = self.input_data.text
background = threading.Thread(target=self.scanwebsite(name))
background.start()
def showpos(self, name, page):
self.position = 'User ' + name + ' is currently on page #' + str(page)
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(driver, 3)
browsertab = driver.current_window_handle
try:
if driver.find_element(By.LINK_TEXT, "I ACCEPT"):
driver.find_element(By.LINK_TEXT, "I ACCEPT").click()
except:
pass

while True:
for page in pages:
url = "https://website.com/?page=" + str(page) 
driver.switch_to.window(browsertab)
driver.get(url)
WebDriverWait(driver, 2)
try:
if driver.find_element(By.LINK_TEXT, name.lower()):
self.showpos(name, page)
break
except:
pass
else:
continue
if __name__ == "__main__":
foreground = threading.Thread(target=MyApp().run())
foreground.start()
exit()

代码中的一些问题:

  • 你不能在另一个线程中运行应用程序,它必须在main线程中运行
  • 在python代码中,将Labeltext设置为StringProperty,只使用代码执行时StringProperty的值。如果不添加更多代码进行更新,则不会进行任何更新
  • 代码background = threading.Thread(target=self.scanwebsite(name))实际上在当前线程中运行scanwebsite()方法,然后将其返回值(即None(分配给target参数

如果使用kivy语言定义GUI,则可以利用自动更新,例如更新使用StringPropertyLabel。以下是使用这种方法的代码的修改版本:

import threading
from functools import partial
import numpy as num
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import StringProperty
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)
global browsertab
kv = '''
BoxLayout:
padding: 20
orientation: 'vertical'
Label:
text: app.position
TextInput:
id: input
hint_text: 'Enter username to serach for'
multiline: False
Button:
text: 'Scan'
on_press: app.btn_pressed()
'''

class MyApp(App):
position = StringProperty('Scan website')
def on_enter(self, *args):
self.btn_pressed(self)
def btn_pressed(self, *args):
name = self.root.ids.input.text  # get name by using id set in kv

# use partial to set args for the scanwebsite() method
# set daemon=True to kill this thread when the App quits
background = threading.Thread(target=partial(self.scanwebsite, name), daemon=True)
background.start()
def showpos(self, name, page):
self.position = 'User ' + name + ' is currently on page #' + str(page)
def build(self):
return Builder.load_string(kv)
def scanwebsite(self, name):
with webdriver.Firefox(options=firefox_options) as driver:
driver.get("https://website.com/")
WebDriverWait(driver, 3)
browsertab = driver.current_window_handle
try:
if driver.find_element(By.LINK_TEXT, "I ACCEPT"):
driver.find_element(By.LINK_TEXT, "I ACCEPT").click()
except:
pass
while True:
for page in pages:
url = "https://website.com/?page=" + str(page)
driver.switch_to.window(browsertab)
driver.get(url)
WebDriverWait(driver, 2)
try:
if driver.find_element(By.LINK_TEXT, name.lower()):
self.showpos(name, page)
break
except:
pass
else:
continue

if __name__ == "__main__":
MyApp().run()  # do not use a thread here

最新更新