Python 網頁的抓取 股票篇

工商休息時間

工商休息時間

今天插花一下, 這不是打廣告時間, 只是又有小小的脫離主題, 有人問我想抓股票行情的資料。 該員說: Java 好難寫, 然後 Python 3 又寫不出來, 大家都說 Python是處理網頁的高高手, 阿貝你如何看?

我能說什呢? 好吧, 我上 google 大神查看一下, 嗯, 沒錯阿, python 真的是撈網頁資料高手, 要撈網頁資料大家都嘛用 Python, 難不成, 年輕人越來越懶惰? 是的, 真的很懶惰, 上網查了一下 很多人都用 Python2 寫抓中文網頁的資料, 鮮少用 Python3, 用Py2抓中文在中文碼上面著墨比較麻煩, 可是Py2的套件 (import package) 非常多,而 Py3 就幾乎沒看到用法, 套件也比較少。

不過, 我不死心, 又上網查了一下下, 有阿, 很多套件也跟著升級上來啦。那麼, 到底我們該學 Py3, 還是Py2? 其實我也不知道哩? 就這樣吧, 我現學現賣, 幫剛學的 Py3 拿出來獻醜。

基本上, 阿貝認為學任何程式語言, 只要有心, 有邏輯概念, 應該會很容易上手, 除非它是很特別的程式或語法, 例如 Forth, Postscript, Tex,,, 等等, 族繁不及備載。而 Python 標榜易學, 容易上手, 事實上也真的是如此。 你們有沒有發現, 阿貝寫網格用的 markdown 已經改成 asciidoc? 為什麼? 就功能需求胃口變大了阿!

大部分程式語言難學的部份, 應該來自於外部函數 (libraries), 套件 (packages) 吧。因為地球上太多人開發各種函數 庫, 所以要選那一種套件還是要靠你自己去判斷, 阿貝今天選的就是懶人套件。 OK, 言歸正傳。

首先要分析網頁

我們拿證交所公司行號基本資料表來分析, 有了股票代號才容易對應公司名稱。

上市 http://isin.twse.com.tw/isin/C_public.jsp?strMode=2
上櫃 http://isin.twse.com.tw/isin/C_public.jsp?strMode=4

我就選用 firefox 瀏覽器裡面的 inspector 來看一下內容, 當然你也可以使用其他對你有幫助的工具來查看, 你可以發現 <TR> …​ </TR>是一個區塊 , 裡面包含著無數的 <TD> …​ </TD>, 而 <TD> 裡面就是我們要的資料, 就降子。

啊?! 就降子?! 對阿, 連系統分析都不用。

拿出程式來

"""
# Python 3.x default coding: utf8
#
# 上市 http://isin.twse.com.tw/isin/C_public.jsp?strMode=2
# 上櫃 http://isin.twse.com.tw/isin/C_public.jsp?strMode=4
#
# 例如:
# 有價證券代號及名稱 國際證券辨識號碼(ISIN Code) 上市日 市場別 產業別 CFICode
# 1101 台泥         TW0.....             yyyy/mm/dd   上市 水泥工業  ESVUFR
"""
import re        # regex
import requests  # webpage crawler
from bs4 import BeautifulSoup  # page parser

# -----------
def insertRow(isindb, code, name, isinCode, yearmmdd, marketing, attribute, esvufr):
    sqlCommand = 'insert into companies ' \
        + '(code, name, isincode, yyyymmdd, market, attrib, cficode) values (' \
        + '\'' + code      + '\', ' \
        + '\'' + name      + '\', ' \
        + '\'' + isinCode  + '\', ' \
        + '\'' + yearmmdd  + '\', ' \
        + '\'' + marketing + '\', ' \
        + '\'' + attribute + '\', ' \
        + '\'' + esvufr    + '\')'

    cursor = isindb.cursor()
    cursor.execute(sqlCommand)
    cursor.close()

# -----------
def fetch(url):
    page = requests.get(url)
    soup = BeautifulSoup(page.text, 'html.parser')

    isindb = sqlite3.connect('isin.db')
    #   block:= '<tr> ......</tr>'
    # segment:= '<td ...> ... </td>'
    for block in soup.select('tr'):
        segments = block.find_all('td')
        rawSeg0 = segments[0]
        # for instance: ' <td bgcolor="#FAFAD2">1101¡@¥xªd</td> '
        name = re.search(r'<td bgcolor="#FAFAD2">', str(rawSeg0))

        if name is not None:
            # remove tags
            esvufr = re.sub(r'<.*?>', "", str(segments[5]))
            # check ESVUFR data, which requested data
            if esvufr == 'ESVUFR':
                header    = re.sub(r'<.*?>', "", str(rawSeg0))
                isinCode  = re.sub(r'<.*?>', "", str(segments[1]))
                yearmmdd  = re.sub(r'<.*?>', "", str(segments[2]))
                marketing = re.sub(r'<.*?>', "", str(segments[3]))
                attribute = re.sub(r'<.*?>', "", str(segments[4]))
                code = header.split()
                insertRow(isindb, code[0], code[1], isinCode, yearmmdd, marketing, attribute, esvufr)

    isindb.commit()
    isindb.close()

# -----------
def main():
    url = "http://isin.twse.com.tw/isin/C_public.jsp?strMode=2"
    fetch(url)
    url = "http://isin.twse.com.tw/isin/C_public.jsp?strMode=4"
    fetch(url)

if __name__ == "__main__":
    main()

Python 的簡單精神

我簡單解說一下, 首先上網 google 一下懶人抓網頁的套件, 先不考慮套件執行速度的快慢。這時我找到 BeautifulSoup, 然後就降子 import 進來。 當然 pip install BeautifulSoup4 別忘了。

  • 首先先去執行 fetch(url)

  • 然後開啟 sqlite

  • 以每一區塊 <tr> 為讀取條件

  • 讀取每一段 <td>

  • re.search() 只是確認是我們要找的資料, 當然接著還要在更詳細的確認

  • ESVUFR 則是一定要收集的資料, 這是該員的要求, 只有紀錄 ESVUFR 的公司行號

  • 然後就執行 regex 消掉 <tr> 這些東西, regex 只是阿貝習慣用的正規化指令, 因為以前用 perl 跟 vi 習慣了

  • 沒有強迫每個工程師一定要學, 所以備註就必須講解一下, 免得別人看不懂

  • 最後就存到 sqlite 裡面去了

整個程式就這樣完了, PS: 我知道, windows 系統下的命令可能會亂碼 ( command prompt ) , 你要學會自己改 dos 字碼集。 這不是小學教育。第二, 資料庫的 commit() 何時使用, 你自己決定, 我只簡單說一下, 我是在單機上作業 , 就這樣。

這個也是 firefox 的 addons, sqlite manager, 你只要加進來就好, 感恩世界, 讚嘆世界。

留言

這個網誌中的熱門文章

機車頭燈自動開關裝置

CRV 變速箱油-煞車油-濾芯-中型保養(二)

迅光化油器調整