Python 将XML转换为熊猫

Python 将XML转换为熊猫,python,dataframe,finance,Python,Dataframe,Finance,有没有一种方法可以在不知道确切的列标题的情况下将XML文件(来自IB API的财务报表)转换为Pandas?行应反映不同的日期(每列有4个或更多数据点)。另外,最好能把资产负债表、损益表和现金流量表分开。我曾尝试使用beautiful soup,但我感到很沮丧,因为我似乎需要专门查找每个列标题,而我不知道如何获取每个日期的数据 我试图得到三个独立的数据帧(每个财务报表一个)。对不起,我不知道如何在这里添加表,但它们应该是这样的 Df1名称=损益表 这一部分的例子如下: 52 周 更新正常值

有没有一种方法可以在不知道确切的列标题的情况下将XML文件(来自IB API的财务报表)转换为Pandas?行应反映不同的日期(每列有4个或更多数据点)。另外,最好能把资产负债表、损益表和现金流量表分开。我曾尝试使用beautiful soup,但我感到很沮丧,因为我似乎需要专门查找每个列标题,而我不知道如何获取每个日期的数据

我试图得到三个独立的数据帧(每个财务报表一个)。对不起,我不知道如何在这里添加表,但它们应该是这样的

Df1名称=损益表

这一部分的例子如下:


52
周
更新正常值
2018-09-29
安永会计师事务所;扬律师事务所
不合格的
10-K
265595
(...)
12.208930
这是XML文件(由于字符限制,大约有一半):


05680
苹果公司。
942404110
0000320193
普通股
AAPL
AAPL.O
AAPL.OQ
331724
7645713
纳斯达克
7
活跃的
股票发行
2020-01-23
2019-09-28
2019-09-28
美元
1
工业
区分
间接的
收入
(...)
支付的现金税
52
周
更新正常值
2019-09-28
安永会计师事务所;扬律师事务所
不合格的
10-K
260174
(...)
11.885790
更新正常值
2019-09-28
安永会计师事务所;扬律师事务所
不合格的
10-K
12204
(...)
20.365340
52
周
更新正常值
2019-09-28
安永会计师事务所;扬律师事务所
不合格的
10-K
55256
(...)
24311
52
周
更新正常值
2018-09-29
安永会计师事务所;扬律师事务所
不合格的
10-K
265595
(...)
12.208930
重新分类正常
2018-12-29
10-Q
11575
(...)
22.533610
52
周
更新正常值
2018-09-29
安永会计师事务所;扬律师事务所
不合格的
10-K
59531
(...)
5624
53
周
更新正常值
2017-09-30
安永会计师事务所;扬律师事务所
不合格的
10-K
229234
(...)
9.206750

我知道这并不漂亮,但这很管用:

from ib_insync import *
from bs4 import BeautifulSoup as bs
import pandas as pd

ib = IB()
ib.connect('127.0.0.1', 7497, clientId=1)


security = Stock('AAPL', 'SMART', 'USD')

# request the fundamentals
fundamentals = ib.reqFundamentalData(security, reportType='ReportsFinStatements')

soup = bs(fundamentals,'xml')

bal_l = []
inc_l = []
cas_l = []


for period in soup.find_all('FiscalPeriod'):
    if period.get('Type') != "Annual":
        for statement in period.find_all('Statement'):
            if statement.find('UpdateType').get('Code') != 'CLA':
                dic = {}


                t = statement.get('Type')
                d = statement.find('Source').get('Date')
                d1 = statement.find('StatementDate').text
                dic['date'] = d
                dic['StatementDate'] = d1


                for item in statement.find_all('lineItem'):
                    dic[item.get('coaCode')] =item.text


                if t == 'BAL':
                    bal_l.append(dic)
                    print(t, d, dic)
                elif t == 'INC':
                    inc_l.append(dic)
                elif t == 'CAS':
                    cas_l.append(dic)

balancesheet = pd.DataFrame(bal_l).sort_values('date')

with pd.option_context('display.max_rows', 1000, 'display.max_columns', None):
    print(balancesheet)

你好我认为,如果您截断重复的条目,这样我们就可以看到整个XML文档的结构,这会很有帮助。例如,用
..
替换大部分
mapItem
条目。感谢您的提示,因为我从未真正使用过xml,所以我不知道在这里放置哪些部分很重要。编辑:去掉一些重复的东西没问题,基本上当标签被重复时,如果它们不引入新的属性或子元素,它们就不会提供太多的价值。但了解它们是否是重复字段很重要。通常使用XSD(XML模式定义)或DTD(文档类型定义)来描述该结构。例如,见。XPath也可能派上用场。这些XML概念将来可能会对您有所帮助也可能对您有所帮助。感谢您提供这些资源。我以前读过这篇博文,我想我理解它是如何处理固定的列标题的。我的问题是如何在同一个XML中处理不同的列标题和多个表谢谢,我批准了您的编辑。我将添加一个示例表/df
from ib_insync import *
from bs4 import BeautifulSoup as bs
import pandas as pd

ib = IB()
ib.connect('127.0.0.1', 7497, clientId=1)


security = Stock('AAPL', 'SMART', 'USD')

# request the fundamentals
fundamentals = ib.reqFundamentalData(security, reportType='ReportsFinStatements')

soup = bs(fundamentals,'xml')

bal_l = []
inc_l = []
cas_l = []


for period in soup.find_all('FiscalPeriod'):
    if period.get('Type') != "Annual":
        for statement in period.find_all('Statement'):
            if statement.find('UpdateType').get('Code') != 'CLA':
                dic = {}


                t = statement.get('Type')
                d = statement.find('Source').get('Date')
                d1 = statement.find('StatementDate').text
                dic['date'] = d
                dic['StatementDate'] = d1


                for item in statement.find_all('lineItem'):
                    dic[item.get('coaCode')] =item.text


                if t == 'BAL':
                    bal_l.append(dic)
                    print(t, d, dic)
                elif t == 'INC':
                    inc_l.append(dic)
                elif t == 'CAS':
                    cas_l.append(dic)

balancesheet = pd.DataFrame(bal_l).sort_values('date')

with pd.option_context('display.max_rows', 1000, 'display.max_columns', None):
    print(balancesheet)