教你用Python製作一個NBA球員資料查詢小程式

松鼠愛吃餅乾發表於2020-11-09

本文的文字及圖片來源於網路,僅供學習、交流使用,不具有任何商業用途,如有問題請及時聯絡我們以作處理。

以下文章來源於早起Python ,作者投稿君

一、前言

有時將程式碼轉成帶有介面的程式,會極大地方便使用,雖然在網上有很多現成的GUI系統,但是套用別人的程式碼,心裡難免有些尷尬,所以本文將用Python爬蟲結合wxpython模組構造一個NBA爬蟲小軟體

 

 

本文框架構造將分為二個部分講解:

  1. 構建GUI介面
  2. 舉例套用爬蟲框架

主要涉及的Python模組有

  • requests
  • wx
  • pymysql
  • pandas

 

二、GUI介面設計

首先介紹下流程:GUI介面設計講解插入介面背景圖片

設計GUI介面的程式碼思路其實很簡單,首先匯入wx庫

import wx

這裡引用的模組是wxpython模組,建立GUI的模組很多,常見的有PyQt、Tkinter等。這些模組各有各的優缺點,讀者可以翻閱相關資料進行選擇。

class MyFrame(wx.Frame):
    def __init__(self, parent, id):
        wx.Frame.__init__(self, parent, id, 'titlename',size=(400, 300))
        panel = wx.Panel(self)
        self.bt_confirm = wx.Button(panel, label='name1')
        self.bt_confirm.Bind(wx.EVT_BUTTON,self.OnclickSubmit)
        self.bt_cancel = wx.Button(panel, label='name2')
        self.bt_cancel.Bind(wx.EVT_BUTTON,self.OnclickCancel)
        self.InitUI()

定義全域性變數對於初級的GUI來說就是構建一個形式視窗+按鈕佈置,不需要自建一個模組。但對於高階的GUI諸如投資系統而言,全域性變數是尤為重要的,換句話說全域性變數需要放在一個py檔案中初始化。

上述程式碼是建立部分的程式碼,個性化佈局需要新增容器進行設定,稍後會在總程式碼中呈現。


   def InitUI(self):
        """ 點選InitUI,執行方法 """
        
    def OnclickSubmit(self,event):
        """ 繫結OnclickSubmit事件 """

簡單來說就是繫結事件,該事件是你點選對應按鈕產生的效果。這部是整個GUI的核心,如果你在做簽到系統,那麼你就要繫結一個匯入員工名單txt檔案的事件。

if __name__ == '__main__':
    app = wx.App()                      # 初始化
    frame = MyFrame(parent=None,id=-1)   
    frame.Show()                        
    app.MainLoop()                      # 呼叫主迴圈
del app

第四步的基本套路就是如此。

三、舉例實現

以一個簡單的NBA爬蟲系統為例,首先建立皮膚與佈局

class MyFrame(wx.Frame):
    def __init__(self, parent, id):
        wx.Frame.__init__(self, parent, id, 'NBA視覺化',size=(400, 300))
        panel = wx.Panel(self)
        self.bt_confirm = wx.Button(panel, label='合同資訊')
        self.bt_confirm.Bind(wx.EVT_BUTTON,self.OnclickSubmit)
        self.bt_cancel = wx.Button(panel, label='清空')
        self.bt_cancel.Bind(wx.EVT_BUTTON,self.OnclickCancel)
        self.bt_imf = wx.Button(panel, label='視覺化')
        self.bt_imf.Bind(wx.EVT_BUTTON,self.Onclickvisual)
        self.bt_team = wx.Button(panel, label='球隊資訊',pos=(280,20))
        self.bt_team.Bind(wx.EVT_BUTTON,self.Onclickteam)
        self.bt_obtain = wx.Button(panel, label='球員資訊',pos=(20,20))
        self.bt_obtain.Bind(wx.EVT_BUTTON,self.Onclickimfor)
        self.bt_ml = wx.Button(panel, label='得分榜')
        self.bt_ml.Bind(wx.EVT_BUTTON,self.Onclickmql)     
        self.title = wx.StaticText(panel, label="NBA視覺化")
        self.label_user = wx.StaticText(panel, label="球隊名稱")
        self.text_user = wx.TextCtrl(panel, style=wx.TE_LEFT)
        self.label_pwd = wx.StaticText(panel, label="球員名稱")
        self.text_pwd = wx.TextCtrl(panel, style=wx.TE_LEFT)
        self.label_path = wx.StaticText(panel, label="儲存路徑")
        self.text_pathword = wx.TextCtrl(panel, style=wx.TE_LEFT)

然後新增容器,橫向排列

   hsizer_user = wx.BoxSizer(wx.HORIZONTAL)
        hsizer_user.Add(self.label_user, proportion=0, flag=wx.ALL, border=5)
        hsizer_user.Add(self.text_user, proportion=1, flag=wx.ALL, border=5)
        hsizer_pwd = wx.BoxSizer(wx.HORIZONTAL)
        hsizer_pwd.Add(self.label_pwd, proportion=0, flag=wx.ALL, border=5)
        hsizer_pwd.Add(self.text_pwd, proportion=1, flag=wx.ALL, border=5)        
        hsizer_path = wx.BoxSizer(wx.HORIZONTAL)
        hsizer_path.Add(self.label_path, proportion=0, flag=wx.ALL, border=5)
        hsizer_path.Add(self.text_pathword, proportion=1, flag=wx.ALL, border=5)       
        hsizer_button = wx.BoxSizer(wx.HORIZONTAL)
        hsizer_button.Add(self.bt_confirm, proportion=0, flag=wx.ALIGN_CENTER, border=5)
        hsizer_button.Add(self.bt_cancel, proportion=0, flag=wx.ALIGN_CENTER, border=5)
        hsizer_button.Add(self.bt_imf, proportion=0, flag=wx.ALIGN_CENTER, border=5)
        hsizer_button.Add(self.bt_ml, proportion=0, flag=wx.ALIGN_CENTER, border=5)       

接著新增容器,縱向排列

        vsizer_all = wx.BoxSizer(wx.VERTICAL)
        vsizer_all.Add(self.title, proportion=0, flag=wx.BOTTOM | wx.TOP | wx.ALIGN_CENTER,
                        border=15)
        vsizer_all.Add(hsizer_user, proportion=0, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=45)
        vsizer_all.Add(hsizer_pwd, proportion=0, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=45)
        vsizer_all.Add(hsizer_path, proportion=0, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=45)      
        vsizer_all.Add(hsizer_button, proportion=0, flag=wx.ALIGN_CENTER | wx.TOP, border=15)
        panel.SetSizer(vsizer_all)
        self.InitUI()

下一步是事件繫結

    def InitUI(self):
        """ 點選使用說明按鈕,執行方法 """        
    def OnQuit1(self,e):
        """ 輸入注意事項 """
    def OnclickSubmit(self,event):
        """ 點選合同資訊按鈕,執行方法 """
    def Onclickvisual(self,event):
        """ 點選視覺化按鈕,執行方法 """
    def OnclickCancel(self,event):
        """ 點選清空按鈕,執行方法 """ 
    def Onclickimfor(self,event):
        """ 點選球員名稱按鈕,執行方法 """ 
    def Onclickteam(self,event):
        """ 點選球隊名稱按鈕,執行方法 """ 
    def Onclickmql(self,event):
        """ 點選得分榜按鈕,執行方法 """

這裡的事件處理不是很難,讀者可以自己嘗試創新,最後執行指令碼

if __name__ == '__main__':
    app = wx.App()                      # 初始化
    frame = MyFrame(parent=None,id=-1)  # 例項MyFrame類,並傳遞引數 
    frame.Show()                        # 顯示視窗
    app.MainLoop()                      # 呼叫主迴圈方法

效果如圖

 

補充:插入背景圖片

想要構造一個個性化系統,最不能缺的就是將介面背景換成自己想要的。這裡我選擇用一張老科的圖片。

相信有的讀者會覺得一個獨立的單機的GUI軟體會更適合自己,我也恰恰如此,因此,在設定背景圖片中於之後的GUI需要進行打包,故需要將指定的二進位制圖片base64化,轉換後存入py檔案後以import為媒介才能打包。二進位制程式碼轉換如下:

import base64
with open("name.jpg","rb") as f:  
    base64_str = base64.b64encode(f.read())  
with open('%s.py' % picture_name.replace('.', '_'), 'w+') as f1:
    f1.write(base64_str)
    f1.close()  

此時可以得到有base64編碼的py檔案,而後在程式碼中進行引用。由於打包不能打包圖片,故這裡稍微複雜的實現“引用指定圖片的base64編碼——建立圖片——插入背景圖片”功能!

最後再稍加修飾將文字底色改為透明。編寫這段程式碼的框架非常固定,所以我借鑑了大神們的程式碼,基本程式碼框架如下:

#這裡需要在主事件中插入兩句話
panel.Bind(wx.EVT_ERASE_BACKGROUND,self.OnEraseBack)
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBack)
#引用編碼並建立圖片
from bg_png import img as bg    
def pic(picPath,picName):
    tmp = open(picPath, 'wb')        
    tmp.write(base64.b64decode(picName))   
    tmp.close()      
pic('bg.png',bg)
#插入圖片(子事件 有縮排)
    def OnEraseBack(self,event):
        '''加入圖片背景'''
        try :
            dc = event.GetDC()
            if not dc:
                dc = wx.ClientDC(self)
                rect = self.GetUpdateRegion().GetBox()
                dc.SetClippingRect(rect)
            dc.Clear()
            bmp = wx.Bitmap(nowpath+r'\bg.png')
            dc.DrawBitmap(bmp, -500, -100)
        except :
            pass
#將文字底色改為透明
#第一步:將主事件中wx.StaticText全部換成TransparentStaticText
#第二步:重現StaticText控制元件
class TransparentStaticText(wx.StaticText):
    def __init__(self, parent, id=wx.ID_ANY, label='', pos=wx.DefaultPosition, size=wx.DefaultSize,
                 style=wx.TRANSPARENT_WINDOW, name='TransparentStaticText'):
        wx.StaticText.__init__(self, parent, id, label, pos, size, style, name)
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Bind(wx.EVT_ERASE_BACKGROUND, lambda event: None)
        self.Bind(wx.EVT_SIZE, self.OnSize)
    def OnPaint(self, event):
        bdc = wx.PaintDC(self)
        dc = wx.GCDC(bdc)
        font_face = self.GetFont()
        font_color = self.GetForegroundColour()
        dc.SetFont(font_face)
        dc.SetTextForeground(font_color)
        dc.DrawText(self.GetLabel(), 0, 0)
    def OnSize(self, event):
        self.Refresh()
        event.Skip()

最終效果如圖:

 

注意如果你想打包的話,需要程式碼中中引入下面三個模組:

import six
import packaging
import packaging.version
import packaging.specifiers
import packaging.requirements

相關文章