自動下單(Part 1):用Python爬取交易記錄

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

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

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

thumbnail 3 1

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

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

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

打開網頁,監控network

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

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

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

1

這個 Network 列表是做什麼的?

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

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

2

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

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

查看 Request 內容

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

3

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

  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」也是用一樣的方式找

以下是節圖:

4

當然自己慢慢輸入肯定很蠢,所以這一切都要用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
df 1

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

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

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

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

FinLab - 韓承佑

嗨大家好,我是韓承佑,FinLab創辦人,畢業於巴黎薩克雷大學資工博士,目前擔任臺灣量化交易協會 學術顧問、台北商業大學 創新育成中心 創業技術顧問與上市科技公司 量化交易顧問。當初,我喜歡寫程式、無意間因為軟體比賽接觸Fintech,從此開始了財經跟程式的學習之路。我們成立 FinLab 量化投資部落格,用自己研發的軟體,對台灣股市做大量快速的實驗。希望可以在量化投資的路上,當大家的「武器製造商」!