обновление метки tkinter при запуске другого l oop - PullRequest
3 голосов
/ 04 апреля 2020
import tkinter as tk
from tkinter import messagebox
import re,sys
from urllib.parse import urlparse
import requests,time
from bs4 import BeautifulSoup
class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("Quotes Scraper v1")
        self.geometry("400x250")
        button = tk.Button(self, text="Collect Links",bd=3, 
            activebackground="grey90",command=self.start_collecting)
        button.place(x=130,y=120)

    def start_collecting(self):
        url = "http://quotes.toscrape.com/"
        res=requests.get(url)
        is res.status_code!=200:
            sys.exit('Check Internet')
        self.clean_screen_plus()
        quotes = []
        while True:
            soup = BeautifulSoup(res.text,'lxml')
            self.update_status()
            quotes+=[i.span.text.strip() for i in soup.findAll('div',{'class':'quote'})]
            try:
                next_page = 'http://quotes.toscrape.com/'+ soup.find('li',{'class':'next'}).a['href']
                time.sleep(5)
                res = requests.get(next_page)
            except AttributeError:
                break
        self.destroy()

    def clean_screen_plus(self,):
        for widget in self.winfo_children():
            widget.destroy()
        self.geometry("300x100")
        self.resizable(False, False)
        self.status = tk.Label(self, text="Collecting")
        self.status.grid()
        self.update_idletasks()

    def update_status(self):

        current_status = self.status["text"]
        if current_status.endswith("..."): 
            current_status = "Collecting"

        else: 
            current_status += "."

        # Update the message
        self.status["text"] = current_status
        self.update_idletasks()
        self.after(1000, update_status) #updates every 1 sec
        print(current_status)
App().mainloop()

Здравствуйте, у меня есть этот код, Как я могу обновлять ярлык tkinter, пока while l oop работает, т.е. я хочу, чтобы статус менялся каждую секунду, чтобы обновлять статус независимо от того, где я нахожусь в while l oop.

ожидаемый результат на tkinter равен Collecting.\n {len(quotes)}, затем Collecting.. {len(quotes)} ... до тех пор, пока while l oop не закончится, а затем просто self.destroy()

1 Ответ

3 голосов
/ 04 апреля 2020

Вы должны использовать поток, чтобы удалить страницу, иначе она заблокирует ее.

Этот код сработал для меня, (хотя нужно потратить некоторое время, я добавил аннотацию в свой код):

import tkinter as tk
from tkinter import messagebox
import re,sys
from urllib.parse import urlparse
import requests,time
from bs4 import BeautifulSoup
import threading

class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("Quotes Scraper v1")
        self.geometry("400x250")
        button = tk.Button(self, text="Collect Links",bd=3,
            activebackground="grey90",command=self.start_thread) # start a thread instead of starting scrap the page.
        button.place(x=130,y=120)

    def start_thread(self):
        threading.Thread(target=self.start_collecting).start() # create a thread to scrap a page in the background

    def start_collecting(self): # this is your work.
        url = "http://quotes.toscrape.com/"
        res = requests.get(url)
        if res.status_code != 200:
            sys.exit('Check Internet')

        self.clean_screen_plus()
        quotes = []
        while True:
            soup = BeautifulSoup(res.text, 'lxml')
            self.update_status()
            quotes += [i.span.text.strip() for i in soup.findAll('div', {'class': 'quote'})]
            try:
                next_page = 'http://quotes.toscrape.com/' + soup.find('li', {'class': 'next'}).a['href']
                time.sleep(5)
                res = requests.get(next_page)
            except AttributeError:
                break
        self.destroy()

    def clean_screen_plus(self):
        for widget in self.winfo_children():
            widget.destroy()
        self.geometry("300x100")
        self.resizable(False, False)
        self.status = tk.Label(self, text="Collecting")
        self.status.grid()

    def update_status(self):

        current_status = self.status["text"]
        if current_status.endswith("..."):
            current_status = "Collecting"

        else:
            current_status += "."

        # Update the message
        self.status["text"] = current_status
        self.update_idletasks()
        self.after(1000, self.update_status) #updates every 1 sec
        print(current_status)
App().mainloop()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...