python - Tkinter 中清爽的 BeautifulSoup

标签 python user-interface tkinter beautifulsoup

尝试循环运行我的脚本,以便使用 BeautifulSoup 从网页收集的信息每隔 X 秒刷新一次。这需要在 Tkinter 运行时发生并且需要显示信息。

我目前发现我根本无法循环脚本。这是我的脚本

    import tkinter as tk
    root = tk=Tk()
    root.title('Title')
    from bs4 import BeautifulSoup, Navigable String
    import requests
    import time

    page = requests.get("http://yourpage.com")
    #get info from page

    canvas.create_text(100, 100 text="text")
    #display info

    root.after(100,update)
    root.mainloop()

我尝试放入 while True: 但没有成功。我认为这可能是 root.mainloop() 但我不知道如何解决这个问题,因为如果没有这个,GUI 就不会打开。

编辑

This is my code and it works where it will refresh, however, I don't think this is the proper way of doing it:

import tkinter as tk
root = tk.Tk()
root.title('title')
screen = tk.Canvas(root, width=400, height=600, background='gray15')
screen.grid()
root.iconbitmap(r'C:\\path\to\file.ico')
while True:

    from bs4 import BeautifulSoup, NavigableString
    import requests
    import time
    #SWDL Current
    page = requests.get("https://yourwebpage.com")
    page = requests.get("https://yourwebpage.com/page", cookies=page.cookies)
    soup = BeautifulSoup(page.content, 'html.parser')
    soup.find_all('td')
    yourdata = soup.find_all('td')[12].get_text()

    vara = yourdata[0:1]
    varb = yourdata[1:2]
    varc = yourdata[2:3]
    var1 = int(vara)
    var2 = int(varb)
    var3 = int(varc)

    offsets = (
        (0, 0, 1, 0),  # top
        (1, 0, 1, 1),  # upper right
        (1, 1, 1, 2),  # lower right
        (0, 2, 1, 2),  # bottom
        (0, 1, 0, 2),  # lower left
        (0, 0, 0, 1),  # upper left
        (0, 1, 1, 1),  # middle
    )
    # Segments used for each digit; 0, 1 = off, on.
    digits = (
        (1, 1, 1, 1, 1, 1, 0),  # 0
        (0, 1, 1, 0, 0, 0, 0),  # 1
        (1, 1, 0, 1, 1, 0, 1),  # 2
        (1, 1, 1, 1, 0, 0, 1),  # 3
        (0, 1, 1, 0, 0, 1, 1),  # 4
        (1, 0, 1, 1, 0, 1, 1),  # 5
        (1, 0, 1, 1, 1, 1, 1),  # 6
        (1, 1, 1, 0, 0, 0, 0),  # 7
        (1, 1, 1, 1, 1, 1, 1),  # 8
        (1, 1, 1, 1, 0, 1, 1),  # 9
    )

    if yourdata == 'x':
        class Digit:
            def __init__(self, canvas, x=10, y=10, length=20, width=4):
                self.canvas = canvas
                l = length
                self.segs = []
                canvas.create_line(250, 53, 270, 8, width=3, fill="snow")
                canvas.create_oval(250, 10, 255, 15, outline="snow", fill="snow", width=0)
                canvas.create_oval(265, 46, 270, 51, outline="snow", fill="snow", width=0)
                canvas.create_text(70, 30, text='info', font=('OCR A Extended', '18'), fill='snow')
                for x0, y0, x1, y1 in offsets:
                    self.segs.append(canvas.create_line(
                        x + x0*l, y + y0*l, x + x1*l, y + y1*l,
                        width=width, state = 'hidden', fill='snow'))
            def show(self, num):
                for iid, on in zip(self.segs, digits[num]):
                    self.canvas.itemconfigure(iid, state = 'normal' if on else 'hidden')

        dig = Digit(screen, 160, 10) ##
        dig1 = Digit(screen, 190, 10) ##
        dig2 = Digit(screen, 220, 10) ##
        n = 0
        def update():
            global n
            dig.show(var1)
            dig1.show(var2)
            dig2.show(var3)
            n = (n+1) % 10
            root.after(1000, update)
    else:
        class Digit:
            def __init__(self, canvas, x=10, y=10, length=20, width=4):
                self.canvas = canvas
                l = length
                self.segs = []
                canvas.create_line(220, 53, 240, 8, width=3, fill="snow")
                canvas.create_oval(220, 15, 225, 10, outline="snow", fill="snow", width=0)
                canvas.create_oval(235, 46, 240, 51, outline="snow", fill="snow", width=0)
                canvas.create_text(70, 30, text='info', font=('OCR A Extended', '18'), fill='snow')
                for x0, y0, x1, y1 in offsets:
                    self.segs.append(canvas.create_line(
                        x + x0*l, y + y0*l, x + x1*l, y + y1*l,
                        width=width, state = 'hidden', fill='ghost white'))
            def show(self, num):
                for iid, on in zip(self.segs, digits[num]):
                    self.canvas.itemconfigure(iid, state = 'normal' if on else 'hidden')

        dig = Digit(screen, 160, 10) ##
        dig1 = Digit(screen, 190, 10) ##
        n = 0
        def update():
            global n
            dig.show(var1)
            dig1.show(var2) ## Control what you want to show here , eg (n+1)%10
            n = (n+1) % 10
            root.after(1000, update)
    root.after(1000, update)
    root.update_idletasks()
    root.update()

或者如果有一种方法只更新 beautifulsoup 也可以。

感谢任何帮助

最佳答案

您的示例有点稀疏,我们无法测试。然而,一个简单的解决方案是创建一个可以在您需要的任何时间间隔调用的函数。

这是一个基本示例:

def update_canvas():
    canvas.delete("all")
    canvas.create_text(100, 100, text=data_gathered)
    root.after(100, update_canvas)

update_canvas()

通过在函数中使用 after(),您可以避免阻塞主循环并能够保持持续更新。

编辑:

由于这一行,您的完整代码有点难以测试:

yourdata = soup.find_all('td')[12].get_text()

如果不知 Prop 体的网址,我就无法产生结果。 也就是说,我已经对您的代码进行了一些修改,使其能够更好地与主循环配合使用。我认为应该在某个时候将其全部转换为 OOP,这样就可以避免全局。

import tkinter as tk
from bs4 import BeautifulSoup
import requests


root = tk.Tk()
root.title('title')
screen = tk.Canvas(root, width=400, height=600, background='gray15')
screen.grid()

url_to_request = "https://google.com"
page = requests.get(url_to_request)
soup = BeautifulSoup(page.content, 'html.parser')
soup.find_all('td')
yourdata = soup.find_all('td')[12].get_text()
var1 = int(yourdata[0:1])
var2 = int(yourdata[1:2])
var3 = int(yourdata[2:3])

offsets = (
    (0, 0, 1, 0),  # top
    (1, 0, 1, 1),  # upper right
    (1, 1, 1, 2),  # lower right
    (0, 2, 1, 2),  # bottom
    (0, 1, 0, 2),  # lower left
    (0, 0, 0, 1),  # upper left
    (0, 1, 1, 1),  # middle
    )

digits = (
    (1, 1, 1, 1, 1, 1, 0),  # 0
    (0, 1, 1, 0, 0, 0, 0),  # 1
    (1, 1, 0, 1, 1, 0, 1),  # 2
    (1, 1, 1, 1, 0, 0, 1),  # 3
    (0, 1, 1, 0, 0, 1, 1),  # 4
    (1, 0, 1, 1, 0, 1, 1),  # 5
    (1, 0, 1, 1, 1, 1, 1),  # 6
    (1, 1, 1, 0, 0, 0, 0),  # 7
    (1, 1, 1, 1, 1, 1, 1),  # 8
    (1, 1, 1, 1, 0, 1, 1),  # 9
    )


def update(if_else_var):
    global dig, dig1, dig2, n
    soup = BeautifulSoup(requests.get(url_to_request).content, 'html.parser')
    yourdata = soup.find_all('td')[12].get_text()
    var1 = int(yourdata[0:1])
    var2 = int(yourdata[1:2])
    var3 = int(yourdata[2:3])
    dig.show(var1)
    dig1.show(var2)
    if if_else_var:
        dig2.show(var3)
    n = (n+1) % 10
    root.after(1000, update, if_else_var)

if yourdata == 'x':
    global dig, dig1, dig2, n

    class Digit:
        def __init__(self, canvas, x=10, y=10, length=20, width=4):
            self.canvas = canvas
            canvas.delete('all')
            l = length
            self.segs = []
            canvas.create_line(250, 53, 270, 8, width=3, fill="snow")
            canvas.create_oval(250, 10, 255, 15, outline="snow", fill="snow", width=0)
            canvas.create_oval(265, 46, 270, 51, outline="snow", fill="snow", width=0)
            canvas.create_text(70, 30, text='info', font=('OCR A Extended', '18'), fill='snow')
            for x0, y0, x1, y1 in offsets:
                self.segs.append(canvas.create_line(x + x0*l, y + y0*l, x + x1*l, y + y1*l,
                                                    width=width, state='hidden', fill='snow'))

        def show(self, num):
            for iid, on in zip(self.segs, digits[num]):
                self.canvas.itemconfigure(iid, state='normal' if on else 'hidden')

    dig = Digit(screen, 160, 10)
    dig1 = Digit(screen, 190, 10)
    dig2 = Digit(screen, 220, 10)
    n = 0
    update(True)
else:

    class Digit:
        def __init__(self, canvas, x=10, y=10, length=20, width=4):
            self.canvas = canvas
            canvas.delete('all')
            l = length
            self.segs = []
            canvas.create_line(220, 53, 240, 8, width=3, fill="snow")
            canvas.create_oval(220, 15, 225, 10, outline="snow", fill="snow", width=0)
            canvas.create_oval(235, 46, 240, 51, outline="snow", fill="snow", width=0)
            canvas.create_text(70, 30, text='info', font=('OCR A Extended', '18'), fill='snow')
            for x0, y0, x1, y1 in offsets:
                self.segs.append(canvas.create_line(
                    x + x0*l, y + y0*l, x + x1*l, y + y1*l,
                    width=width, state='hidden', fill='ghost white'))

        def show(self, num):
            for iid, on in zip(self.segs, digits[num]):
                self.canvas.itemconfigure(iid, state='normal' if on else 'hidden')

    dig = Digit(screen, 160, 10)
    dig1 = Digit(screen, 190, 10)
    n = 0
    update(False)

root.mainloop()

关于python - Tkinter 中清爽的 BeautifulSoup,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54011261/

相关文章:

python - 如何用 Pandas 数据框中第一行和相应行之间的列的平均值填充特定值

python - django send_mail() 函数需要几分钟

css - 如何制作:hover more mobile friendly and accessible?

windows - 在 Win32 GUI 应用程序中使用标准输出 : crashes if I don't have a redirect to file in arguments

python - 以 4k (3840*2160) 分辨率缩放 Tkinter GUI?

Python 打印变量时出现 Unicode 错误

python - Coursera ML - 在 python 中实现正则化逻辑回归成本函数

jquery - Kendo Grid 更改事件触发问题(当我单击一行时触发两次)

python - 如何在 tkinter 中使用 grid() 方法在新小部件上创建按钮?

python - Tkinter:调用多线程实例