使用 Python 解析 XBRL






4.33/5 (9投票s)
使用 Python 从在线财务报告中提取数据。
我的上一篇文章解释了如何访问EDGAR数据库中的公司报告,但没有解释如何从报告中提取数据。如果你查看报告列表,你会发现 EDGAR 提供三种主要格式的报告:
- 普通文本 - 以普通文件(*.txt)形式提供的数据
- 网页 - 供浏览器查看的数据(*.htm)
- XBRL - 以 XBRL 格式文件(*.xml)形式提供的数据
如果你想自己阅读报告数据,前两个选项很好。但如果你想以编程方式提取数据,最后一个选项是最实用的。XBRL 文件对人类来说不容易阅读,但由于其结构,它们非常适合计算机。
本文介绍了 XBRL 格式,然后解释了如何使用 BeautifulSoup
读取 XBRL。最后,我将展示一个示例代码,它以编程方式从 EDGAR 下载并解析 XBRL 文件。
1. XBRL 简介
美国证券交易委员会 (SEC) 的主要职责是确保投资者拥有可靠的信息来做出决策。为此,SEC 要求上市公司提交准确反映其财务状况的报告。公司传统上以普通文本形式提供这些报告,但随着计算机化股票分析的普及,SEC 决定采用更结构化、计算机可读的格式。
SEC 选择了可扩展商业报告语言 (XBRL) 用于结构化公司报告。自 2009 年 4 月起,SEC 要求公司除了文本报告外,还以 XBRL 格式提供财务报告。此后,印度和英国也采用了 XBRL 进行公司报告。
XBRL 基于可扩展标记语言 (XML),但使用特殊的标签来标记财务数据。本节介绍了 XML 和命名空间的基础知识,然后概述了 XBRL。
1.1 XML、Schema 和命名空间
介绍 XML 的好方法是将其与 HTML 进行比较。HTML 文档使用嵌套标签来构造其内容,形式为 <xyz>...</xyz>
。例如,HTML 使用 <b>...</b>
标签以粗体显示文本,例如 <b>Hi there!</b>
。HTML 允许你通过属性控制标签的行为,例如 <p id="...">...</p>
中的 id
属性。
我喜欢将 XML 视为通用 HTML。XML 文档包含与 HTML 中的标签和属性相似的标签和属性,但 XML 不定义任何特定的标签或属性。相反,实现者可以通过创建模式(schema)来定义自己的标签和属性。模式在用 XML Schema Definition (XSD) 格式化的特殊 XML 文档中定义,因此,模式文档的后缀是 *.xsd 而不是 *.xml。
XML 文档可以使用命名空间声明访问模式的标签和属性。例如,以下声明指定 XML 文档将访问位于 http://www.example.com 的模式中定义的标签和属性
xmlns:ex="http://www.example.com"
xmlns
部分代表 XML 命名空间,并且必须存在于每个命名空间声明中。ex
是可选的,用作从模式中获取的标签的前缀。例如,如果模式定义了一个名为 apple
的元素,XML 文档可以使用 <ex:apple>...</ex:apple>
标签访问该元素。
1.2 XBRL 报告和模式
XBRL 文档是一个 XML 文档,它使用 XBRL 的标签和属性来构造其内容。这听起来很简单,但单个文档可能需要访问来自许多不同模式的功能。例如,不同国家有不同的报告要求,因此美国报告将访问与英国报告不同的元素集。同样,不同类型的报告将需要不同的模式,因此年度报告将使用与招股说明书不同的标签。
对美国公司年度报告中标签/属性的详细讨论将占据一本厚厚的书。在本次讨论中,我的目标是介绍美国报告中常用的一些命名空间:
- 基本 XBRL 模式 - 提供 XBRL 文档的整体结构
- 美国文档和实体信息 (DEI) - 设置文档的类型和特征
- 美国公认会计原则 (GAAP) - 定义美国报告的必要元素
- 实体特定模式 - 定义报告提供实体特有的元素
你不需要记住这些命名空间的元素,但你越熟悉,就越能更好地从 XBRL 文档中提取数据。
1.2.1 基本 XBRL 模式
XBRL 的基本标签和属性在位于 http://www.xbrl.org/2003/instance 的模式中提供。文档通常通过 xbrli
前缀访问这些元素,如下面的命名空间声明所示:
xlmns:xbrli="http://www.xbrl.org/2003/instance"
在该模式定义的众多元素中,xbrli:xbrl
尤其重要。这是因为每个 XBRL 文档的内容都必须包含在 <xbrli:xbrl>...</xbrli:xbrl>
标签内。
要理解基本模式提供的其他标签,你应该熟悉以下术语:
instance
- 根元素为<xbrli:xbrl>
的 XBRL 文档fact
- 报告中的单个细节,例如 2000 万美元concept
- 与事实相关的含义,例如销售成本entity
- 概念所描述的公司或个人context
- 将实体与概念关联的数据结构
许多 XBRL 文档首先定义一个很长的上下文列表。每个上下文由一个 <xbrli:context>
元素表示,并且每个上下文都有一个 id
属性。每个 <xbrli:context>
元素都包含一个识别实体的 <xbrli:entity>
子元素。以下标记定义了一个 ID 为 FD2013Q4YTD
的上下文:
<xbrli:context id="FD2013Q4YTD">
<xbrli:entity>
<xbrli:identifier scheme="http://www.sec.gov/CIK">0001065088</xbrli:identifier>
</xbrli:entity>
<xbrli:period>
<xbrli:startDate>2013-01-01</xbrli:startDate>
<xbrli:endDate>2013-12-31</xbrli:endDate>
</xbrli:period>
</xbrli:context>
文档后面的部分可以通过将 contextRef
属性分配给上下文的 ID 来引用此上下文。这在以下标记中显示:
<us-gaap:IncomeTaxDisclosureTextBlock contextRef="FD2013Q4YTD" ...>
1.2.2 美国文档和实体信息 (DEI)
提交给 SEC 的每个 XBRL 文档都需要提供有关其内容的信息。提交者可以通过包含美国文档和实体信息 (DEI) 模式中的元素来满足此要求。这些元素通常以 dei
为前缀,文档可以通过以下声明访问它们:
xlmns:dei="http://xbrl.sec.gov/dei/2014-01-31"
此模式中定义的元素标识 XBRL 报告的类型,并提供有关提交报告的实体的信息。表 1 列出了可用元素中的十一个。
表 1:美国文档和实体信息模式提供的元素(节选)
DocumentType | 报告文档的类型 |
EntityCentralIndexKey | 提交报告实体的 CIK |
TradingSymbol | 提交报告实体的交易代码 |
EntityCurrentReportingStatus | 识别实体是否受备案要求约束 |
EntityFilerCategory | 识别实体的备案类别(大型、小型等) |
EntityRegistrantName | 章程中给出的实体确切名称 |
DocumentFiscalPeriodFocus | 文档关注的会计期间 |
DocumentFiscalYearFocus | 文档关注的会计年度 |
CurrentFiscalYearEndDate | 当前会计年度结束日期 |
AmendmentFlag | 识别文档是否为已备案文档的修正案 previously-filed document |
AmendmentDescription | 修订文档中更改的描述 |
区分 EntityCentralIndexKey
、TradingSymbol
和 EntityRegistrantName
很重要。EntityCentralIndexKey
元素标识提交者的 CIK 代码,TradingSymbol
标识提交者的交易(股票代码)符号,EntityRegistrantName
提供实体的正式名称。
以下标记取自 eBay 年度报告,演示了 DEI 元素的使用方式:
<dei:DocumentType contextRef="..." id="Fact-...">
10-K
</dei:DocumentType>
<dei:EntityCentralIndexKey contextRef="..." id="Fact-...">
0001065088
</dei:EntityCentralIndexKey>
<dei:TradingSymbol contextRef="..." id="Fact-...">
EBAY
</dei:TradingSymbol>
<dei:EntityRegistrantName contextRef="..." id="Fact-...">
EBAY INC
</dei:EntityRegistrantName>
<dei:EntityFilerCategory contextRef="..." id="Fact-...">
Large Accelerated Filer
</dei:EntityFilerCategory>
如所示,每个 DEI 元素都有一个 id
属性和一个 contextRef
,它引用文档前面定义的 <xbrli:context>
元素。
1.2.3 美国公认会计原则 (GAAP)
为了确保企业在其会计报告中使用通用术语,美国财务会计准则委员会 (FASB) 提供了一套称为公认会计原则 (GAAP) 的标准。实体可以通过访问 FASB 的模式定义在其 XBRL 报告中提供 GAAP 数据。GAAP 元素通常以 us-gaap
前缀开头:
xmlns:us-gaap="http://fasb.org/us-gaap/2014-01-31"
此模式提供了数千个与会计相关的元素,表 2 列出了其中一小部分但很重要的子集。你可以在此处查看更完整的表格。
表 2:美国公认会计原则模式的元素(节选)
AccountsPayableCurrent | 截至资产负债表日应付供应商的负债 |
AccountsReceivableGross | 应收客户或客户的款项 |
AccountsReceivableNet | 应收客户或客户的款项,扣除 预计可变现价值 |
AccruedIncomeTaxes | 已知和估计税收义务的未付总额 |
AccruedInsuranceCurrent | 应付保险实体的赔付义务 |
AssetManagementCosts | 与资产管理相关的总成本 |
AssetsCurrent | 预计在一年内变现的所有资产的总和 |
BorrowedFunds | 所有债务金额的总和 |
Cash | 可用于运营需求的无限制现金 |
CommercialPaper | 使用银行和公司发行的无担保 短期借款的价值 |
CommonStockNoParValue | 无面值股票的每股发行价值 |
CommonStockSharesIssued | 已出售或授予股东的普通股总数 sold or granted to shareholders |
CommonStockValue | 已发行普通股的总面值或声明价值 |
SalariesAndWages | 除高级职员外的工资支出 |
ConvertibleDebt | 可以转换为另一种形式的金融工具的债务金额, 例如普通股 |
CostOfGoodsSold | 本期销售商品相关的总成本 |
CostOfServices | 本期提供服务相关的总成本 |
CostsAndExpenses | 本期销售成本和运营费用的总和 |
DebtCurrent | 短期债务和长期债务到期日的总和 |
DeferredRevenue | 尚未实现现金或其他资产 |
Depreciation | 与有形资产成本相关的费用金额,在资产的 有用年限内 |
DirectOperatingCosts | 与运营直接相关的总费用 |
Dividends | 本期所有证券的现金、股票和已宣告股息的股权影响 for all securities during the period |
EarningsPerShareBasic | 本期每股普通股净收益(损失) |
GrossProfit | 总收入减去商品/服务销售成本和运营费用 operating expenses |
IntangibleAssetsCurrent | 非实物资产的流动部分,不包括金融资产 资源文件 |
InterestAndDebtExpense | 与利息和债务支付相关的费用 |
InventoryGross | 为未来销售或用于制造或生产而持有的商品、货物或用品 int manufacturing or production |
Land | 为生产性使用而持有的房地产,非为出售而持有 |
负债 | 所有已确认负债的总和 |
LiabilitiesAndStockholdersEquity | 负债和股东权益的总和,包括归属于非控股权益的 部分权益 |
NetIncomeLoss | 本期利润或损失的一部分,扣除所得税后 |
ProfitLoss | 本期合并利润或损失 |
NotesPayable | 应付票据的总金额,初始到期日超过一年或正常营业周期 beyond one year or the normal operating cycle |
OfficersCompensation | 高级职员的工资支出 |
OperatingCycle | 实体营业周期(如果小于 12 个月) |
OperatingExpenses | 与正常运营相关的经常性成本,销售成本或服务成本中 不包含的费用 |
PreferredStockValue | 已发行不可赎回优先股的声明价值 |
ResearchAndDevelopment 费用 | 在研发活动中发生的成本 activities |
Revenues | 本期确认的总收入 |
SharesIssued | 已发行股票数量 |
SharesOutstanding | 已发行和流通股数量 |
StockholdersEquity | 股东权益项目总和,扣除应收高级职员、董事、 所有者和关联方的款项 |
你可以通过搜索相应的 us-gaap
元素来查找报告中的会计数据。例如,eBay 的 2014 年年度报告使用以下标记识别其总负债:
<us-gaap:Liabilities contextRef="..." decimals="..." id="..." unitRef="usd">
25226000000
</us-gaap:Liabilities>
us-gaap
模式中有很多元素在名称和目的上非常相似。如果你正在搜索特定的会计数据,请务必不要混淆这些元素。
2. 使用 BeautifulSoup 解析 XBRL
下载 XBRL 文档后,你可以使用多种方法提取其数据。如果你知道你感兴趣的元素,你可以对文本执行暴力搜索,例如 us-gaap:Assets
。另一方面,python-xbrl 库是专门为解析 XBRL 文档而创建的,但我从未让它正常工作。
本节解释了如何使用上一篇文章中介绍的 BeautifulSoup
包来解析 XBRL。你不需要学习任何新的类或方法,但重要的是要指定你要执行 XML 解析。如果你安装了 lxml 库 (pip install lxml
),那么你可以使用以下代码创建 BeautifulSoup
实例:
soup = BeautifulSoup(..., 'lxml')
由于某种原因,当我调用 find_all
方法搜索 XBRL 标签时,返回的列表总是空的。但是当我无参数调用 find_all
时,返回的列表包含表示 XBRL 标签的 Tag
。因此,我使用如下代码:
soup = BeautifulSoup(xbrl_string, 'lxml')
tag_list = soup.find_all()
for tag in tag_list:
if tag.name == 'us-gaap:liabilities':
print('Liabilities: ' + tag.text)
年度报告可能包含多个 <us-gaap:liabilities>
元素,每个元素对应一个不同的报告期。每个报告期对应一个 <context>
元素,因此你可以通过检查它们的 contextRef
属性来区分 GAAP 元素。
3. 完整的 EDGAR-XBRL 示例
如果你阅读了上一篇文章和本文的内容,你理解如何访问公司的 EDGAR 报告并在 Python 中解析它们应该没有任何问题。为了演示这一点,清单 1 中的代码在 EDGAR 中搜索 IBM(CIK: 0000051143)的 2014 年年度报告 (10-K),然后解析 XBRL 以确定股东权益 (us-gaap:stockholdersequity
),
清单 1:从 IBM 年度报告中读取股东权益 (xbrl_reader.py)
from bs4 import BeautifulSoup
import requests
import sys
# Access page
cik = '0000051143'
type = '10-K'
dateb = '20160101'
# Obtain HTML for search page
base_url = "https://www.sec.gov/cgi-bin/browse-edgar?action=getcompany&CIK={}&type={}&dateb={}"
edgar_resp = requests.get(base_url.format(cik, type, dateb))
edgar_str = edgar_resp.text
# Find the document link
doc_link = ''
soup = BeautifulSoup(edgar_str, 'html.parser')
table_tag = soup.find('table', class_='tableFile2')
rows = table_tag.find_all('tr')
for row in rows:
cells = row.find_all('td')
if len(cells) > 3:
if '2015' in cells[3].text:
doc_link = 'https://www.sec.gov' + cells[1].a['href']
# Exit if document link couldn't be found
if doc_link == '':
print("Couldn't find the document link")
sys.exit()
# Obtain HTML for document page
doc_resp = requests.get(doc_link)
doc_str = doc_resp.text
# Find the XBRL link
xbrl_link = ''
soup = BeautifulSoup(doc_str, 'html.parser')
table_tag = soup.find('table', class_='tableFile', summary='Data Files')
rows = table_tag.find_all('tr')
for row in rows:
cells = row.find_all('td')
if len(cells) > 3:
if 'INS' in cells[3].text:
xbrl_link = 'https://www.sec.gov' + cells[2].a['href']
# Obtain XBRL text from document
xbrl_resp = requests.get(xbrl_link)
xbrl_str = xbrl_resp.text
# Find and print stockholder's equity
soup = BeautifulSoup(xbrl_str, 'lxml')
tag_list = soup.find_all()
for tag in tag_list:
if tag.name == 'us-gaap:stockholdersequity':
print("Stockholder's equity: " + tag.text)
此代码仅在 SEC 不更改 EDGAR 网站的标记时才能正常工作。当然,标记不太可能随时间保持不变,因此请记住,你可能需要深入研究标记以更新代码。
历史
- 2018 年 2 月 2 日 - 文章首次提交