在Python中,如何解析和组织来自每个链接上具有不同结构的API的信息?

在Python中,如何解析和组织来自每个链接上具有不同结构的API的信息?,python,pandas,dataframe,parsing,python-requests,Python,Pandas,Dataframe,Parsing,Python Requests,在python3和pandas中,我使用请求从公共API捕获信息。这样: import requests import pandas as pd headers = {"Accept" : "application/json"} #Example link url = 'http://legis.senado.leg.br/dadosabertos/materia/votacoes/137178' projetos_vot = [] try: r = requests.get(u

在python3和pandas中,我使用请求从公共API捕获信息。这样:

import requests
import pandas as pd

headers = {"Accept" : "application/json"}

#Example link
url = 'http://legis.senado.leg.br/dadosabertos/materia/votacoes/137178'

projetos_vot = []

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)

projects = r.json()

try:
    CodigoMateria = str(projects['VotacaoMateria']['Materia']['IdentificacaoMateria']['CodigoMateria'])
except KeyError:
    CodigoMateria = None                
except TypeError:
    CodigoMateria = None

try:
    SiglaCasaIdentificacaoMateria = str(projects['VotacaoMateria']['Materia']['IdentificacaoMateria']['SiglaCasaIdentificacaoMateria'])
except KeyError:
    SiglaCasaIdentificacaoMateria = None                
except TypeError:
    SiglaCasaIdentificacaoMateria = None

try:
    NomeCasaIdentificacaoMateria = str(projects['VotacaoMateria']['Materia']['IdentificacaoMateria']['NomeCasaIdentificacaoMateria'])
except KeyError:
    NomeCasaIdentificacaoMateria = None                
except TypeError:
    NomeCasaIdentificacaoMateria = None

try:
    SiglaSubtipoMateria = str(projects['VotacaoMateria']['Materia']['IdentificacaoMateria']['SiglaSubtipoMateria'])
except KeyError:
    SiglaSubtipoMateria = None                
except TypeError:
    SiglaSubtipoMateria = None

try:
    DescricaoSubtipoMateria = str(projects['VotacaoMateria']['Materia']['IdentificacaoMateria']['DescricaoSubtipoMateria'])
except KeyError:
    DescricaoSubtipoMateria = None                
except TypeError:
    DescricaoSubtipoMateria = None

try:
    NumeroMateria = str(projects['VotacaoMateria']['Materia']['IdentificacaoMateria']['NumeroMateria'])
except KeyError:
    NumeroMateria = None                
except TypeError:
    NumeroMateria = None

try:
    AnoMateria = str(projects['VotacaoMateria']['Materia']['IdentificacaoMateria']['AnoMateria'])
except KeyError:
    AnoMateria = None                
except TypeError:
    AnoMateria = None

try:
    DescricaoObjetivoProcesso = str(projects['VotacaoMateria']['Materia']['IdentificacaoMateria']['DescricaoObjetivoProcesso'])
except KeyError:
    DescricaoObjetivoProcesso = None                
except TypeError:
    DescricaoObjetivoProcesso = None

try:
    DescricaoIdentificacaoMateria = str(projects['VotacaoMateria']['Materia']['IdentificacaoMateria']['DescricaoIdentificacaoMateria'])
except KeyError:
    DescricaoIdentificacaoMateria = None                
except TypeError:
    DescricaoIdentificacaoMateria = None

try:
    IndicadorTramitando = str(projects['VotacaoMateria']['Materia']['IdentificacaoMateria']['IndicadorTramitando'])
except KeyError:
    IndicadorTramitando = None                
except TypeError:
    IndicadorTramitando = None

# This item (Votacoes) does not have a pattern of the same number of items on each link, so I capture everything
try:
    Votacoes = str(projects['VotacaoMateria']['Materia']['Votacoes'])
except KeyError:
        Votacoes = None
except TypeError:
        Votacoes = None


dicionario = {"CodigoMateria": CodigoMateria,
        "SiglaCasaIdentificacaoMateria": SiglaCasaIdentificacaoMateria,
        "NomeCasaIdentificacaoMateria": NomeCasaIdentificacaoMateria,
        "SiglaSubtipoMateria": SiglaSubtipoMateria,
        "DescricaoSubtipoMateria": DescricaoSubtipoMateria,
        "NumeroMateria": NumeroMateria,
        "AnoMateria": AnoMateria,
        "DescricaoObjetivoProcesso": DescricaoObjetivoProcesso,
        "DescricaoIdentificacaoMateria": DescricaoIdentificacaoMateria,
        "IndicadorTramitando": IndicadorTramitando,
        "Votacoes": Votacoes
        }


projetos_vot.append(dicionario)

df_projetos_vot = pd.DataFrame(projetos_vot)

df_projetos_vot.reset_index()
df_projetos_vot.info()

<class 'pandas.core.frame.DataFrame'>                                    
RangeIndex: 1 entries, 0 to 0
Data columns (total 11 columns):
CodigoMateria                    1 non-null object
SiglaCasaIdentificacaoMateria    1 non-null object
NomeCasaIdentificacaoMateria     1 non-null object
SiglaSubtipoMateria              1 non-null object
DescricaoSubtipoMateria          1 non-null object
NumeroMateria                    1 non-null object
AnoMateria                       1 non-null object
DescricaoObjetivoProcesso        1 non-null object
DescricaoIdentificacaoMateria    1 non-null object
IndicadorTramitando              1 non-null object
Votacoes                         1 non-null object
dtypes: object(11)
memory usage: 216.0+ bytes
正如我在上面的脚本中所说,项(Votacoes)可以在每个链接上具有不同的结构—列数或数据量

请问有没有更有效的方法来解析此类信息

在数据帧中组织它也更好吗?还是最好将数据帧分成多个,每个数据帧的每个链接都有一个唯一的键

2019年12月20日编辑

关于“Votacoes”一项的更多细节,试图进一步解释这个问题

这是关于议会投票的信息,包括参议员的投票

例如,如果在Chrome浏览器中打开或,您将看到更多有关其形成方式的示例

它们是信息的子级别,具有各种密钥和数据。 此外,键的数量可能因链接而异

它不同于“IdentificationCaoMaterial”中的项,更简单且没有子级,因此很容易想到数据帧结构

1-我的问题是,是否有一种方法可以读取“Votacoes”中存在的所有密钥并自动创建数据帧

2-或者如果我必须预测所有可能的关键条件以捕获信息,然后执行数据帧

3-此外,由于这是一个复杂的数据结构,我想就传统的数据帧策略是否真的是最好的或者是否可以使用其他方法发表意见

例如,当前数据帧生成了这个

我想我应该使用每个轮询的唯一键“CodigoMaterial”来索引数据帧。 然后使用唯一键进行搜索将返回“Votacoes”中包含的词典 这个字典将用于显示应用程序中的信息

2019年12月21日编辑

我按照@wowkin2给出的以下说明进行了操作:

import requests
import pandas as pd
import collections

# Function to read all keys
def get_by_key(key, value):
    try:
        if '.' in key:
            old_key, new_key = key.split('.', 1)
            new_value = value[old_key]
            return get_by_key(new_key, new_value)
        else:
            return value[key]
    except (KeyError, TypeError) as _:
        return None

# Function to flatten nested dictionaries
def flatten(d, parent_key='', sep='_'):
    items = []
    for k, v in d.items():
        new_key = parent_key + sep + k if parent_key else k
        if isinstance(v, collections.MutableMapping):
            items.extend(flatten(v, new_key, sep=sep).items())
        else:
            items.append((new_key, v))
    return dict(items)

headers = {"Accept": "application/json"}

# This is a dataframe with multiple voting links
# This in column "url_votacoes_materia"
df_projetos_det.info()

# Marks the beginning of the iteration in df_projetos_det
conta = 0

for num, row in df_projetos_det.iterrows():
    projetos_votos = []
    projects = {}

    url = row['url_votacoes_materia']
    print(url)

    try:
        r = requests.get(url, headers=headers)
        projects = r.json()
    except requests.exceptions.RequestException as e:
        print("Requests exception: {}".format(e))

    dicionario = {
        "CodigoMateria": get_by_key('VotacaoMateria.Materia.IdentificacaoMateria.CodigoMateria', projects),
        "SiglaCasaIdentificacaoMateria": get_by_key('VotacaoMateria.Materia.IdentificacaoMateria.SiglaCasaIdentificacaoMateria', projects),
        "NomeCasaIdentificacaoMateria": get_by_key('VotacaoMateria.Materia.IdentificacaoMateria.NomeCasaIdentificacaoMateria', projects),
        "SiglaSubtipoMateria": get_by_key('VotacaoMateria.Materia.IdentificacaoMateria.SiglaSubtipoMateria', projects),
        "DescricaoSubtipoMateria": get_by_key('VotacaoMateria.Materia.IdentificacaoMateria.DescricaoSubtipoMateria', projects),
        "NumeroMateria": get_by_key('VotacaoMateria.Materia.IdentificacaoMateria.NumeroMateria', projects),
        "AnoMateria": get_by_key('VotacaoMateria.Materia.IdentificacaoMateria.AnoMateria', projects),
        "DescricaoObjetivoProcesso": get_by_key('VotacaoMateria.Materia.IdentificacaoMateria.DescricaoObjetivoProcesso', projects),
        "DescricaoIdentificacaoMateria": get_by_key('VotacaoMateria.Materia.IdentificacaoMateria.DescricaoIdentificacaoMateria', projects),
        "IndicadorTramitando": get_by_key('VotacaoMateria.Materia.IdentificacaoMateria.IndicadorTramitando', projects),
        "Votacoes": get_by_key('VotacaoMateria.Materia.Votacoes', projects),
    }

    projetos_votos.append(dicionario)

    if conta == 0:
        df_projetos_votos = pd.DataFrame(projetos_votos)
    else:
        df_projetos_votos_aux = pd.DataFrame(projetos_votos)
        df_projetos_votos = df_projetos_votos.append(df_projetos_votos_aux)

    conta = conta + 1

df_projetos_votos.info()


# Marks the beginning of the iteration in df_projetos_votos
conta = 0

for num, row in df_projetos_votos.iterrows():
    # I capture the unique code of the proposition that was voted or not
    CodigoMateria = row['CodigoMateria']
    Votacoes = row['Votacoes']

    # Tests if the proposition has already had a vote
    if Votacoes is not None:
        votos = flatten(Votacoes)

        df = pd.DataFrame(votos)
        # Add column with unique code
        df['CodigoMateria'] = CodigoMateria 

        if conta == 0:
           df_procura1 = df
        else:
            df_procura1 = df_procura1.append(df)

        conta = conta + 1

# Created a dataframe with the voting dictionary and its unique proposition codes
df_procura1.info()

若你们想使dict结构扁平化并在数据帧中使用,你们可以使用类似问题中的例子。结果将是一个dict,可以很容易地转换。如果少数对象中缺少某些字段,dataframe将在其中包含空值

导入集合
def展平(d,父项键='',sep=''):
项目=[]
对于d.项()中的k,v:
新密钥=父密钥+sep+k(如果父密钥不是k)
如果isinstance(v,collections.MutableMapping):
items.extend(展平(v,new_键,sep=sep.items())
其他:
项目。附加((新的_键,v))
返回目录(项目)
>>>展平({'a':1,'c':{'a':2,'b':{'x':5,'y':10},'d':[1,2,3]})
{'a':1,'c_a':2,'c_b_x':5,'d':[1,2,3],'c_b_y':10}


最初(2019年12月20日编辑前),
我认为,您需要手动提取一些键并构建结构。所以我想你可以试着用点来定义你的结构,比如
VotacaoMateria.Materia.identificaomateria.CodigoMateria
,来为熊猫数据帧生成dict

导入请求
作为pd进口熊猫
headers={“Accept”:“application/json”}
#示例链接
url='1〕http://legis.senado.leg.br/dadosabertos/materia/votacoes/137178'
项目成本=[]
项目={}
尝试:
r=requests.get(url,headers=headers)
projects=r.json()
除了requests.exceptions.RequestException作为e:
打印(“请求例外:{}”。格式(e))
def get_by_键(键,值):
尝试:
如果键中有“.”:
旧密钥,新密钥=密钥。拆分('.',1)
新_值=值[旧_键]
返回按_键获取_(新_键,新_值)
其他:
返回值[键]
除(KeyError,TypeError)外,如下所示:
一无所获
迪西奥里奥={
“CodigoMateriala”:通过密钥获取(“VotacaoMateria.Material.IdentificationCaomateria.CodigoMaterial”,项目),
“Siglacasa IdentificationCaoMateriala”:按键获取(“VotacaoMateriala.Materiala.IdentificationCaoMaterial.Siglacasa IdentificationCaoMateriala”,项目),
“Nomecasaidentificaomateria”:按键获取(“VotacaoMateria.Material.Identificaomateria.Nomecasaidentificaomateria”,项目),
“SiglaSubtipoMateria”:通过密钥获取(“VotacaoMateria.Materia.IdentificaoMateria.SiglaSubtipoMateria”,项目),
“descripaosubtipomateria”:按键获取(“votacaomatteria.Materia.identicaomatteria.descripaosubtipomateria”,项目),
“数字材料”:通过密钥获取(“VotacaoMaterial.Material.IdentificationCaoMaterial.NumeroMateria”,项目),
“AnoMateria”:通过密钥获取(“VotacaoMateria.Material.IdentificationCaomateria.AnoMateria”,项目),
“descripcaobjetivoprocesso”:按键获取(“VotacaoMateria.material.identificaomateria.descripcaobjetivoprocesso”,项目),
“descripcaodentificationcaomateria”:按键获取(“VotacaoMateria.material.identificationcaomateria.descripcaodentificationcaomateria”,项目),
“IndicatorTramitando”:通过密钥获取(“VotacaoMaterial.Material.IdentificationCaoMaterial.IndicatorTramitando”,项目),
“Votacoes”:按键获取(“VotacaoMateriala.Materiala.Votacoes”,项目),
}
项目附加(dicionario)
df_projetos_vot=pd.数据帧(projetos_vot)
df_项目变量重置索引()
df_projetos_vot.info()
# 
#范围索引:1个条目,0到0
#数据列(共11列):
#AnoMateria 1非空对象
#CodigMaterial 1非空对象
#descripcaoIdentificationCaoMaterial 1非空对象
#DescriptaObjeTivoProcess 1非空对象
#descripaSubTipMaterial 1非空对象
#IndicatorTramitAndo 1非空对象
#NomecasAidentificAcomateria 1非空对象
#NumeroMateria 1非空对象
#SIGLACASEAIdentificationCaoMaterial 1非空对象
#SiglaSubtipoMateria 1非空对象
#Votacoes 1非空对象
#数据类型:对象(11)
#内存使用:160.0+字节
#
#进程已完成,退出代码为0
打印(df_projetos_vot.head())
#化学物质描述鉴定物质描述目标过程。。。
import requests
import pandas as pd
import collections

# Function to read all keys
def get_by_key(key, value):
    try:
        if '.' in key:
            old_key, new_key = key.split('.', 1)
            new_value = value[old_key]
            return get_by_key(new_key, new_value)
        else:
            return value[key]
    except (KeyError, TypeError) as _:
        return None

# Function to flatten nested dictionaries
def flatten(d, parent_key='', sep='_'):
    items = []
    for k, v in d.items():
        new_key = parent_key + sep + k if parent_key else k
        if isinstance(v, collections.MutableMapping):
            items.extend(flatten(v, new_key, sep=sep).items())
        else:
            items.append((new_key, v))
    return dict(items)

headers = {"Accept": "application/json"}

# This is a dataframe with multiple voting links
# This in column "url_votacoes_materia"
df_projetos_det.info()

# Marks the beginning of the iteration in df_projetos_det
conta = 0

for num, row in df_projetos_det.iterrows():
    projetos_votos = []
    projects = {}

    url = row['url_votacoes_materia']
    print(url)

    try:
        r = requests.get(url, headers=headers)
        projects = r.json()
    except requests.exceptions.RequestException as e:
        print("Requests exception: {}".format(e))

    dicionario = {
        "CodigoMateria": get_by_key('VotacaoMateria.Materia.IdentificacaoMateria.CodigoMateria', projects),
        "SiglaCasaIdentificacaoMateria": get_by_key('VotacaoMateria.Materia.IdentificacaoMateria.SiglaCasaIdentificacaoMateria', projects),
        "NomeCasaIdentificacaoMateria": get_by_key('VotacaoMateria.Materia.IdentificacaoMateria.NomeCasaIdentificacaoMateria', projects),
        "SiglaSubtipoMateria": get_by_key('VotacaoMateria.Materia.IdentificacaoMateria.SiglaSubtipoMateria', projects),
        "DescricaoSubtipoMateria": get_by_key('VotacaoMateria.Materia.IdentificacaoMateria.DescricaoSubtipoMateria', projects),
        "NumeroMateria": get_by_key('VotacaoMateria.Materia.IdentificacaoMateria.NumeroMateria', projects),
        "AnoMateria": get_by_key('VotacaoMateria.Materia.IdentificacaoMateria.AnoMateria', projects),
        "DescricaoObjetivoProcesso": get_by_key('VotacaoMateria.Materia.IdentificacaoMateria.DescricaoObjetivoProcesso', projects),
        "DescricaoIdentificacaoMateria": get_by_key('VotacaoMateria.Materia.IdentificacaoMateria.DescricaoIdentificacaoMateria', projects),
        "IndicadorTramitando": get_by_key('VotacaoMateria.Materia.IdentificacaoMateria.IndicadorTramitando', projects),
        "Votacoes": get_by_key('VotacaoMateria.Materia.Votacoes', projects),
    }

    projetos_votos.append(dicionario)

    if conta == 0:
        df_projetos_votos = pd.DataFrame(projetos_votos)
    else:
        df_projetos_votos_aux = pd.DataFrame(projetos_votos)
        df_projetos_votos = df_projetos_votos.append(df_projetos_votos_aux)

    conta = conta + 1

df_projetos_votos.info()


# Marks the beginning of the iteration in df_projetos_votos
conta = 0

for num, row in df_projetos_votos.iterrows():
    # I capture the unique code of the proposition that was voted or not
    CodigoMateria = row['CodigoMateria']
    Votacoes = row['Votacoes']

    # Tests if the proposition has already had a vote
    if Votacoes is not None:
        votos = flatten(Votacoes)

        df = pd.DataFrame(votos)
        # Add column with unique code
        df['CodigoMateria'] = CodigoMateria 

        if conta == 0:
           df_procura1 = df
        else:
            df_procura1 = df_procura1.append(df)

        conta = conta + 1

# Created a dataframe with the voting dictionary and its unique proposition codes
df_procura1.info()