Python+Tkinter制作股票數(shù)據(jù)抓取小程序
在前面的文章中,我們一起學習了如何通過 Python 抓取東方財富網(wǎng)的實時股票數(shù)據(jù),鏈接如下
今天我們就在這個基礎(chǔ)上,實現(xiàn)一個 Tkinter GUI 程序,完成無代碼股票抓取!
首先對于 Tkinter 相信大家都是比較了解的,如果有小伙伴對于 Tkinter 的相關(guān)用法不是特別熟悉的話,可以看如下文章
首先我們先看一下 GUI 程序的最終效果

該程序共分三個區(qū)域:
- 個股查詢:用于查詢某只股票的數(shù)據(jù),可以查詢1天或者多天數(shù)據(jù)
- 批量查詢:查詢某個交易所所有股票的數(shù)據(jù)
- 日志區(qū)域:打印抓取信息
下面我們就來看看該如何從頭完成這個 GUI 程序
程序布局
首先就是程序布局,這里我們使用了 ttkbootstrap 庫來美化整體程序
程序初始化部分
import?ttkbootstrap?as?ttk
from?ttkbootstrap.constants?import?*
import?tkinter.messagebox?as?messbox
class?MainCreator(ttk.Window):
????def?__init__(self):
????????super().__init__("股票抓取工具",?themename="solar",?resizable=(False,?False))
????????self.configure_frame?=?ttk.Frame(self,?padding=(10,?10,?5,?10))
????????self.configure_frame.pack(side=LEFT,?fill=BOTH,?expand=YES)
????????self.demo_frame?=?ttk.Frame(self,?padding=(5,?10,?10,?10))
????????self.demo_frame.pack(side=LEFT,?fill=BOTH,?expand=YES)
程序布局部分
????def?create_frame(self):
????????"""Create?all?the?frame?widgets"""
????????container?=?ttk.Frame(self)
????????container.pack(side=LEFT,?fill=BOTH,?expand=YES,?padx=5)
????????color_group?=?ttk.Labelframe(
????????????master=container,?text="個股查詢",?padding=10
????????)
????????color_group.pack(fill=X,?side=TOP)
????????en_command?=?super().register(self.en_validate)
????????self.en0?=?ttk.Entry(color_group,?width=5,?text='',?bootstyle='warning',
?????????????????????????????validate='key',?validatecommand=(en_command,?'%P'))
????????self.en0.insert('0',?1)
????????self.en0.config(state=DISABLED)
????????...
總體上來說,我們所有的組件都是從 ttk 當中實例化的,也就是直接復用了庫 ttkbootstrap 的相關(guān)美化功能,使得我們的程序看起來更加高級美觀
抓取與保存功能
下面我們編寫股票抓取代碼和對應的保存代碼
股票抓取
def?get_A_mins(code):
????if?code.startswith("3")?or?code.startswith("0"):
????????url?=?shang_A_url.replace("%s",?code)
????elif?code.startswith("6"):
????????url?=?shen_A_url.replace("%s",?code)
????else:
????????return?False
????res?=?requests.get(url)
????result?=?res.text.split("cb_1659146437934_51841953")[1].split("(")[1].split(");")[0]
????result_json?=?json.loads(result)
????stock_data?=?result_json['data']
????return?stock_data
def?get_A_days(code):
????if?code.startswith("3")?or?code.startswith("0"):
????????url?=?shang_A_days.replace("%s",?code)
????elif?code.startswith("6"):
????????url?=?shen_A_days.replace("%s",?code)
????else:
????????return?False
????res?=?requests.get(url)
????result?=?res.text.split("cb_1659171393020_15037673")[1].split("(")[1].split(");")[0]
????result_json?=?json.loads(result)
????stock_data?=?result_json['data']
????return?stock_data
def?get_hsj(date):
????total_data?=?[]
????try:
????????for?i?in?range(1,?5):
????????????res?=?requests.get(hsj_url.replace("%s",?str(i)))
????????????result?=?res.text.split("jQuery112402508937289440778_1658838703304")[1].split("(")[1].split(");")[0]
????????????result_json?=?json.loads(result)
????????????stock_data?=?result_json['data']
????????????if?stock_data:
????????????????total_data.append(stock_data)
????????????????saveFunc.save_data_hsj(stock_data['diff'],?date)
????????????else:
????????????????return?total_data
????????return?total_data
????except?Exception?as?e:
????????return?False
def?get_Center():
????total_data?=?[]
????for?i?in?range(1,?20):
????????res?=?requests.get(center_url.replace("%s",?str(i)))
????????result?=?res.text.split("jQuery112404177389105264733_1659176039486")[1].split("(")[1].split(");")[0]
????????result_json?=?json.loads(result)
????????center_data?=?result_json['data']
????????if?center_data:
????????????total_data.append(center_data)
????????else:
????????????return?total_data
def?get_shang_A():
????pass
def?get_shen_A():
????pass
def?get_bei_A():
????pass
股票代碼分為上交所,深交所和北交所以及大盤行情數(shù)據(jù),所以我們分別編寫函數(shù)進行處理
數(shù)據(jù)保存
import?os
def?save_data_mins(data,?date):
????Code?=?data['code']
????Name?=?data['name']
????if?not?os.path.exists(r"stock_data_%s_%s_%s_mins.csv"?%?(Code,?Name,?date)):
????????with?open("stock_data_%s_%s_%s_mins.csv"?%?(Code,?Name,?date),?"a+",?encoding='utf-8')?as?f:
????????????f.write("時間,最新價,成交量(手),成交額\n")
????????????for?i?in?data['trends']:
????????????????i_list?=?i.split(",")
????????????????time?=?i_list[0]
????????????????price?=?i_list[2]
????????????????mount?=?i_list[5]
????????????????count?=?i_list[6]
????????????????row?=?'{},{},{},{}'.format(
????????????????????time,price,mount,count)
????????????????f.write(row)
????????????????f.write('\n')
????else:
????????...
def?save_data_days(data,?days):
????print(days)
????Code?=?data['code']
????Name?=?data['name']
????if?not?os.path.exists(r"stock_data_%s_%s_days.csv"?%?(Code,?Name)):
????????with?open("stock_data_%s_%s_days.csv"?%?(Code,?Name),?"a+",?encoding='utf-8')?as?f:
????????????f.write("時間,開盤價,收盤價,最高價,最低價,成交量(手),成交額,振幅,漲跌幅,漲跌額,換手率\n")
????????????for?i?in?data["klines"][::-1][:int(days)]:
????????????????i_list?=?i.split(",")
????????????????time?=?i_list[0]
????????????????Open?=?i_list[1]
????????????????close?=?i_list[2]
????????????????heigh?=?i_list[3]
????????????????low?=?i_list[4]
????????????????mount?=?i_list[5]
????????????????count?=?i_list[6]
????????????????amplitude?=?i_list[7]
????????????????changePercent?=?i_list[8]
????????????????change?=?i_list[9]
????????????????turnoverRate?=?i_list[10]
????????????????row?=?'{},{},{},{},{},{},{},{},{},{},{}'.format(
????????????????????time,Open,close,heigh,low,mount,count,amplitude,changePercent,change,turnoverRate)
????????????????f.write(row)
????????????????f.write('\n')
????else:
????????...
def?save_data_hsj(data,?date):
????if?not?os.path.exists(r'stock_data_%s.csv'?%?date):
????????with?open("stock_data_%s.csv"?%?date,?"a+",?encoding='utf-8')?as?f:
????????????f.write("股票代碼,股票名稱,最新價,漲跌幅,漲跌額,成交量(手),成交額,振幅,換手率,市盈率,量比,最高,最低,今開,昨收,市凈率\n")
????????????for?i?in?data:
????????????????Code?=?i["f12"]
????????????????Name?=?i["f14"]
????????????????Close?=?i['f2']
????????????????ChangePercent?=?i["f3"]
????????????????Change?=?i['f4']
????????????????Volume?=?i['f5']
????????????????Amount?=?i['f6']
????????????????Amplitude?=?i['f7']
????????????????TurnoverRate?=?i['f8']
????????????????PERation?=?i['f9']
????????????????VolumeRate?=?i['f10']
????????????????Hign?=?i['f15']
????????????????Low?=?i['f16']
????????????????Open?=?i['f17']
????????????????PreviousClose?=?i['f18']
????????????????PB?=?i['f22']
????????????????row?=?'{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{}'.format(
????????????????????Code,Name,Close,ChangePercent,Change,Volume,Amount,Amplitude,
????????????????????TurnoverRate,PERation,VolumeRate,Hign,Low,Open,PreviousClose,PB)
????????????????f.write(row)
????????????????f.write('\n')
????else:
????????...
def?save_data_center():
????pass
def?save_data_shang_A():
????pass
添加功能
接下來就是為布局好的 GUI 程序添加各種響應功能
個股查詢按鈕
為個股查詢的抓取按鈕綁定方法catch
self.bt?=?ttk.Button(color_group,?text='抓取',?bootstyle='success',?command=self.catch)
方法catch的定義如下
????def?catch(self):
????????self.txt.yview_moveto(1)
????????now?=?datetime.datetime.now().strftime('%Y-%m-%d?%H:%M:%S')
????????day?=?datetime.datetime.now().strftime('%Y-%m-%d')
????????if?self.cbvar.get()?==?1:
????????????catch_day?=?self.en0.get()
????????????if?self.en.get():
????????????????code?=?self.en.get()
????????????????result?=?catchFunc.get_A_days(code)
????????????????if?result:
????????????????????saveFunc.save_data_days(result,?catch_day)
????????????????????self.txt.insert(ttk.INSERT,?"抓取股票%s成功?%s"?%?(code,?now))
????????????????????self.txt.insert(ttk.INSERT,?"\n")
????????????????????self.txt.update()
????????????????????self.txt.yview_moveto(1)
????????????????else:
????????????????????print("股票代碼錯誤")
????????????????????messbox.showerror("股票代碼錯誤",?"請輸入正確的股票代碼!")
????????????else:
????????????????print("請輸入股票代碼")
????????????????messbox.showerror("股票代碼為空",?"請輸入股票代碼!")
????????else:
????????...
批量查詢開關(guān)
對于批量查詢,我們是通過一個多選框開關(guān)控制的
self.cb_batch?=?ttk.Checkbutton(cr_group,?text="開啟批量",?variable=self.cbvar1,?command=self.cb_button)
綁定的方法如下
????def?cb_button(self): ????????if?self.cbvar1.get()?==?1: ????????????self.bt_batch.config(state=NORMAL) ????????else: ????????????self.bt_batch.config(state=DISABLED)
以上就是Python+Tkinter制作股票數(shù)據(jù)抓取小程序的詳細內(nèi)容,更多關(guān)于Python Tkinter股票數(shù)據(jù)抓取的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
深入討論Python函數(shù)的參數(shù)的默認值所引發(fā)的問題的原因
這篇文章主要介紹了深入討論Python函數(shù)的參數(shù)的默認值所引發(fā)的問題的原因,利用了Python解釋器在內(nèi)存地址分配中的過程解釋了參數(shù)默認值帶來陷阱的原因,需要的朋友可以參考下2015-03-03
Python實現(xiàn)求解斐波那契第n項的解法(包括矩陣乘法+快速冪)
這篇文章主要介紹怎么使用Python求解斐波那契第n項,方法多樣,邏輯清晰,代碼簡單詳細,有這方面需要的朋友可以參考下2021-04-04
python threading和multiprocessing模塊基本用法實例分析
這篇文章主要介紹了python threading和multiprocessing模塊基本用法,結(jié)合實例形式詳細分析了Python中threading和multiprocessing模塊基本概念、功能、使用方法及相關(guān)操作注意事項,需要的朋友可以參考下2019-07-07
python爬取股票最新數(shù)據(jù)并用excel繪制樹狀圖的示例
這篇文章主要介紹了python爬取股票最新數(shù)據(jù)并用excel繪制樹狀圖的示例,幫助大家更好的理解和學習使用python,感興趣的朋友可以了解下2021-03-03

