前面有提到網路爬蟲的優點與缺點,優點就是免錢,缺點就是資料格式可能會改變,需要花時間去維護,但是對於一些即時性沒有那麼強的資料,我們還是可以利用爬蟲來抓取資料,尤其是千百年格式不變的台灣各種交易所,爬取方式都相當容易,比較麻煩的就是要個別抓取不同的標的,沒辦法一次全部吐給我們,接下來我們就一步一步來撰寫臺灣證券交易所的爬蟲吧!
由於這篇文章是我第一篇教學爬蟲,步驟都會比較詳細一點,老手的就可以直接去後面複製程式碼就好了
事前準備:
開始剖析網路資料前要先準備好的東西:
- 開啟Anaconda Spyder IDE (【Python 3 新手村系列】 #01 Anaconda 安裝與操作簡介、【Python 3 新手村系列】 #02 Anaconda IDE Spyder)
- 用Google Chrome開啟:臺灣證券交易所-個股日成交資訊
Step1:分析臺灣證券交易所網頁
首先進入上方的證交所網頁連結,我們就可以看到以上畫面,這個就是我們的目標網站,輸入民國的年月與股票代號(ex. 2330, 2454, 0050)後,點擊查詢就可以看到那一檔股票在當月的歷史資料,在這邊我們須就對這個網頁進行一些進一步的分析,要找出他背後資料是怎麼進來的。
- 在網頁上空白處按滑鼠右鍵,點選「檢查」或是Ctrl+Shift+I,就可以開出上圖右邊的畫面
- 在最上面點選「Network」
- 輸入股票代號2330,並點擊查詢
仔細找一下就會在眾多連結裡面找到我們要的連結,就是上面兩個圖顯示這個連結內容,網址紅色就是可以改變的參數,第一個為日期,第二個為股票代號,第三串數字拿掉其實也不影響
https://www.twse.com.tw/exchangeReport/STOCK_DAY?response=json&date=20200921&stockNo=2330&_=1600694538744
Python Code
Step 1 引入套件:除了我們平常很熟悉的Pandas與Numpy外,另外需要requests來幫助我們抓取網頁內容,json幫剖析網頁的內容成json格式。
import pandas as pd
import numpy as np
import json
import requests
Step 2 網頁爬蟲:利用requests套件進行抓取網址內容,並轉為文字格式輸出。
url = 'https://www.twse.com.tw/exchangeReport/STOCK_DAY?response=json&date=20200921&stockNo=2330'
data = requests.get(url).text
data輸出結果:
Step 3 格式轉換:由上面的資料一看就知道是json格式,所以利用json去進行拆解,拆解後再傳換成pandas的DataFrame格式以方便後續的操作。
json_data = json.loads(data)
Stock_data = json_data['data']
StockPrice = pd.DataFrame(Stock_data, columns = ['Date','Volume','Volume_Cash','Open','High','Low','Close','Change','Order'])
Step 4 更多的格式轉換:原先爬下來的資料均為文字格式,我們這邊需要將這些文字格式轉為程式看得懂的格式,例如將民國日期轉為西元日期,將數值文字資料轉為浮點位(float),包含需要去除千分位的處理。
StockPrice['Date'] = StockPrice['Date'].str.replace('/','').astype(int) + 19110000
StockPrice['Date'] = pd.to_datetime(StockPrice['Date'].astype(str))
StockPrice['Volume'] = StockPrice['Volume'].str.replace(',','').astype(float)/1000
StockPrice['Volume_Cash'] = StockPrice['Volume_Cash'].str.replace(',','').astype(float)
StockPrice['Order'] = StockPrice['Order'].str.replace(',','').astype(float)
StockPrice['Open'] = StockPrice['Open'].str.replace(',','').astype(float)
StockPrice['High'] = StockPrice['High'].str.replace(',','').astype(float)
StockPrice['Low'] = StockPrice['Low'].str.replace(',','').astype(float)
StockPrice['Close'] = StockPrice['Close'].str.replace(',','').astype(float)
StockPrice = StockPrice.set_index('Date', drop = True)
StockPrice = StockPrice[['Open','High','Low','Close','Volume']]
完整Source Code
最後我們可以將上面的程式碼轉換為函數型態,未來只需要丟入參數就可以變更股票代號,網址中的日期參數代表要查詢哪的時間的歷史資料,證交所一次只給一個月,所以下一篇文章將會帶大家把所有股票代號與日期都丟進去,這樣才能夠將所有資料都抓下來。
(如果臺灣證券交易所網站沒改版的話,都可以正常使用,改版則必須重新剖析撰寫)
import pandas as pd
import numpy as np
import json
import requests
def Get_StockPrice(Symbol, Date):
url = f'https://www.twse.com.tw/exchangeReport/STOCK_DAY?response=json&date={Date}&stockNo={Symbol}'
data = requests.get(url).text
json_data = json.loads(data)
Stock_data = json_data['data']
StockPrice = pd.DataFrame(Stock_data, columns = ['Date','Volume','Volume_Cash','Open','High','Low','Close','Change','Order'])
StockPrice['Date'] = StockPrice['Date'].str.replace('/','').astype(int) + 19110000
StockPrice['Date'] = pd.to_datetime(StockPrice['Date'].astype(str))
StockPrice['Volume'] = StockPrice['Volume'].str.replace(',','').astype(float)/1000
StockPrice['Volume_Cash'] = StockPrice['Volume_Cash'].str.replace(',','').astype(float)
StockPrice['Order'] = StockPrice['Order'].str.replace(',','').astype(float)
StockPrice['Open'] = StockPrice['Open'].str.replace(',','').astype(float)
StockPrice['High'] = StockPrice['High'].str.replace(',','').astype(float)
StockPrice['Low'] = StockPrice['Low'].str.replace(',','').astype(float)
StockPrice['Close'] = StockPrice['Close'].str.replace(',','').astype(float)
StockPrice = StockPrice.set_index('Date', drop = True)
StockPrice = StockPrice[['Open','High','Low','Close','Volume']]
print(StockPrice)
return StockPrice
if __name__ == '__main__':
data = Get_StockPrice('2317','20200921')
雷大的Python投資筆記電子報
歡迎訂閱雷大的Python投資筆記電子報,每週將會發布定期市場分析文章與不定期的專案研究文章:
- 國際金融市場分析
- 量化交易策略分享
- Python程式撰寫教學
立即訂閱最新文章