當如果遇到彈出式視窗、沒有網址、沒辦法看 Network Panel 的時候,我們還可以嘗試觀察 html 結構。 由於是在按下「詳細資料」之後跳出目標資料,我們觀察下 節點的 onclick 屬性,其按鈕動作是 document.t15sf_fm.ppp.value='0';document.t15sf_fm.co_id.value='2330';openWindow(this.form ,''); 而 document.t15sf_fm 其實指的是隱藏在 html 結構中的第二個 元件,這個沒有顯示在網頁上的表單,包覆了整個子母公司的資訊表格。 這個就是 name="t15sf_fm" 的 元件,我們就發現這個 form 的目標網址是 "https://mops.twse.com.tw/mops/web/ajax_t15sf" ,發送表單使用的是 POST method。 ###draft_code_symbol_lessthen###form action='/mops/web/ajax_t15sf' name='t15sf_fm' id='t15sf_fm' method='post' onsubmit='return false;'> 說到 POST method,是不是也會有 payload 傳遞呢?再細看 裡面的 : ###draft_code_symbol_lessthen###input type=hidden name=ppp >###draft_code_symbol_lessthen###/input> ###draft_code_symbol_lessthen###input type=hidden name=statef value='110'>###draft_code_symbol_lessthen###/input> ###draft_code_symbol_lessthen###input type=hidden name=TYPEK value='sii'>###draft_code_symbol_lessthen###/input> ###draft_code_symbol_lessthen###input type=hidden name=year value=111>###draft_code_symbol_lessthen###/input> ###draft_code_symbol_lessthen###input type=hidden name=month value=02>###draft_code_symbol_lessthen###/input> ###draft_code_symbol_lessthen###input type=hidden name=co_id >###draft_code_symbol_lessthen###/input> ###draft_code_symbol_lessthen###input type=hidden name=id value=''>###draft_code_symbol_lessthen###/input> ###draft_code_symbol_lessthen###input type=hidden name=key value=''>###draft_code_symbol_lessthen###/input> ###draft_code_symbol_lessthen###input type=hidden name=co_name >###draft_code_symbol_lessthen###/input> ###draft_code_symbol_lessthen###input type='hidden' name='firstin' value='ture'/>###draft_code_symbol_lessthen###/input> 其實這每個 的 name, value 屬性就是 POST request payload 中的 key-value pairs; 其中 ppp, co_id, co_name 被預設為空值。 再回到前面的按鈕 onclick document.t15sf_fm.ppp.value='0';document.t15sf_fm.co_id.value='2330';openWindow(this.form ,''); 這段 javascript 做的事是,當我按下按鈕: 在 name=ppp 的 input value 填入 "0" 在 name=co_id 的 input value 填入 "2330" 就是在將前面 中的 空值處填好並送出表單,將回傳的資料另開視窗呈現。 觀察完畢就很簡單了,我們來寫代碼: import pandas as pd import requests url = "https://mops.twse.com.tw/mops/web/ajax_t15sf" child_co_id = 2330 # 從頁面上的表格獲取的子/母公司代號 payload = { "ppp": "0", "statef": "110", "TYPEK": "sii", "year": "111", "month": "01", "co_id": child_co_id, "id": "", "key": "", "co_name": "", "firstin": "ture" } res = requests.post(url, data=payload, headers=default_headers).content soup = BeautifulSoup(res, "html.parser") df_list = pd.read_html(str(soup)) # 將字串中的 ###draft_code_symbol_lessthen###table> 解析成 DataFrame 格式 (DataFrame 資料需要再額外進行一些清洗) 這樣我們就在不使用 Network Panel 的情況下、以 Requests 方式取得資料啦! 以上是本週工作坊的精選問答更新! 如果妳有爬蟲相關的問題或建議,都歡迎留言/詢問我!