我建立了一個名為 myfinsight.com 的網站,提供各家美國上市公司的財務報表與視覺化。 本系列文章將探討如何向美國證券交易委員會 (SEC) 查詢盈利報告、如何將數據發佈到網站, Mailchimp 電子報, 以及社交平台 X 和 Threads.
我有一個數據管道 (data pipeline),每天運行以查詢新的SEC文件。然後,這些新文件會發佈到網站上,以確保網站始終擁有最新的公司文件。從SEC獲取數據並不困難,您不需要是網站爬蟲專家。該數據管道的每日工作流程如下:
獲取今天所有公司文件的列表,網址為:
https://www.sec.gov/cgi-bin/browse-edgar?action=getcurrent
對於每一份公司文件,都會有一個文件頁面,例如:
https://www.sec.gov/Archives/edgar/data/907471/000090747125000090/0000907471-25-000090-index.html. 下載此頁面上列出的所有 "Data Files" (數據文件)。
解析 (Parse) 下載的文件以獲取您想要的數據。這部分的難度取決於您想從文件中獲取多詳細的資訊。
將解析後的數據上傳到 Google BigQuery。
清除網站快取 (cache),以便新數據可以從 BigQuery 載入到網站。
透過 MailChimp API 向訂閱者發送今天公司文件的電子報(附有摘要和精美圖表)。
選取一份公司文件,並透過 X 和 Threads 提供的 API,發佈摘要和精美圖表。
本文將介紹上述步驟 #1 和 #2。請注意,這不是獲取 SEC 文件的唯一方法。SEC 也提供自己的一套 API,您可以直接呼叫,而無需從網站上抓取和下載。如果您只需要簡單的事實,例如公司的淨收益 (net income),那麼 API 就足夠了。另外,您也可以從 SEC 下載壓縮的歷史文件。每天的文件大小約為 2 GB。如果您只需要特定的公司和/或特定類型的文件,則無需下載和處理如此大的文件。此外,數據會延遲一天;今天的文件要到第二天才能獲得。
10-K 和 10-Q 是人們最關心的重要文件之一。10-K 是年度文件 (annual filing),10-Q 是季度文件 (quarterly filing)。要獲取最新的 10-Q 文件,您可以使用此 URL:
https://www.sec.gov/cgi-bin/browse-edgar?type=10-Q&action=getcurrent
對於 10-K 文件,只需將 URL 中的 10-Q 替換為 10-K 即可。如果您訪問這個 URL,您會看到一個 10-K/Q 文件的表格。您可以使用 Pandas 模組將這個 html 表格轉換為 Pandas DataFrame:
response = requests.get(
f"https://www.sec.gov/cgi-bin/browse-edgar?type=10-Q&action=getcurrent",
headers={"User-Agent": "example@email.com"},
)
tables = pd.read_html(
io.StringIO(response.content.decode("utf-8")), extract_links="all"
)
其中 example@email.com 實際上可以是任何內容;我通常只放我的工作郵箱,以便 SEC 知道我不是機器人,儘管我懷疑他們是否真的會在意。請注意,read_html 方法實際上返回的是一個表格列表 (list of tables)。在這個文件網頁上,其實上有多個表格,由於表格多有隱形的邊框,所以光用眼睛看網頁,各個表格其實並不明顯。我們主要關心的是第 6 個表格,即 tables[5]
,它包含最近的文件。別擔心,SEC 網站很少更新;在過去幾年中,tables[5]
一直是正確的表格,您的程式在很長一段時間內都不會出錯、下載到錯誤的表格。
請注意,在上面的程式碼片段中,我們指定了 extract_links="all"
。這樣做,所有的超連結 (hyperlinks) 都將在表格中返回。這很重要,因為我們需要知道每份文件的文件 URL 連結 (filing URL link)。經過一些處理,您會得到類似以下的結果:
這就是您所需要的今天的(2025-09-17)文件,包含公司名稱及其文件 URL (/Archives/edgar/data/…)。
一旦有了文件 URL,我們就可以從中下載文件數據。讓我們看看一個文件頁面的示例:
https://www.sec.gov/Archives/edgar/data/907471/000090747125000090/0000907471-25-000090-index.html
第一個表格(在本例中,第一欄 "Seq" 為 1、2、3、4、5、11)包含供人類閱讀的文件,例如 HTML 網頁和圖片。第二個表格("Seq" 為 6-10 和 99)是供機器處理的文件;這些就是我們需要的。
那麼這些文件是什麼呢?如果我們查看 "Type" (類型) 列,共有 6 種不同類型的文件:
這是最重要的文件,它包含所有財務數據。例如,"淨收益" 是損益表 (income statement) 中的一個財務數據。在這個文件中,"淨收益" 被標記為 us-gaap:NetIncomeLoss,您可以找到類似以下的內容:
<us-gaap:NetIncomeLoss contextRef="ref_xyz" > $24986 </us-gaap:NetIncomeLoss>
這意味著該文件中的淨收益為 $24986。如果您在文件中搜索鍵 ref_xyz
,您還可以找到與此數字相關聯的期間 (period),例如本季度,有時甚至是維度 (dimensions),例如 "Taiwan",表示這筆收益源自台灣的銷售額。該文件還包含在實際文件中看到的 html 表格。
這個文件相對無趣。它列出了該文件中的所有財務表格 (financial tables)。例如,資產負債表 (balance sheet) 通常被列為 http://laab.com/role/CondensedBalanceSheets (roleURI):
<link:roleType roleURI="http://laab.com/role/CondensedBalanceSheets">
<link:definition>110200 - Statement - CONDENSED BALANCE SHEETS</link:definition>
</link:roleType>
當您想使用 roleURI 在不同文件中找到相同的表格時,它可能會很有用。
這個文件指定了不同財務數據之間的數學關係。如果沒有這項資訊,就不可能畫出像這樣的損益表:
例如,如果您查看右上角,您可以看到 "淨收益 (Net income)" 是 "所得稅前收益 (Income before income tax)" 減去 "所得稅準備 (Provision for income tax)"。在這個文件中,"淨收益"、"所得稅前收益" 和 "所得稅準備" 分別被標記為 gaap_NetIncomeLoss、gaap_IncomeBeforeTaxes 和 gaap_IncomeTax。它們的數學關係為:
<link:calculationArc weight="1.0" xlink:from="loc_us-gaap_NetIncomeLoss" xlink:to="loc_us-gaap_IncomeBeforeTaxes"/>
<link:calculationArc weight="-1.0" xlink:from="loc_us-gaap_NetIncomeLoss" xlink:to="loc_us-gaap_IncomeTax"/>
在這裡我們看到有兩個 calculationArc
,用於連結兩個財務數據。第一個 calculationArc
從 gaap_NetIncomeLoss 連結到 gaap_IncomeBeforeTaxes,第二個 calculationArc
從 gaap_NetIncomeLoss 連結到 gaap_IncomeTax,即:
gaap_NetIncomeLoss → gaap_IncomeBeforeTaxes
gaap_NetIncomeLoss → - gaap_IncomeTax
請注意,第二個等式中有一個減號,這是因為前面程式碼片段中的 weight="-1.0"
。結合這兩個等式,我們得到:
gaap_NetIncomeLoss = gaap_IncomeBeforeTaxes - gaap_IncomeTax。透過解析所有的 calculationArc
,我們可以構建如上圖所示的財務報表。
這個文件指定了每個財務表格的 "定義 (definition)"。例如,表格中列出了哪些財務數據,以及表格所在的維度。損益表可以有收益損失 (income loss) 等事實,這些財務數據可以存在於台灣等維度中,表示該表格包含來自台灣的收益值。
這個文件給出了所有財務數據的 "名稱 (labels)"。根據不同的公司,相同的財務數據可以在文件中用不同的名稱。例如,淨收益損失在一家公司中可能被標記為 "Net Income (Loss)",而在另一家公司中則被標記為 "Net Income (Loss) Attributable to Parent Company"。
這個文件給出了每個表格的 "呈現方式 (presentation)"。即使在同一份文件中,一個財務數據在不同表格中的命名也可能不同。例如,在 EX-101.LAB 文件中,淨收益損失可以有兩個標籤 "Net Income (Loss)" 和 "Net Income (Loss) - Taiwan"。EX-101.PRE 文件將告訴您哪個表格對每個財務數據使用了哪個名字。
我的數據程式處理所有 6 個文件,以獲取每個表格中每個財務數據的正確名字及其相互關係。但是,如果您只關心收益損失,那麼您只需在 XML 文件中找到 us-gaap:NetIncomeLoss 並讀取其值即可。在下一篇文章中,我將介紹如何使用 Python 解析這些文件並將結果上傳到 Google BigQuery。