立場新聞 Stand News

不想變大戶點心?用python DIY上市公司通告追蹤器

2018/7/29 — 15:18

facebook、Twitter上周股價齊齊暴瀉,市值蒸發以百億美元計,有股東投訴facebook不提早預警業績差,更發起集體訴訟,與其中伏時才如夢初醒,倒不如做足功課,緊盯愛股的一舉一動。今次以Python寫一個簡單的程式,讓你可以定時到港交所取得愛股的最新公告,並以電郵方式傳送給自己,監察愛股的一舉一動,減少事後「O嘴」、變成大戶點心的機會。

港交所的開放數據之差眾所周知,即時股價買賣資料固然要你付出鉅款才會提供,就連保障股東知情權的公司通告,都沒有一個容易被電腦閱讀的格式,一律以PDF檔上傳,而且其通告搜尋亦不設程式友善的API介面,於是想用電腦到其網站去篩選資料,便要大費周章,其「德政」確實與國際金融中心的名號完全不符。

暫且擱下怨氣,本文將撰寫兩個程式,其一是到港交所的最新通告網頁,下載全個通告列表,然後找出你的愛股的相關通告,再製成表格傳送給指定電郵地址。結果如下:

廣告

第二個程式是到港交所的詳盡搜尋,以程式「扮人」輸入股票編號等資料,然後截取結果列表作分析。

廣告

好了,先說第一個程式的具體操作,首先下載所需的程式庫(程式碼附於後文),BeautifulSoup是一個專門從網頁取得所需訊息的程式庫,十分好用,而pandas則是處理數據的程式庫,requests則具備下載網頁的功能。

究竟具體如何可以取得公司通告的資訊?這亦是最煩的部份,讀者需具備一定的html知識,在最新通告網頁,開啟瀏覽原始碼(所有瀏覽器均有這功能),你會發現通告列表是放在一個<table>中,而每一個通告均有如下結構:

<tr class="row0"><td width="91"><img src="/image/spacer.gif" width="10"/>27/07/2018<br/><img src="/image/spacer.gif" width="10"/>22:59</td><td width="54">02014</td><td width="140"><nobr>浩澤淨水</nobr></td><td class="arial12black"><div id="hdLine">財務報表/環境、社會及管治資料 - [環境、社會及管治資料/報告]<br/></div><a class="news" href="/listedco/listconews/sehk/2018/0727/LTN201807271099_C.pdf" target="_new">二零一七年環境、社會及管治報告</a> (3594KB, PDF)</td></tr>

留意<tr class="row0">,而下一個通告則是"row1",再下一個通告又是"row0",亦即以梅花間竹出現,相信是因為其通告底色的style所致,但卻增加了取得資料的難度,即要取得所有以"row"開首的class的資料,這可以用BeautifulSoup的find_all搭配regular expression,取得一個由類似上述html組成的所有最新通告名單,但如何取得當中的有用資料呢?再觀察上述的一段html,內中日期及時間包在首個<td>tags內,而股票編號及公司名稱則包在第二及第三個<td>tags內,至於通告類型則在一個id="hdLine"的<div>內,而通告標題則在class="news"的<a>tags內,通告鏈結亦包含在<a>中的href屬性內。於是可以設定其他變數,逐一以BeautifulSoup讀入。

很煩嗎,對。因為還要對數據作處理,目前日期及時間會「黏」在一起(如27/07/201821:48),需要用一個小程序加入空格,而通告鏈結亦不完整(如"/listedco/listconews/sehk/2018/0727/LTN201807271099_C.pdf"),要加回港交所的域名才可以直接點擊。

當處理完數據後,便可以用一個數據列表(data frame)變數讀入,這時才真正進入截取有用資訊的部份。幸好python這方面的功能很簡單,只需設定一個追蹤股份名單,然後在股票編號一欄中搜尋,便可即時知道相關股份是否有消息發布。若讀者希望以其他準則搜尋,如找出所有發盈警的股份,亦同一原理。

有了結果後,若果想把結果傳給自己或其他人,可以載入smtplib等電郵處理程式庫,設定好傳送人的電郵帳戶及密碼,電郵標題及訊息,當中訊息即是上述的追蹤股票通告名單,並將其轉化為html table的format。這部份最煩是要把你用於傳送的電郵帳戶的保安程度調校至較寬鬆(詳情請搜尋gmail的Allowing less secure apps to access your account),而筆者亦要使用SSL才能傳送成功。

程式好像很短,但測試則花去不少時間。最後一步則是使用定時工作軟件,定時定候(如一天一次)啟動有關程式,送出電郵,程式全文如下:

Python的網頁擷取資料功能強大,甚至可模擬人的瀏覽動作,例如我想在港交所的進階搜尋網頁內,搜尋小米(01810)的最新通告名單,由於不能在鏈結中加入參數,故此又變得大費周章,幸好Python的Selenium可以扮人手輸入表格,成功取得列表。不過,令人火滾的是該列表的格式,又與上述的最新通告列表不同,故此又需要研究其格式,「度身訂做」抽取資料的程式,但由於做法大同小異,在此不贅,讀者可自行研究以下程式。

以上只是牛刀小試,可以改良的地方很大,例如可以refactor一下,把部份程式編入function,令其更有可讀性及簡潔,又如可否在追蹤股份有通告後即時要求瀏覽器或手機通知用戶,又或挖掘相關pdf並找出通告撮要,希望有高手可以指點一二。

發表意見