Python 的標準模組庫 (standard library) 具有非常豐富的內容,整理官網提供的 Library Reference ,細數有以下分類
- 內建函數 (function) 、常數 (constant) 、型態 (type) 、例外 (exception)
- 文字處理
- 二進位資料處理
- 額外的資料型態
- 數字及數學相關
- 函數程式設計
- 檔案及目錄存取
- 資料保存及資料庫
- 資料壓縮
- 檔案格式
- 密碼處理
- 作業系統相關
- 並時處理
- 網路通訊相關
- 網路資料處理
- 格式化文件處理
- 網路協定相關
- 多媒體處理
- 國際化文字相關
- 程式框架
- 圖形介面
- 發展工具
- 除錯工具
- 發布工具
- 執行期間處理
- 客製化 Python 直譯器
- 模組工具
- Python 語言處理
- 格式化輸出處理
- MS-Windows 特定處理
- UNIX 特定處理
功能非常多,除了新進發展出的手機 App 外,幾乎想開發什麼都已經囊括在標組模組庫中了。像是直接用 Python 把自己電腦設定為簡單的伺服器 (server)
$ python3 -m http.server |
Serving HTTP on 0.0.0.0 port 8000 ... |
這樣在瀏覽器中輸入網址 http://127.0.0.1:8000 ,就會自動尋找啟動目錄下的 index.html ,如下
我們也可以寫個簡單版本的 HTML 解譯器來解析 HTML 文件,例如以下的 demo.py
001 | from html.parser import HTMLParser |
002 | |
003 | document = """<html> |
004 | <head> |
005 | <title>My Home Page</title> |
006 | </head> |
007 | <body> |
008 | <p>Hello! Welcome!</p> |
009 | </body> |
010 | """ |
011 | |
012 | class TitleParser(HTMLParser): |
013 | def __init__(self): |
014 | self.handledtags=['title'] |
015 | self.processing=None |
016 | HTMLParser.__init__(self) |
017 | |
018 | def handle_starttag(self, tag, attrs): |
019 | if tag in self.handledtags: |
020 | self.data='' |
021 | self.processing=tag |
022 | |
023 | def handle_data(self, data): |
024 | if self.processing: |
025 | self.data+=data |
026 | |
027 | def handle_endtag(self, tag): |
028 | if tag==self.processing: |
029 | self.processing=None |
030 | |
031 | def gettitle(self): |
032 | return self.data |
033 | |
034 | if __name__ == '__main__': |
035 | tp=TitleParser() |
036 | tp.feed(document) |
037 | print(tp.gettitle()) |
此處的例子採用 Python 3 。
TitleParser 繼承自 HTMLParser ,而 handle_starttag() 、 handle_data() 、 handle_endtag() 都是來自 HTMLParser
012 | class TitleParser(HTMLParser): |
handle_starttag() 處理遇到的開始標籤,這裡把標籤名稱都儲存在屬性 handledtags 之中,由於只有一個 'title' ,所以只會處理 <title> 標籤
018 | def handle_starttag(self, tag, attrs): |
019 | if tag in self.handledtags: |
020 | self.data='' |
021 | self.processing=tag |
handle_data() 處理標籤內的資料,參數 data 就是標籤內的文字,這裡把標籤內的文字儲存到屬性 data 內
023 | def handle_data(self, data): |
024 | if self.processing: |
025 | self.data+=data |
至於 handle_endtag() 則是處理遇到結束標籤的情況
027 | def handle_endtag(self, tag): |
028 | if tag==self.processing: |
029 | self.processing=None |
測試程式碼的部分是呼叫 feed() ,然後把 HTML 文件當參數給 TitleParser 解析, feed() 會依 HTML 文件內標籤的順序依序處理
036 | tp.feed(document) |
簡單說, TitleParser 就是取得 HTML 文件的標題,然後把標題內容儲存在屬性 (attribute) data 中,此例用把 HTML 文件放在字串 (string) 來測試,執行結果如下
$ python3 demo.py |
My Home Page |
$ |
可是命令列對一般使用者不是很友善,這點我們倒是可以利用標準模組庫中內建的 tkinter 替 TitleParser 設計 GUI , tkinter 是 Python 連結到 Tk 的模組 (module) , Tk 則是跨平台、輕量化、開放原始碼的 GUI 工具。
大部份的 GUI 框架都是先做出排版 (layout) ,這排版就是設定版面中放入小工具 (widget) 的模式,例如格子的模式,就得設定每個小工具要放在哪個格子,最後就是設定小工具跟使用者互動的事件 (event) ,例如使用者按了按鈕後,程式要如何做出回應。
tkinter 的概念大同小異,我們打算設計 SimpleBrowser 類別,這個類別繼承自 tkinter 中的 Frame ,也就是 GUI 中的視窗,然後在這個視窗做出可以解析網址取出標題列的功能,全部程式如下
001 | from tkinter import * |
002 | from tkinter.ttk import * |
003 | from urllib.request import urlopen |
004 | |
005 | from demo import TitleParser |
006 | |
007 | class SimpleBroswer(Frame): |
008 | def __init__(self, master=None): |
009 | Frame.__init__(self, master) |
010 | self.grid() |
011 | self.createWidgets() |
012 | self.address="" |
013 | self.data=None |
014 | |
015 | def createWidgets(self): |
016 | self.sitebar=Entry(self) |
017 | self.sitebar["width"]=40 |
018 | self.sitebar.grid(row=0, column=0) |
019 | |
020 | self.gobutton=Button(self) |
021 | self.gobutton["text"]="Go" |
022 | self.gobutton["width"]=5 |
023 | self.gobutton.grid(row=0, column=1) |
024 | self.gobutton["command"]=self.go |
025 | |
026 | self.display=Text(self) |
027 | self.display["width"]=50 |
028 | self.display["height"]=4 |
029 | self.display.grid(row=1, column=0, |
030 | columnspan=2) |
031 | |
032 | def go(self): |
033 | self.address=self.sitebar.get() |
034 | self.data=urlopen(self.address) |
035 | web=TitleParser() |
036 | str=self.data.read().decode("utf-8") |
037 | web.feed(str) |
038 | print(web.data) |
039 | self.display.delete(1.0, END) |
040 | self.display.insert(INSERT, web.data) |
041 | self.data.close() |
042 | |
043 | if __name__ == '__main__': |
044 | root = Tk() |
045 | root.wm_title("Simple Browser") |
046 | app = SimpleBroswer(master=root) |
047 | app.mainloop() |
SimpleBrowser 的建構子先呼叫 grid() 將其設定為格子版面管理,接著再用 createWidgets() 建立所有的小工具
008 | def __init__(self, master=None): |
009 | Frame.__init__(self, master) |
010 | self.grid() |
011 | self.createWidgets() |
012 | self.address="" |
013 | self.data=None |
我們預計在視窗中放入三個小工具,分別是 Entry 、 Button 及 Text 三種視窗元件,分別儲存在屬性 sidebar 、 gobutton 跟 display 中。例如 gobutton ,建立初值就用 Button
020 | self.gobutton=Button(self) |
建立好 gobutton 後,就可以用串列的方式設定相關屬性,像是設定按鈕的文字
021 | self.gobutton["text"]="Go" |
還要呼叫 grid() 設定在格子的位置
023 | self.gobutton.grid(row=0, column=1) |
至於 "command" 則是設定按下按鈕後去執行哪個方法
024 | self.gobutton["command"]=self.go |
這個 GUI 設定成按下按鈕就執行方法 go() ,除了 demo 中的 TitleParser 外,也用到 urllib.request 的 urlopen() 開啟指定網址的檔案
032 | def go(self): |
033 | self.address=self.sitebar.get() |
034 | self.data=urlopen(self.address) |
035 | web=TitleParser() |
036 | str=self.data.read().decode("utf-8") |
037 | web.feed(str) |
038 | print(web.data) |
039 | self.display.delete(1.0, END) |
040 | self.display.insert(INSERT, web.data) |
041 | self.data.close() |
開啟後如下圖
來試試看囉!輸入 Yahoo 首頁的網址,按下 Go
重新輸入 Facebook 首頁的網址,按下 Go
其實這就是個簡易版的瀏覽器了,倒是想開發自己的瀏覽器,直接整合開源的排版引擎如 WebKit 、 Gecko 等,以及 JavaScript 引擎如 V8 、 SpiderMonkey 等,也就完全不用自己寫諸多解析 HTML 文件的細節了。
tkinter 很方便也很好用,如果要用 MVC 模式來分析的話, M 就是 TitleParser 類別, V 是 SimpleBroswer 類別中的 createWidgets() 方法, C 則是 go() 方法。雖說嚴格的 MVC 模式三者都需要是分開的類別或檔案,倒是簡單的程式把 V 跟 C 合在一起倒無妨。
開發程式應該要專注在 M 的部分,至於 V 則直接套用已經有的框架即可,因為這就像已經有人把輪子都做好了,我們拿輪子裝上去就可以了,大可不必完全重新再次發明輪子。
the end
Python 新手之旅 V1.10 (Google Play)
沒有留言:
張貼留言