跳至主要內容
FinLab

自動下單 (Part 1):用 Python 爬取券商交易記錄與持股部位

量化投資原來分為以下兩個步驟:

  1. 用數學模型,運算出買賣股票清單
  2. 清單自動與看盤軟體對接,實現自動買賣

今天就教你怎麼將自己的帳戶與 python 做連接,讓電腦得知你實際持股的部位。

自動下單教學縮圖

打開券商看盤軟體(網站)

首先,我們針對新光證券來進行對接,其它證券的朋友就不好意思了,我只有新光 XDD,但每一家的網站設計不會差太多,可以舉一反三,做出其它證券的對接系統。

雖然我是新光的用戶,但新光的網站真的很瞎!介面老舊不說,每天早上 9 點開盤必當機…好在我都是直接下開盤漲停買入,我是可憐窮散戶金額小所以沒差 XDD。

打開網頁,監控 network

接下來我們要來查看登入機制是如何運作的,知道了內部的機制,才能用 python 來模擬登入的動作喔!

  1. 用無痕視窗登入頁面
  2. 對著網頁任何一處按右鍵,選擇 inspect(中文忘記是什麼了,反正就是最下方那個 XD)
  3. 選擇 network(一樣請自己對照中文)

做完這三步驟你應該會看到以下節圖:

瀏覽器開發者工具的 Network 列表畫面

這個 Network 列表是做什麼的?

network 這個列表,最主要就是會紀錄網頁所用到的 get 跟 post 的請求,什麼是 get 跟 post 呢?籠統的說,這些就是你的瀏覽器跟網站主機互動時的通信方式,平常瀏覽網頁,將網頁從網路上下載到瀏覽器中,這個動作通常是用 get,而隱私性比較高的(登入、修改網路上的資料),就會用 post。

輸入你的帳號密碼按下登入,你會看到 network 的列表出現了很多東西,大部分的都不重要,請點選其中的 Login.aspx,裡面紀錄著用來登入的通訊過程。

Network 列表中 Login.aspx 的登入通訊過程

你應該會看到以上的節圖,裡面有些重要的資訊,我們先把登入當作是一封寫給新光主機的信,上圖中包含了幾個重要的資訊:

  1. 信寄到:https://w.sk88.com.tw/Cross/Pc/Login.aspx 這個地方
  2. 這是一個 POST request
  3. server 回覆代號是 302 (通常是 2XX、或 3XX。4XX、5XX 代表有問題)

查看 Request 內容

目前知道的訊息有:信的種類為 post,而地址也有了。但信中的內容要寫什麼呢?無非就是跟登入有關的訊息吧!例如帳號密碼之類的,所以我們將視窗往下拉,看到 form data 這裡:

登入 Request 的 form data 內容

你可以看到信封裡的內容:

  1. __EVENTTARGET: 欄位為空
  2. __EVENTARGUMENT: 欄位為空
  3. __VIEWSTATE: 亂碼
  4. __VIEWSTATEGENERATOR: 亂碼
  5. __EVENTVALIDATION: 亂碼
  6. TxtIDNo: 你的身份證字號,
  7. TxtPass: 你的密碼,
  8. HiddenIDNo: 你的生份正字號,
  9. Button1: 登入,

我們可以發現除了帳號密碼外,還有很多怪東西,例如:「__EVENTTARGET」等等,這些東西我們不能亂填,我們得找到這些欄位的正確內容,登入才會生效。 我們可以到原本的登入網頁找:

  1. 回到登入頁面(inspect 依然開啟)
  2. 點選 inspect 中的 Element,打開網站的原始碼,並搜尋(Ctrl-F 或 Cmd-F),’__VIEWSTATE’,就可以找到一它的 value 是多少了!
  3. 其它如「__EVENTARGUMENT」、「__VIEWSTATE」、「__VIEWSTATEGENERATOR」、「__EVENTVALIDATION」也是用一樣的方式找

以下是節圖:

在網站原始碼中搜尋 __VIEWSTATE 的 value

當然自己慢慢輸入肯定很蠢,所以這一切都要用 python 自動化才行! 以後真的只要 1 秒就可以下載好,省去網站慢吞吞填入帳密。。。

寫 code 時間

所以你已經瞭解了原理了,接下來就是實做! 首先,我們要得到網頁,找尋當中的「__VIEWSTATE」等驗證碼: 得到網頁、驗證碼

顯示程式碼
import re
import requests
import pandas as pd
from io import StringIO
 
# 開啟瀏覽器
ses = requests.Session()
 
# 打開登入網頁
d = ses.get('https://w.sk88.com.tw/Cross/Pc/Login.aspx')
 
# 此函式會找特定的value,如「__VIEWSTATE」等
def find_value(name, web):
    reg = 'name="' + name + '".+value="(.*)" />'
    pattern = re.compile(reg)
    result  = pattern.findall(web.text)
    try:
        return result[0]
    except:
        return ""
 
# 使用方式
find_value('__VIEWSTATE', d)

我特別寫好了一個 find_value 的函式,它會幫你找出網頁中的怪碼,大家有興趣可以去研究 regex ,用來解析字串用的。

find_value 函式找出網頁驗證碼的結果

於是 __VIEWSTATEGENERATOR__EVENTVALIDATION,這些怪東西的驗證碼就被找到了!

寫信封的內容

接下來我們再來實際的登入:

用 python 模擬登入

顯示程式碼
data = {
    '__EVENTTARGET': find_value('__EVENTTARGET', d),
    '__EVENTARGUMENT': find_value('__EVENTARGUMENT', d),
    '__VIEWSTATE': find_value('__VIEWSTATE', d),
    '__VIEWSTATEGENERATOR': find_value('__VIEWSTATEGENERATOR', d),
    '__EVENTVALIDATION': find_value('__EVENTVALIDATION', d),
    'TxtIDNo':'你的身份證字號(帳號)',
    'TxtPass':'密碼',
    'HiddenIDNo':'你的身份證字號(帳號)',
    'Button1':'登入',
}
 
login = ses.post('https://w.sk88.com.tw/Cross/Pc/Login.aspx', data=data)

以上的 code,就是創建信封的內容 data,並發送「POST」,請求登入。記得要修改改帳號密碼才能用喔!

下載持股部位

接下來,由於已經登入了,我們就去相對應的網址,下載自己的持股部位: 下載持股部位

顯示程式碼
 
# 下載持股
data = ses.get('https://w.sk88.com.tw/Cross/Pc/QueryPositionRealTime.aspx')
data.encoding = 'utf-8'
 
# 用 pandas 整理
df = pd.read_html(StringIO(data.text))[0]
 
# 設定第一行row 為 欄位名稱
df.columns = df.iloc[0]
 
# 刪除第一行row
df = df.iloc[1:]
df

用 pandas 整理後的持股部位 DataFrame

以上是我的持股記錄,趁最近表現不錯放一下 XDD,這只是表面績效很好,實際上沒那麼好,因為最近賣了很多虧損股,只剩好的股票,所以才看起來光鮮亮麗。絕對不能只看持股獲利,還必須考慮銀行帳戶中的存款才行喔!不然很有可能發現,持股獲利很高,但帳戶餘額慢慢變少的情況喔!

以上就是今天的教學,有以下幾個小重點:

  1. 學習用 chrome 來找 get post 的方法
  2. 利用 python 模擬登入帳號
  3. 下載自己的持股狀況

下次會介紹如何串接自動化買賣,敬請期待!

想建立自己的策略?

用自然語言描述你的選股想法,AI 自動驗證、回測、給你答案

免費開始