[Python 股票爬蟲]十分鐘學會Python爬台股(From Yahoo Finance API)

一、Python爬蟲

如果你已經對Python了解了,十分鐘就可以照著本篇的說明學會如何撈出台灣股票從2000到現在的所有股價。
但如果你從沒接觸過Python,建議從以下清單從頭學習。

預備知識:

基本爬蟲步驟:

網路爬蟲基本的步驟如下:

  • Step 1: 觀察網頁特性
  • Step 2: 用Get/Post將網頁資訊撈下來
  • Step 3: Data Clean/Data Mining
  • Step 4: 將Data存進Database裡

概念就是把網路上的data轉化成工程師可以處理的data,接下來我會照著步驟解釋詳細的流程。
(但基本上,就算不懂這些,直接拉到最下面,把code copy過去就可以動了。)

學習難度: ★

二、Python 爬台灣個股詳細步驟

Step 1: 觀察網頁特性

我們今天要爬的是一個Yahoo Finance API:
https://query1.finance.yahoo.com/v7/finance/download/2330.TW?period1=0&period2=1549258857&interval=1d&events=history&crumb=hP2rOschxO0

根據觀察,我們可以看到兩個重點:
(1) 2330.TW 代表著台積電的股票代碼。
(2) period1 & period2 代表起始日和結束日的timestamp

Step 2: 用Get/Post將網頁資訊撈下來

觀察完,接下來要把網址撈下來,我們會用 Python 的套件來做

(1) 把requests import 進來

1
import requests

(2) 用Post來抓Data

1
2
site = "https://query1.finance.yahoo.com/v7/finance/download/2330.TW?period1=0&period2=1549258857&interval=1d&events=history&crumb=hP2rOschxO0"
response = requests.post(site)

(3) 將抓出來的文字(CSV)直接寫進Dataframe裡,這裡會用到StringIO & Pandas 套件

1
2
3
4
from io import StringIO
import pandas as pd
df = pd.read_csv(StringIO(response.text))
df

Step 3: Data Clean/Data Mining

這個data很乾淨,不用什麼處理

Step 4: 將Data存進Database裡

因為資料量很小的關係,我決定將它寫入 pickle 就好

1
2
3
import pickle
with open('stock.pkl','wb') as f:
pickle.dump(df,f)

三、Python 爬台灣個全部股票的詳細步驟

了解上面步驟後,接下來就可以學習怎麼把全台灣的股票抓下來。

Step 1: Import 所有的套件

1
2
3
4
5
import time
from io import StringIO
import requests
import pandas as pd
import pickle

Step 2: 用time套件處理timestamp

1
2
3
4
5
6
7
def create_today_timestamp():
today = time.strftime("%Y-%m-%d",time.gmtime())
return int(time.mktime(time.strptime(today, "%Y-%m-%d")))
def create_timestamp_from_today(n):
today = create_today_timestamp()
return today + n*24*3600
tomorrow_timestamp = create_timestamp_from_today(1)

Step3: 抓全台灣的股票清單

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def create_tw_stock_info_list():
res = requests.get("http://isin.twse.com.tw/isin/C_public.jsp?strMode=2")
df = pd.read_html(res.text)[0]
df.columns = df.iloc[0]
df = df.iloc[1:]
df = df.dropna(thresh=3, axis=0).dropna(thresh=3, axis=1)
df = df.dropna(how='any')
df = df.reset_index(drop=True)
new_df = df['有價證券代號及名稱'].str.replace(u'\u3000',' ').str.split(u' ',expand=True)
new_df.columns = ['Ticker', 'StockName']
new_df['Sector'] = df['產業別']
return new_df
tw_stock_info_df = create_tw_stock_info_list()
tw_stock_info_df

Step4: For迴圈把所有股票抓下來

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
stock_df = pd.DataFrame()
#ticker_list = tw_stock_info_df['Ticker']
ticker_list = tw_stock_info_df['Ticker'].tail(30)
for ticker in ticker_list:
print('## Info: Download Ticker '+ticker+'!')
site = "https://query1.finance.yahoo.com/v7/finance/download/"+ticker+".TW?period1=0&period2="+str(tomorrow_timestamp)+"&interval=1d&events=history&crumb=hP2rOschxO0"
try:
response = requests.post(site)
tmp_df = pd.read_csv(StringIO(response.text))
tmp_df['Ticker'] = ticker
stock_df = pd.concat([stock_df,tmp_df],axis=0)

except:
print('## Warning: Ticker '+ticker+' is failed!')
stock_df = stock_df.reset_index(drop=True)
stock_df = stock_df[['Date','Ticker','Open','High','Low','Close','Adj Close','Volume']]

總結

雖然很多人都寫過相關的主題,但是還是自己實作一次,當作學習紀錄。
希望對大家有所幫助。

Reference

分享到