利用 Python 獲取餘額寶歷史收益數據
最近想做一個關於用一些指數基金與餘額寶組成的簡單 風險-無風險 投資組合的實驗計算,發現通達信之類的行情軟體並沒有提供完整的餘額寶收益信息,如通達信僅有年化收益率的數據,並沒有萬份收益的數據。因此考慮利用 Python 做一個小的爬蟲程序獲取相關數據。
數據來源
簡單的搜索了一下,發現網上推薦的網站多數指向一個叫理財收益網 的網站,這裡的較為詳細的數據,不過這個網站的數據僅僅提供到2016年的12月底,17年的1月到2月並沒有,所以不怎麼符合條件。
然後再看了一下天天基金網 ,進入餘額寶頁面,在走勢圖旁邊有一個 歷史收益 的欄目,點擊進去,可以看到有 歷史凈值 的數據,而且數據從 2013-5-30 到最近一天的數據,這裡的數據比較適合,因此就選擇從這裡爬取數據。
網頁分析
在編寫爬蟲程序之前,我們先分析一下這個網頁。
我們可以看到,這張表格下面有一個分頁欄,點擊下面的頁數切換數據。到這裡,一般思路是先看看能不能找到這個網頁的數據更新的 api,如果有,就可以直接通過拼接 url 傳入參數來獲取數據,如果不能的話,那可以考慮使用 selenium 之類的工具模擬點擊實現。
我們先用 chrome 瀏覽器自帶的開發者工具,嘗試是否能夠獲取的數據更新的 api 。比較幸運,這個網站是可以獲取到更新數據的 url 的。url 如下:
http://fund.eastmoney.com/f10/F10DataApi.aspx?type=lsjz&code=000198&page=1&per=20
然後這個 url 的返回值如下:
var apidata={ content:"<table class=w782 comm lsjz><thead><tr><th class=first>凈值日期</th><th>每萬份收益</th><th>7日年化收益率(%)</th><th>申購狀態</th><th>贖回狀態</th><th class=tor last>分紅送配</th></tr></thead><tbody><tr><td>2017-03-17</td><td class=tor bold>1.0213</td><td class=tor bold>3.7480%</td><td>開放申購</td><td>開放贖回</td><td class=red unbold></td></tr><tr><td>2017-03-16</td><td class=tor bold>1.0147</td><td class=tor bold>3.7360%</td><td>開放申購</td><td>開放贖回</td><td class=red unbold></td></tr><tr><td>2017-03-15</td><td class=tor bold>1.0082</td><td class=tor bold>3.7230%</td><td>開放申購</td><td>開放贖回</td><td class=red unbold></td></tr><tr><td>2017-03-14</td><td class=tor bold>1.0066</td><td class=tor bold>3.7120%</td><td>開放申購</td><td>開放贖回</td><td class=red unbold></td></tr><tr><td>2017-03-13</td><td class=tor bold>1.0191</td><td class=tor bold>3.6990%</td><td>開放申購</td><td>開放贖回</td><td class=red unbold></td></tr><tr><td>2017-03-12</td><td class=tor bold>0.9931</td><td class=tor bold>3.6830%</td><td>開放申購</td><td>開放贖回</td><td class=red unbold></td></tr><tr><td>2017-03-11</td><td class=tor bold>0.9934</td><td class=tor bold>3.6740%</td><td>開放申購</td><td>開放贖回</td><td class=red unbold></td></tr><tr><td>2017-03-10</td><td class=tor bold>0.9998</td><td class=tor bold>3.6660%</td><td>開放申購</td><td>開放贖回</td><td class=red unbold></td></tr><tr><td>2017-03-09</td><td class=tor bold>0.9904</td><td class=tor bold>3.6540%</td><td>開放申購</td><td>開放贖回</td><td class=red unbold></td></tr><tr><td>2017-03-08</td><td class=tor bold>0.9873</td><td class=tor bold>3.6500%</td><td>開放申購</td><td>開放贖回</td><td class=red unbold></td></tr><tr><td>2017-03-07</td><td class=tor bold>0.9836</td><td class=tor bold>3.6460%</td><td>開放申購</td><td>開放贖回</td><td class=red unbold></td></tr><tr><td>2017-03-06</td><td class=tor bold>0.9882</td><td class=tor bold>3.6460%</td><td>開放申購</td><td>開放贖回</td><td class=red unbold></td></tr><tr><td>2017-03-05</td><td class=tor bold>0.9775</td><td class=tor bold>3.6420%</td><td>開放申購</td><td>開放贖回</td><td class=red unbold></td></tr><tr><td>2017-03-04</td><td class=tor bold>0.9777</td><td class=tor bold>3.6440%</td><td>開放申購</td><td>開放贖回</td><td class=red unbold></td></tr><tr><td>2017-03-03</td><td class=tor bold>0.9786</td><td class=tor bold>3.6450%</td><td>開放申購</td><td>開放贖回</td><td class=red unbold></td></tr><tr><td>2017-03-02</td><td class=tor bold>0.9829</td><td class=tor bold>3.6500%</td><td>開放申購</td><td>開放贖回</td><td class=red unbold></td></tr><tr><td>2017-03-01</td><td class=tor bold>0.9804</td><td class=tor bold>3.6500%</td><td>開放申購</td><td>開放贖回</td><td class=red unbold></td></tr><tr><td>2017-02-28</td><td class=tor bold>0.9821</td><td class=tor bold>3.6510%</td><td>開放申購</td><td>開放贖回</td><td class=red unbold></td></tr><tr><td>2017-02-27</td><td class=tor bold>0.9814</td><td class=tor bold>3.6520%</td><td>開放申購</td><td>開放贖回</td><td class=red unbold></td></tr><tr><td>2017-02-26</td><td class=tor bold>0.9806</td><td class=tor bold>3.6520%</td><td>開放申購</td><td>開放贖回</td><td class=red unbold></td></tr></tbody></table>",records:1386,pages:70,curpage:1};
我們可以通過返回數據得到總頁數,然後通過更改 url 中的page參數,再解釋 content 裡面的內容就可以獲取到我們想要的數據了。
Python 爬蟲程序
有了上面的分析和思路,我們就可以開始編寫程序了。我的 python 環境為基於 Anaconda2 的 python 2.7.12 版本,代碼在 macOS Sierra 10.12.3 通過。
第一步,我們首先要拿到數據的總頁數,這裡有個小 Tips,這個獲取數據的 url 可以不需要 per 參數,然後它的輸出是默認一頁10行,我在代碼中為了讓 url 更短小好看,因此就省略了 per 參數。
獲取總記錄,總頁數,當前頁面的代碼如下:
def obtain_info_of_data(symbol): response = requests.get(http://fund.eastmoney.com/f10/F10DataApi.aspx?type=lsjz&code= + str(symbol)) # return format: var apidata={...}; # filter the tag content = str(response.text.encode(utf8)[13:-2]) content_split = content.split(,) # obtain the info of data, curpage, pages, records curpage = content_split[-1].split(:)[-1] pages = content_split[-2].split(:)[-1] records = content_split[-3].split(:)[-1] return {curpage: curpage, pages: pages, records: records}
在這段代碼中,有幾個地方需要稍微注意一下。首先這個返回值要注意編碼的問題 (python2.7),然後這個返回值的格式有點像 json 格式但其實它並不是,它的前面有一個 var apidata = * 以及最後多了一個 *; 。 我們可以選擇把它整理成 json 的格式,然後再做處理,不過我這裡直接把前面到 { 的內容切掉,然後後面把 } 後的內容切掉,這樣就可以得到一個以 , 分割的字元串,我們通過 split 函數對 , 進行分割,這樣既可方便的把返回的字元串截取成 4 個我們需要的部分,然後後面的處理就比較簡單了。
拿到這個數據相關描述信息後,我們可以開始接著爬去數據了,相關代碼如下:
def obtain_data(symbol, dict_data_info): cur_pages = int(dict_data_info[pages]) pages = dict_data_info[pages] records = dict_data_info[records] data_return = [] url = http://fund.eastmoney.com/f10/F10DataApi.aspx?type=lsjz&code=%s&page=%s for cp in range(int(pages), 0, -1): response = requests.get(url % (symbol, str(cp))) content = response.text.encode(utf8)[13:-2] data = content.split(,)[0][10:-1] data_soup = bs4.BeautifulSoup(data, lxml) line_of_data = len(data_soup.select(table > tbody > tr)) for i in range(line_of_data, 0, -1): row_of_data = [] date = data_soup.select(table > tbody > tr:nth-of-type(%i) > td:nth-of-type(1) % i)[0].text earning_per_10k = data_soup.select(table > tbody > tr:nth-of-type(%i) > td:nth-of-type(2) % i)[0].text annualized_return = data_soup.select(table > tbody > tr:nth-of-type(%i) > td:nth-of-type(3) % i)[0].text row_of_data.append(date) row_of_data.append(earning_per_10k) row_of_data.append(annualized_return) data_return.append(row_of_data) print Finished %i % cp cur_pages -= 1 if cur_pages == 1 and len(data_return) != int(records): print Data Missing.. return pd.DataFrame(data_return)
這段代碼主要分為兩個部分,一個是遍歷頁面,另一個是在頁面用遍歷每一行的數據。這裡我們用到了 BeautifulSoup 庫來處理 HTML 的內容,然後在函數的最後添加了一個簡單的數據完整性炎症,最後以 pandas DataFrame 的格式返回。
小結
這個獲取餘額寶歷史收益數據的小爬蟲其實並不難,只要耐心分析一個網站的結構,理順思路就可以完成,不過代碼到這裡,其實並不是很完善。如果希望將這些數據更方便的用於量化交易以及其他的一些實驗,還需要把 Dataframe 裡面的數據再做一些處理,如萬分收益率轉為以1為單位的收益率可能更方便計算,然後年化收益率規整話,去掉那個百分號等。
以上代碼已經上傳的 Github,可以下載運行。
推薦閱讀:
※利用requests爬取表情包
※回顧一個月的爬蟲學習
※網易雲音樂Ajax Post參數加密方法
※爬蟲-使用Python3爬取360DOC文檔
※python中 if-else 與 try-except的轉換 與while 與 whileTrue-try-except的轉換