import tkinter
import requests
import threading
from bs4 import BeautifulSoup
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36', 'Referer':'https://wallstreetcn.com/live/global' }
def getprice(url):
html=requests.get(url, headers=headers).text
soup=BeautifulSoup(html,'lxml')
price=soup.find('div',class_='price lt').get_text() #<div class="price lt" data-v-13b642d2="">12438.00</div>
return price
while True:
g=getprice('https://wallstreetcn.com/markets/indices/GER30INDEX')
top = tkinter.Tk()
label = tkinter.Label(top,text=g)
label.pack()
tkinter.mainloop()
top.wm_attributes('-topmost',1)
1
jin6220 OP 不太会 md 格式 找了个网站贴了代码进去 然后所见所得修改了下贴进来 确实是好看了点
昨天试了大半天 看了多进程 多线程 锁 队列 但是还是写不出来 |
2
icedx 2017-04-29 08:19:00 +08:00 via Android
印象里不能用 while true
会阻塞界面的绘制 |
3
jin6220 OP @icedx 哦 那是不是把 getprice 放进多线程里?通过队列取出这个返回值,但是昨天试了一天还是不成功;或者其他方法怎么实现呐
|
4
icedx 2017-04-29 08:25:12 +08:00 via Android
对的
|
5
zjqzxc 2017-04-29 08:49:48 +08:00
当然是多线程,在线程中完成对主界面的更新工作
getprice 操作放进新线程里,每次需要绘制的时候执行一次,修改对应的 label 的 text 属性即可 |
6
jin6220 OP import tkinter
import requests import threading from bs4 import BeautifulSoup import queue #import Queue headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36', 'Referer':'https://wallstreetcn.com/live/global' } def getprice(url): html=requests.get(url, headers=headers).text soup=BeautifulSoup(html,'lxml') price=soup.find('div',class_='price lt').get_text() #<div class="price lt" data-v-13b642d2="">12438.00</div> q.put(price) return price while True: q = queue.Queue() p = threading.Thread(target=getprice,args=('https://wallstreetcn.com/markets/indices/GER30INDEX',)) p.start() qprice=q.get() top = tkinter.Tk() label = tkinter.Label(top,text=qprice) label.pack() tkinter.mainloop() top.wm_attributes('-topmost',1) 写了个 不知道这个爬虫网页价格放到 tk 里随价格变化而变化,实现了没。 |
7
jin6220 OP @zjqzxc 您意思是绘制的 tk 也放进一个线程了吗? 6 楼那个怎么样?刚才试了可以显示价格,不知道堵塞没,但是功能太简单了。还想实现这些:价格有变化绘制 tk,没变化不用管。
|
8
zjqzxc 2017-04-29 09:05:05 +08:00
from tkinter import *
import threading import time root = Tk() label1 = Label(root,text='0') label1.pack() def getPrice(): return time.time() def threadGetPrice(): while(True): label1['text'] = getPrice() time.sleep(1) t = threading.Thread(target=threadGetPrice,args=(),name='thread-refresh') t.setDaemon(True) t.start() root.mainloop() 大概是这么个意思 如果想实现价格变化时绘制(修改 text ),可以在 threadGetPrice()中进行判断 |
9
jin6220 OP while 循环一次:构建队列,获取价格并放进队列,然后取出价格并绘制图形界面。
想实现价格有变化绘制图形,没变化不要管看来有点难度(针对我这种小白哈) 因为每次循环都是一个新的队列一个, 新的价格啊 |
10
zjqzxc 2017-04-29 09:15:03 +08:00
@jin6220 如果只是为了修改界面上的价格,完全没必要使用队列。
简单的思路是,有一个线程,在 while true:中获取最新价格,然后看是否改变了决定要不要更新主界面对应的 label 标签的 text 值;循环最后加一个 time.sleep(1)每次获取操作间隔 1 秒 另外:新建线程的操作不要放在 while 中。。更新操作交给新创建的线程来做 |
11
zjqzxc 2017-04-29 09:25:52 +08:00 1
import time
import tkinter import requests import threading from bs4 import BeautifulSoup headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36', 'Referer':'https://wallstreetcn.com/live/global' } def getPrice(url): (space)html=requests.get(url, headers=headers).text (space)soup=BeautifulSoup(html,'lxml') (space)price=soup.find('div',class_='price lt').get_text() (space)return price root = tkinter.Tk() label1 = tkinter.Label(root,text='init...') label1.pack() def threadGetPrice(): (space)while(True): (space)(space)label1['text'] = getPrice('https://wallstreetcn.com/markets/indices/GER30INDEX') (space)(space)time.sleep(5) t = threading.Thread(target=threadGetPrice,args=(),name='thread-refresh') t.setDaemon(True) t.start() root.mainloop() |
12
jin6220 OP @zjqzxc 嗯请问下 t.setDaemon(True) 这个是不是更新线程的操作,查了下说这是设置守护线程,如果是更新线程的话,为什么 def threadGetPrice()函数下面还要加一句 while True 呐,
|
13
jin6220 OP 感觉到了进程 线程 这里 明显到了 python 的易学难精的地方了。。。
感觉大山来了 当初类 实例之类的马马虎虎地啃下来算是能看懂别人写的代码 但是进程 线程 锁之类的东西 完全看不懂 自猜: 好像搞懂 python 的运行机制才能玩转这些东西了 :) |
15
zjqzxc 2017-04-29 10:17:28 +08:00
@jin6220 这个 setDaemon 的作用并不是让代码循环执行。没有 while true,threadGetPrice()里的代码将只执行一次;
setDaemon(True)的作用:父线程启动了子线程,当父线程结束,子线程跟着同时被 kill; setDaemon(False)的作用:父线程启动了子线程,当父线程结束,会等待子线程结束后,主线程才会结束; 如果把 setDaemon 改为 false,关闭窗体后 threadGetPrice ()继续执行,但此时主窗体已经不存在了,执行更新操作时会报错; 为啥会发生这个,具体原因我也没有确切答案。 猜测可能的原因是,tkinter 窗口的线程并不是手动创建的线程的父线程,关闭 tkinter 窗体的操作并不会等待手动创建的线程结束,所以就有问题了; 表现是:如果 setDaemon ( False ),关闭窗体后进程并不会立刻终止,而是等子线程完成后才会终止。 |