期末考 Projects 說明
CityU Macau, Fall semester, 2021-2022 academic year
重要說明
整個期末考分數(佔學期總分50%)由兩個 project 組成
�. Project 1 – 股價下載器:佔期末考分數80%
�. Project 2 – 基礎數值分析與可視化:佔期末考分數20%
兩個 project 各⾃要經 tronclass 繳交所有相關檔案。
檔案詳細要求會在以下各⾃說明。
2
Project 1 – 股價下載器
3
⽬標
建立⼀個圖形介⾯應⽤(GUI app),在 app 的輸入欄位輸入某港股編號後,點擊下載按
鈕可以從 Yahoo Finance 網站下載該港股最近60個交易⽇的股價。
該程序由以下兩個檔案構成:
�. 模組 yf.py :定義⼀個叫 YahooFinanceHistory 的 python 類。專⾨⽤於處理爬
蟲⼯作。
�. 主程序 app.py :使⽤ tkinter 建立圖形介⾯。
該GUI應⽤的外觀請⾒下⾴。
每當程序成功下載數據檔案,「下載」按鈕下⽅會出現「成功!」字樣,否則出現
「失敗!」字樣:
4
https://finance.yahoo.com/
5
6
提示
7
模組 yf.py
在該⽂件中定義 YahooFinanceHistory 類,使該類具有以下屬性和⽅法以及相關功
能:
�. _url 屬性(attribute),為⽬標網⾴之URL模板(format):
https://finance.yahoo.com/quote/{code}.HK/history?p={code}.HK
其中 {code} 為填入股票編號的地⽅。
�. get_data ⽅法(method),其輸入參數為股價編號 code 。執⾏該⽅法可以從
Yahoo Finance 下載最近60個交易⽇的股價。 get_data 為本程序核⼼內容之⼀。
它可以再細分為以下部份:
i. 由 _url 建構完整 URL。
ii. ⽤ requests.get 函數訪問 Yahoo Finance 網站並取得 HTML 碼。
iii. ⽤ BeautifulSoup 物件分析HTML的結構,並定位所需內容。
iv. 提取數據,建立 DataFrame ,並將其返回(return)。
8
# File: yf.py
class YahooFinanceHistory:
_url = ‘https://finance.yahoo.com/quote/{code}.HK/history?p={code}.HK’
def get_data(self, code):
# 以下請應⽤課堂上教的爬蟲知識:
# 1. 由 `_url` 建構完整 URL。
# 2. ⽤ `requests.get` 函數訪問 Yahoo Finance 網站並取得其中 HTML 碼。
# 3. ⽤ `BeautifulSoup` 物件分析HTML的結構,並定位所需內容。
# 4. 提取數據,建立 `DataFrame`,並將其返回(return)。
return df
9
第⼀步:由 _url 建構完整 URL
這⼀步要⽤到字符串格式化(string formatting)的知識。
由於 _url 中已經有佔位符 {code} ,所以只要把股票編號填入即可:
def get_data(self, code):
url = self._url.format(code=code)
…
10
第⼆步:⽤ requests.get 函數訪問 Yahoo Finance 網站並取得 HTML 碼。
這⼀步⽤到最後⼀週所教的內容。 requests.get(url) 可以讓 python 訪問 url 所指示
的網站伺服器,獲取所需HTML碼,然後進⾏分析。可是,Yahoo Finance 設置了簡單的
反爬蟲,會⾃動拒絕所有來⾃ python 解釋器的請求。因此,我們也有⼀個簡單⽽必須的
⽅法來反反爬蟲,就是通過設置 User-Agent 這個參數來假裝⾃⼰是普通瀏覽器:
r = requests.get(url, headers={‘User-Agent’: ua})
其中 ua 為以下字符串(也可以從這裏選擇⼀個):
‘Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15
(KHTML, like Gecko) Version/14.1.2 Safari/605.1.15’
成功後 r.text 即網⾴的HTML碼。
建議在 get_data 中增加⼀⾏ r.raise_for_status() 來觸發請求失敗後的報
錯。
11
https://developers.whatismybrowser.com/useragents/explore/
第三步:⽤ BeautifulSoup 物件分析HTML的結構,並定位所需內容。
同樣是最後⼀週的內容。
BeautifulSoup 為 bs4 庫的⼀個類,可以把⾃⾏解析HTML內的標簽元素(tag
element)之間的結構關係,因此可以為我們找到股價所在的標簽元素。
soup = BeautifulSoup(r.text, ‘lxml’)
其中 lxml 為解析引擎。
接下來就可以⽤ soup.find 或 soup.find_all 等⽅法,⼀層⼀層找出股價數據所在
位置。
記得 soup.find_all 返回的是⼀個類似 list 的物件,使⽤上請注意。
提示:股價數據所在標簽為⼀ table 標簽。該標簽具有屬性 data-test ,屬性的值為
historical-prices 。請利⽤這⼀點。
12
第四步:提取數據,建立 DataFrame,並將其返回(return)
當已經定位到⽬標 table 標簽,可以發現股價數據每⼀個 row 都處於⼀個 tr 標簽中。
⽽每⾏ row 當中每個格(cell)上的數據⼜處於稱為 th 或 td 的標簽中。
因此,我們可以
table = soup.find?????? # 請⾃⾏完成
trs = table.find_all(‘tr’)
data = list()
for tr in trs:
cells = tr.find_all([‘th’, ‘td’])
row = list()
for cell in cells:
row.append(cell.text.strip())
data.append(row)
df = pandas.DataFrame(data[1:61], columns=data[0]) # 只要60個交易⽇數據
到此, get_data 這個類⽅法(class method)應該已經完成。請⾃⾏調試。
13
主程序 app.py
該應⽤的主要運⾏介⾯由本⽂件給出。
題⽬要求的圖形介⾯視窗應該包含四個控件(widget):
�. 標語⽂字(使⽤控件類 Label ):⽤於顯示輸入股價的提示標語
�. 輸入欄位(使⽤控件類 Entry ):⽤於輸入港股編號
�. 按鈕(使⽤控件類 Button ):⽤於觸發爬蟲的⾏為
�. 結果狀態提示(使⽤控件類 Label ):⽤於顯示爬蟲是否成功:
成功則顯示 成功!
失敗則顯示 失敗! 。
14
# File: app.py
import tkinter as tk
import yf # 請把 yf.py 放在同⼀⽬錄下
window = tk.Tk()
window.geometry(‘200×200’)
window.title(‘股價下載器’)
# 按鈕控件觸發以下函數:
def download():
# 1. 讀取 Entry 控件的內容
# 1. 調⽤ YahooFinanceHistory 類。使⽤其 get_data 下載股價
# 2. 把返回的數據儲存成 csv 檔案
# 4. 利⽤ try-except 語法捕捉錯誤
# 下⽅寫入各控件。所有按件⽤ pack 進⾏放置
15
第⼀步:建立控件
這⼀步⽤到 week9 的內容。
# ⽤於顯示標語
tk.Label(window, text=’請輸入股票編號’).pack()
ent = tk.Entry(window)
ent.pack()
tk.Button(…, text=’下載’, …).pack() # 請⾃⾏完成
lbl = tk.Label(…)
lbl.pack()
要記住每個控件都需要 master 這個參數來說明該控件是建立在什麼結構之上。
Label 和 Button 兩類控件都需要 text 參數來顯示⼀些⽂字。
Button 這類控件還需要 command 參數來說明點擊後觸發的動作。
16
第⼆步: download 函數
這是點擊按鈕後要觸發的函數。
它主要做四件事:
�. 讀取 ent 中的內容
�. 調⽤ yf.py 中的 YahooFinanceHistory 類的 get_data ⽅法來獲得數據
�. 把數據儲存為 csv
�. 在 lbl 中顯示成功或失敗(通過修改 lbl 的屬性 text )
def download():
try:
code = ent.get()
df = YahooFinanceHistory().get_data(code)
except:
lbl[‘text’] = ??? # 請⾃⾏完成
else:
df.to_csv(…) # 請⾃⾏完成
lbl[‘text’] = ??? # 請⾃⾏完成
17
繳交詳情
Project 1 完成後請繳交以下檔案(強烈建議使⽤ tronclass 繳交除非特殊原因):
�. (80%)代碼檔案( yf.py and app.py )
�. (10%)數據檔案(.csv)⼀個
�. (10%)說明⽂檔⼀個:請⽤ markdown 或 powerpoint 等撰寫⼀個精簡⼜清楚的說
明⽂檔解釋你的程序的⽬的、代碼設計、和功能。
�. (必須)程序運⾏情況的螢幕錄影(.mp4)⼀個(不多於1分鐘長度):影⽚應包含
以下過程:
i. 在你的電腦上啟動程序
ii. 輸入股票編號、點擊按鈕爬蟲、顯示成功
iii. ⽬睹數據檔案的產⽣,並將之打開。
上傳時,不⽤把以上檔案打包成zip。
18
Project 2 – 基礎數值分析與可視化
19
⽬標
把 Project 1 所下載下來的60個交易⽇之數據,⽤ pandas 作簡單加⼯,再畫圖顯示。
步驟
�. ⽤ pandas 的 read_csv 函數讀取 project 1 中得到的股價數據 csv。
�. 清洗數據:檢查有沒有數據異常,把各 column 的數據類型轉為合適的類型
(datatime, float, integer, object, …)
�. 把 DataFrame 的 index 轉為 Date
�. 計算 Adj Close 的 5, 10, 15 天移動平均值(分別叫 ma5 , ma10 , ma15 。可使⽤
DataFrame 的 rolling 計算)
�. 把該 60 個交易⽇的 Adj Close ,和上⾯所計算的所有移動平均值,全部畫在同⼀
個圖中,並為該圖加上 title 說明是那⽀股票,並且儲存為 png 圖檔。如下⾴所示:
20
21
沒有提示
本 project 和 project 1 不同。本 project 為全⾃學模式。請同學⾃⾏找尋資料和⼯具學習
相關知識,並依照上⾴步驟完成題⽬。
閱讀材料可以找 pandas 等相關的⼯具庫(還有其他⼯具庫需要⽤到嗎?請⾃⾏研究)的
官⽅網⾴和說明⽂件。也非常⿎勵同學利⽤各式搜尋引擎尋找網上的⽂章,學習相關知
識。也可以到 youtube 等視頻網站挑選教學影⽚觀看。最後就是重溫平時的課程講義。
22
繳交詳情
Project 2 完成後請繳交以下檔案(強烈建議使⽤ tronclass 繳交除非特殊原因):
�. (80%)代碼檔案(.py 或 .ipynb)
�. (10%)數據檔案(.csv)⼀個
�. (10%)圖⽚檔案(.png)⼀個:
�. (必須)程序運⾏情況的螢幕錄影(.mp4)⼀個(不多於1分鐘長度):影⽚應包含
以下過程:
i. 在你的電腦上啟動程序
ii. 運⾏結束後,⽬睹png檔的產⽣,並將之打開。
上傳時,不⽤把以上檔案打包成zip。
23