金融爬蟲(三):如何更新數據 [附程式碼]

在進行分析之前,先做個更新數據的教學。

上一篇抓取了三大法人數據之後,每天證交所仍會公布新數據,要如何持續更新資料庫呢?

其實很簡單,把程式碼稍做修改即可。

首先,先讀取資料庫,看看上次數據更新到哪一天。

接著,從上次更新那天直到今日,這段時間就是要更新的日期了。

程式碼:
# 載入需要用到的函式庫
import time # 時間函式庫
import sqlalchemy # SQL資料庫ORM函式庫
import numpy as np # 科學計算函式庫
import pandas as pd # 數據分析函式庫
from io import StringIO # 記憶體文字檔案函式
from requests import get # HTTP請求函式
from datetime import datetime # 日期函式
from dateutil.relativedelta import relativedelta # 日期增減函式

# 連結SQLite資料庫
engine = sqlalchemy.create_engine('sqlite:///data.db')

# 讀取最後更新日期
df_fini = pd.read_sql('fini', engine, index_col='table_index', parse_dates=['table_index']) # 讀取外資數據
last_date = df_fini.index[-1] # 取得最後一筆資料日期

# 資料區間
start = last_date + relativedelta(days=1) # 起始日期
end = datetime.today() # 結束日期

# 建立空白DataFrame
df_fini = pd.DataFrame(columns=['買進金額', '賣出金額', '買賣差額'], dtype=np.int64) # 外資數據
df_fund = pd.DataFrame(columns=['買進金額', '賣出金額', '買賣差額'], dtype=np.int64) # 投信數據
df_prop_hedge = pd.DataFrame(columns=['買進金額', '賣出金額', '買賣差額'], dtype=np.int64) # 自營商(避險)數據
df_prop_self = pd.DataFrame(columns=['買進金額', '賣出金額', '買賣差額'], dtype=np.int64) # 自營商(自行買賣)數據
df_fini_prop = pd.DataFrame(columns=['買進金額', '賣出金額', '買賣差額'], dtype=np.int64) # 外資自營商數據
df_sum = pd.DataFrame(columns=['買進金額', '賣出金額', '買賣差額'], dtype=np.int64) # 合計數據

# 爬資料
date = start # 從起始日期開始
while date <= end: # 跑迴圈
    str_date = date.strftime('%Y%m%d') # 日期轉字串
    url = "https://www.twse.com.tw/fund/BFI82U?response=csv&dayDate="+str_date+"&type=day" # 資料網址
    csv = get(url).text # 取得csv檔案
    if csv.strip(): # 判斷csv是否為空檔案,若「不是」空檔案則條件為真
        if date >= datetime(2017, 12, 18): # 證交所將「外資自營商」從「外資及陸資」當中分離出來
            df = pd.read_csv(StringIO(csv), header=1, index_col=0, usecols=[0, 1, 2, 3], dtype={0:str, 1:np.int64, 2:np.int64, 3:np.int64}, skiprows=range(8, 50), thousands=',') # 依格式讀取資料
            df_fini.loc[date] = df.loc['外資及陸資(不含外資自營商)'] + df.loc['外資自營商']
            df_fini_prop.loc[date] = df.loc['外資自營商']
        else:
            df = pd.read_csv(StringIO(csv), header=1, index_col=0, usecols=[0, 1, 2, 3], dtype={0:str, 1:np.int64, 2:np.int64, 3:np.int64}, skiprows=range(7, 50), thousands=',') # 依格式讀取資料
            df_fini.loc[date] = df.loc['外資及陸資']
        df_fund.loc[date] = df.loc['投信']
        df_prop_hedge.loc[date] = df.loc['自營商(避險)']
        df_prop_self.loc[date] = df.loc['自營商(自行買賣)']
        df_sum.loc[date] = df.loc['合計']
        print(date.strftime('%Y-%m-%d')) # 顯示下載進度
    date = date + relativedelta(days=1) # 跳到下一天
    time.sleep(3) # 拉長下載間距

# 更新資料庫
df_fini.to_sql('fini', engine, if_exists='append', index_label='table_index')
df_fund.to_sql('fund', engine, if_exists='append', index_label='table_index')
df_prop_hedge.to_sql('prop_hedge', engine, if_exists='append', index_label='table_index')
df_prop_self.to_sql('prop_self', engine, if_exists='append', index_label='table_index')
df_fini_prop.to_sql('fini_prop', engine, if_exists='append', index_label='table_index')
df_sum.to_sql('sum', engine, if_exists='append', index_label='table_index')

參考資料:
1. Python資料庫(上)
2. Python資料庫(下)
3. 金融爬蟲(一)
4. 金融爬蟲(二)