在Python 3中,我有一个用于访问巴西参议员比尔的API的程序。我打算阅读JSON,然后转换为熊猫数据框。我是这样做的:
import requests
import pandas as pd
headers = {"Accept" : "application/json"}
proposals = []
url = 'http://legis.senado.leg.br/dadosabertos/materia/pesquisa/lista?ano=2010'
try:
r = requests.get(url, headers=headers)
except requests.exceptions.HTTPError as errh:
print ("Http Error:",errh)
except requests.exceptions.ConnectionError as errc:
print ("Error Connecting:",errc)
except requests.exceptions.Timeout as errt:
print ("Timeout Error:",errt)
except requests.exceptions.RequestException as err:
print ("OOps: Something Else",err)
content = r.json()
for item in content["PesquisaBasicaMateria"]["Materias"]["Materia"]:
dicionario = {"AnoMateria": str(item['IdentificacaoMateria']['AnoMateria']),
"CodigoMateria": str(item['IdentificacaoMateria']['CodigoMateria']),
"DescricaoIdentificacaoMateria": item['IdentificacaoMateria']['DescricaoIdentificacaoMateria'],
"DescricaoObjetivoProcesso": item["DescricaoObjetivoProcesso"] if "DescricaoObjetivoProcesso" in item else None,
"DescricaoSubtipoMateria": item['IdentificacaoMateria']['DescricaoSubtipoMateria'],
"IndicadorTramitando": item['IdentificacaoMateria']['IndicadorTramitando'],
"NomeCasaIdentificacaoMateria": item['IdentificacaoMateria']['NomeCasaIdentificacaoMateria'],
"NumeroMateria": str(item['IdentificacaoMateria']['NumeroMateria']),
"ApelidoMateria": item['DadosBasicosMateria']['ApelidoMateria'] if 'ApelidoMateria' in item else None,
"DataApresentacao": item['DadosBasicosMateria']['DataApresentacao'],
"DataLeitura": item['DadosBasicosMateria']['DataLeitura'] if 'DataLeitura' in item else None,
"EmentaMateria": item['DadosBasicosMateria']['EmentaMateria'] if 'EmentaMateria' in item else None,
"ExplicacaoEmentaMateria": item['DadosBasicosMateria']['ExplicacaoEmentaMateria'] if 'ExplicacaoEmentaMateria' in item else None,
"IndicadorComplementar": item['DadosBasicosMateria']['IndicadorComplementar'] if 'IndicadorComplementar' in item else None,
"NaturezaMateria": item['DadosBasicosMateria']['NaturezaMateria'] if 'NaturezaMateria' in item else None,
"NomeAutor": item['AutoresPrincipais']['AutorPrincipal']['NomeAutor'] if 'NomeAutor' in item else None,
"SiglaTipoAutor": item['AutoresPrincipais']['AutorPrincipal']['SiglaTipoAutor'] if 'SiglaTipoAutor' in item else None,
"IndicadorOutrosAutores": item['AutoresPrincipais']['AutorPrincipal']['IndicadorOutrosAutores'] if 'IndicadorOutrosAutores' in item else None,
"CodigoParlamentar": str(item['AutoresPrincipais']['AutorPrincipal']['IdentificacaoParlamentar']['CodigoParlamentar']) if 'CodigoParlamentar' in item else None,
"NomeParlamentar": item['AutoresPrincipais']['AutorPrincipal']['IdentificacaoParlamentar']['NomeParlamentar'] if 'NomeParlamentar' in item else None,
"NomeCompletoParlamentar": item['AutoresPrincipais']['AutorPrincipal']['IdentificacaoParlamentar']['NomeCompletoParlamentar'] if 'NomeCompletoParlamentar' in item else None,
"UrlFotoParlamentar": item['AutoresPrincipais']['AutorPrincipal']['IdentificacaoParlamentar']['UrlFotoParlamentar'] if 'UrlFotoParlamentar' in item else None,
"UfParlamentar": item['AutoresPrincipais']['AutorPrincipal']['IdentificacaoParlamentar']['UfParlamentar'] if 'UfParlamentar' in item else None,
"DataSituacao": item['SituacaoAtual']['Autuacoes']['Autuacao']['Situacao']['DataSituacao'] if 'DataSituacao' in item else None,
"DescricaoSituacao": item['SituacaoAtual']['Autuacoes']['Autuacao']['Situacao']['DescricaoSituacao'] if 'DescricaoSituacao' in item else None
}
proposals.append(dicionario)
df_projetos_api = pd.DataFrame(proposals)
df_projetos_api.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 4216 entries, 0 to 4215
Data columns (total 25 columns):
AnoMateria 4216 non-null object
ApelidoMateria 0 non-null object
CodigoMateria 4216 non-null object
CodigoParlamentar 0 non-null object
DataApresentacao 4216 non-null object
DataLeitura 0 non-null object
DataSituacao 0 non-null object
DescricaoIdentificacaoMateria 4216 non-null object
DescricaoObjetivoProcesso 0 non-null object
DescricaoSituacao 0 non-null object
DescricaoSubtipoMateria 4216 non-null object
EmentaMateria 0 non-null object
ExplicacaoEmentaMateria 0 non-null object
IndicadorComplementar 0 non-null object
IndicadorOutrosAutores 0 non-null object
IndicadorTramitando 4216 non-null object
NaturezaMateria 0 non-null object
NomeAutor 0 non-null object
NomeCasaIdentificacaoMateria 4216 non-null object
NomeCompletoParlamentar 0 non-null object
NomeParlamentar 0 non-null object
NumeroMateria 4216 non-null object
SiglaTipoAutor 0 non-null object
UfParlamentar 0 non-null object
UrlFotoParlamentar 0 non-null object
dtypes: object(25)
memory usage: 411.8+ KB
这行得通,但后来我意识到了两个问题:
1-数据帧“ AutoresPrincipais_df”和“ SituacaoAtual_df”具有子层,可更改键/列的数量
示例:
'AutoresPrincipais': {'AutorPrincipal': {'NomeAutor': 'Eunício Oliveira',
'SiglaTipoAutor': 'SENADOR',
'UfAutor': 'CE',
'IndicadorOutrosAutores': 'Não',
'IdentificacaoParlamentar': {'CodigoParlamentar': '612',
'NomeParlamentar': 'Eunício Oliveira',
'NomeCompletoParlamentar': 'Eunício Lopes de Oliveira',
'SexoParlamentar': 'Masculino',
'FormaTratamento': 'Senador',
'UrlFotoParlamentar': 'http://www.senado.leg.br/senadores/img/fotos-oficiais/senador612.jpg',
'UrlPaginaParlamentar': 'http://www25.senado.leg.br/web/senadores/senador/-/perfil/612',
'SiglaPartidoParlamentar': 'MDB',
'UfParlamentar': 'CE'}}},
或
'AutoresPrincipais': {'AutorPrincipal': {'NomeAutor': 'Ministério da Fazenda',
'SiglaTipoAutor': 'MINISTERIO',
'IndicadorOutrosAutores': 'Não'}},
SituacaoAtual_df的示例
'SituacaoAtual': {'Autuacoes': {'Autuacao': {'NumeroAutuacao': '1',
'Situacao': {'DataSituacao': '2018-06-28',
'CodigoSituacao': '107',
'SiglaSituacao': 'CONHECIDA',
'DescricaoSituacao': 'CONHECIDA.'},
'Local': {'DataLocal': '2018-06-28',
'CodigoLocal': '438',
'SiglaCasaLocal': 'SF',
'NomeCasaLocal': 'Senado Federal',
'SiglaLocal': 'COARQ',
'NomeLocal': 'Coordenação de Arquivo'}}}}},
或
'SituacaoAtual': {'Autuacoes': {'Autuacao': {'NumeroAutuacao': '1',
'Situacao': {'DataSituacao': '2018-06-06',
'CodigoSituacao': '25',
'SiglaSituacao': 'APRVD',
'DescricaoSituacao': 'APROVADA'},
'Local': {'DataLocal': '2018-06-07',
'CodigoLocal': '440',
'SiglaCasaLocal': 'SF',
'NomeCasaLocal': 'Senado Federal',
'SiglaLocal': 'SEXPE',
'NomeLocal': 'Secretaria de Expediente'}}}}},
2-四个数据框没有单个密钥,以后无法合并。这意味着我必须按照“ IdentificacaoMateria”,“ DadosBasicosMateria”,“ AutoresPrincipais”和“ SituacaoAtual”组的出现顺序创建数据框。 JSON中的每一组都是数据框中的一行
这是JSON初始行的摘录
{'PesquisaBasicaMateria': {'@xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
'@xsi:noNamespaceSchemaLocation': 'http://legis.senado.gov.br/dadosabertos/dados/PesquisaBasicaMateriav5.xsd',
'Metadados': {'Versao': '16/01/2019 12:38:14',
'VersaoServico': '5',
'DataVersaoServico': '2017-02-01',
'DescricaoDataSet': 'Efetua a pesquisa de matérias, com a criação de um filtro através dos parâmetros que podem ser informados.\n Se não informar parâmetro algum, não retorna conteúdo.'},
'Materias': {'Materia': [{'IdentificacaoMateria': {'CodigoMateria': '132317',
'SiglaCasaIdentificacaoMateria': 'SF',
'NomeCasaIdentificacaoMateria': 'Senado Federal',
'SiglaSubtipoMateria': 'ACE',
'DescricaoSubtipoMateria': 'AVISO DA COMISSÃO DE EDUCAÇÃO',
'NumeroMateria': '00001',
'AnoMateria': '2018',
'DescricaoIdentificacaoMateria': 'ACE 1/2018',
'IndicadorTramitando': 'Não'},
'DadosBasicosMateria': {'EmentaMateria': 'Avalia as medidas adotadas pelo Governo Federal e pelas prefeituras municipais para implementar as estratégias do Plano Nacional de Educação no que concerne à sua Meta 1 (educação infantil), bem como as medidas adotadas pelos entes federativos para promover o funcionamento de creches e pré-escolas construídas com recursos federais por meio do Proinfância.',
'IndicadorComplementar': 'Não',
'DataApresentacao': '2018-02-23',
'NaturezaMateria': {'CodigoNatureza': '304',
'NomeNatureza': 'DECISAO_TCU',
'DescricaoNatureza': 'Decisão do Tribunal de Contas da União'}},
'AutoresPrincipais': {'AutorPrincipal': {'NomeAutor': 'Tribunal de Contas da União',
'SiglaTipoAutor': 'TRIBUNAL_CONTAS_UNIAO',
'IndicadorOutrosAutores': 'Não'}},
'SituacaoAtual': {'Autuacoes': {'Autuacao': {'NumeroAutuacao': '1',
'Situacao': {'DataSituacao': '2018-03-07',
'CodigoSituacao': '107',
'SiglaSituacao': 'CONHECIDA',
'DescricaoSituacao': 'CONHECIDA.'},
'Local': {'DataLocal': '2018-03-07',
'CodigoLocal': '47',
'SiglaCasaLocal': 'SF',
'NomeCasaLocal': 'Senado Federal',
'SiglaLocal': 'CE',
'NomeLocal': 'Comissão de Educação, Cultura e Esporte'}}}}},
{'IdentificacaoMateria': {'CodigoMateria': '133324',
'SiglaCasaIdentificacaoMateria': 'SF',
'NomeCasaIdentificacaoMateria': 'Senado Federal',
'SiglaSubtipoMateria': 'ACE',
'DescricaoSubtipoMateria': 'AVISO DA COMISSÃO DE EDUCAÇÃO',
'NumeroMateria': '00002',
'AnoMateria': '2018',
'DescricaoIdentificacaoMateria': 'ACE 2/2018',
'IndicadorTramitando': 'Não'},
'DadosBasicosMateria': {'EmentaMateria': 'Analisa a regularidade do usufruto da isenção de contribuição para a seguridade social das entidades beneficentes de assistência social, com atuação preponderante na área de educação.',
'IndicadorComplementar': 'Não',
'DataApresentacao': '2018-05-18',
'NaturezaMateria': {'CodigoNatureza': '304',
'NomeNatureza': 'DECISAO_TCU',
'DescricaoNatureza': 'Decisão do Tribunal de Contas da União'}},
'AutoresPrincipais': {'AutorPrincipal': {'NomeAutor': 'Tribunal de Contas da União',
'SiglaTipoAutor': 'TRIBUNAL_CONTAS_UNIAO',
'IndicadorOutrosAutores': 'Não'}},
'SituacaoAtual': {'Autuacoes': {'Autuacao': {'NumeroAutuacao': '1',
'Situacao': {'DataSituacao': '2018-07-10',
'CodigoSituacao': '107',
'SiglaSituacao': 'CONHECIDA',
'DescricaoSituacao': 'CONHECIDA.'},
'Local': {'DataLocal': '2018-07-10',
'CodigoLocal': '47',
'SiglaCasaLocal': 'SF',
'NomeCasaLocal': 'Senado Federal',
'SiglaLocal': 'CE',
'NomeLocal': 'Comissão de Educação, Cultura e Esporte'}}}}},
{'IdentificacaoMateria': {'CodigoMateria': '133655',
'SiglaCasaIdentificacaoMateria': 'SF',
'NomeCasaIdentificacaoMateria': 'Senado Federal',
'SiglaSubtipoMateria': 'ACE',
'DescricaoSubtipoMateria': 'AVISO DA COMISSÃO DE EDUCAÇÃO',
'NumeroMateria': '00003',
'AnoMateria': '2018',
'DescricaoIdentificacaoMateria': 'ACE 3/2018',
'IndicadorTramitando': 'Não'},
'DadosBasicosMateria': {'EmentaMateria': 'Avalia a atuação do Ministério da Educação nos processos de regulação, supervisão e avaliação da educação superior, tendo como uma de suas referências a estratégia 12.19 do Plano Nacional de Educação.',
'IndicadorComplementar': 'Não',
'DataApresentacao': '2018-06-14',
'NaturezaMateria': {'CodigoNatureza': '304',
'NomeNatureza': 'DECISAO_TCU',
'DescricaoNatureza': 'Decisão do Tribunal de Contas da União'}},
'AutoresPrincipais': {'AutorPrincipal': {'NomeAutor': 'Tribunal de Contas da União',
'SiglaTipoAutor': 'TRIBUNAL_CONTAS_UNIAO',
'IndicadorOutrosAutores': 'Não'}},
'SituacaoAtual': {'Autuacoes': {'Autuacao': {'NumeroAutuacao': '1',
'Situacao': {'DataSituacao': '2018-12-21',
'CodigoSituacao': '28',
'SiglaSituacao': 'ARQVD',
'DescricaoSituacao': 'ARQUIVADA AO FINAL DA LEGISLATURA'},
'Local': {'DataLocal': '2018-12-21',
'CodigoLocal': '438',
'SiglaCasaLocal': 'SF',
'NomeCasaLocal': 'Senado Federal',
'SiglaLocal': 'COARQ',
'NomeLocal': 'Coordenação de Arquivo'}}}}},
...
然后在Materia中重复键“ IdentificacaoMateria”,“ DadosBasicosMateria”,“ AutoresPrincipais”和“ SituacaoAtual”,每个重复都是一个数据帧行
因此,我想创建一个数据行,其中的每一行都由“ IdentificacaoMateria”,“ DadosBasicosMateria”,“ AutoresPrincipais”和“ SituacaoAtual”中的列组成,并包含其内容
请问,是否可以从JSON文档创建数据框,以便仅选择一些内部键?
在同事们提供的各种信息的帮助下,我的工作方式奏效了。但是您可以看到某些列完全为空。我不明白为什么,因为直到信息出现之前我才指出完整路径
答案 0 :(得分:2)
json有两个级别。第一个是“ PesquisaBasicaMateria”。因此,要获取所需的字典,请使用:
mats = projects['PesquisaBasicaMateria']['Materias']
然后查看或从mats
中获取每个“材料”。
materia = mats['Materia']
那是您必须进一步解压缩的列表。
dict_l = [d['IdentificacaoMateria'] for d in mat]
df = pd.DataFrame(dict_l)
这将为您提供10列和5行的DataFrame。列为:
['AnoMateria', 'CodigoMateria', 'DescricaoIdentificacaoMateria', 'DescricaoObjetivoProcesso', 'DescricaoSubtipoMateria', 'IndicadorTramitando', 'NomeCasaIdentificacaoMateria', 'NumeroMateria', 'SiglaCasaIdentificacaoMateria', 'SiglaSubtipoMateria']
答案 1 :(得分:1)
您可以仅访问该密钥并从此处构建数据框:
projects = r.json()
mats = projects.get('Materias') # This is a dictionary
if not mats:
raise ValueError("Didn't find anything in 'Materias')
mats_list = mats.get('Materia') # This should be a list of dictionaries
if not mats_list:
raise ValueError("Got None or empty list in 'Materia'")
df = pd.DataFrame(mats_list)
这是假设json结构如下:
{ 'Materias': {
'Materia': [ # interesting dictionaries]
}
}
如果嵌套像看起来的那样进一步下降,这可能会更棘手
答案 2 :(得分:1)
通过对Materia的JSON响应进行挖掘,我们找到一个列表:
the_json["PesquisaBasicaMateria"]["Materias"]["Materia"]
测试的样本包含3014 items
,每个字典本身都是字典,具有以下2-4个键之间的任意位置:
['IdentificacaoMateria', 'DadosBasicosMateria', 'AutoresPrincipais', 'SituacaoAtual']
['IdentificacaoMateria', 'DadosBasicosMateria', 'AutoresPrincipais']
['IdentificacaoMateria', 'DadosBasicosMateria', 'SituacaoAtual']
['IdentificacaoMateria', 'DadosBasicosMateria']
这4种类型中的每一种都包含唯一字段,而又不了解有关数据的更多信息或您的需求,就很难计划如何将这些数据组合到单个记录集中。
但是,您可以先在各自的DataFrame中查看以下四种类型的Materia,如下所示:
the_records = {
"IdentificacaoMateria": [],
"DadosBasicosMateria": [],
"AutoresPrincipais": [],
"SituacaoAtual": []
}
for item in the_json["PesquisaBasicaMateria"]["Materias"]["Materia"]:
for subkey in item.keys():
the_records[subkey].append(item[subkey])
IdentificacaoMateria_df = pd.DataFrame(the_records["IdentificacaoMateria"])
DadosBasicosMateria_df = pd.DataFrame(the_records["DadosBasicosMateria"])
AutoresPrincipais_df = pd.DataFrame(the_records["AutoresPrincipais"])
SituacaoAtual_df = pd.DataFrame(the_records["SituacaoAtual"])
然后也许看看:
https://pandas.pydata.org/pandas-docs/stable/merging.html
并尝试使用pd.concat
来按照您想要的方式合并记录。