如何使用 JSON 正确读取 API 并创建列表?在 Python 中

Posted

技术标签:

【中文标题】如何使用 JSON 正确读取 API 并创建列表?在 Python 中【英文标题】:How to read an API correctly with JSON and create list? In Python 【发布时间】:2017-12-19 14:36:50 【问题描述】:

在 Python3 中,我编写了一个程序来读取 API(来自巴西众议院)并以 JSON 格式获取数据

import requests
import pandas as pd

url = 'https://dadosabertos.camara.leg.br/api/v2/deputados'

首先我用字典列出了一个列表 - 它们是代表的姓名和每个代表的相应 API 链接。参数为json,每页项数和页码(有500多副,那就有6页)

deputados = []
for pagina in [1, 2, 3, 4, 5, 6]:
    parametros = 'formato': 'json', 'itens': 100, 'pagina': pagina
    resposta = requests.get(url, parametros)
    for deputado in resposta.json()['dados']:
        dicionario = "deputado": deputado['nome'], "link_api": deputado['uri']
        deputados.append(dicionario)

列表内容:

deputados
['deputado': 'ABEL MESQUITA JR.',
  'link_api': 'https://dadosabertos.camara.leg.br/api/v2/deputados/178957',
 'deputado': 'ADAIL CARNEIRO',
  'link_api': 'https://dadosabertos.camara.leg.br/api/v2/deputados/178864',
 'deputado': 'ADALBERTO CAVALCANTI',
  'link_api': 'https://dadosabertos.camara.leg.br/api/v2/deputados/178914',
 'deputado': 'ADELMO CARNEIRO LEÃO',
  'link_api': 'https://dadosabertos.camara.leg.br/api/v2/deputados/178890',
 'deputado': 'ADELSON BARRETO',
  'link_api': 'https://dadosabertos.camara.leg.br/api/v2/deputados/178968',
 'deputado': 'ADEMIR CAMILO',
  'link_api': 'https://dadosabertos.camara.leg.br/api/v2/deputados/133374',
...

我用结果创建一个数据框

df = pd.DataFrame(deputados)
df.reset_index().head()
index   deputado    link_api
0   0   ABEL MESQUITA JR.   https://dadosabertos.camara.leg.br/api/v2/depu...
1   1   ADAIL CARNEIRO  https://dadosabertos.camara.leg.br/api/v2/depu...
2   2   ADALBERTO CAVALCANTI    https://dadosabertos.camara.leg.br/api/v2/depu...
3   3   ADELMO CARNEIRO LEÃO    https://dadosabertos.camara.leg.br/api/v2/depu...
4   4   ADELSON BARRETO     https://dadosabertos.camara.leg.br/api/v2/depu...

然后我用字典创建了另一个列表。这次我想去每个代理 API 页面,提取一些数据。我打印了一些照片来检查结果(“resposta”和“linha”)。现在参数只是json

perfis = []
for num, row in df.iterrows():
    parametros = 'formato': 'json'
    resposta = requests.get(row['link_api'], parametros)
    print(resposta)
    for linha in resposta.json()['dados']:
        print(linha)
        item1 = linha['uri']
        item2 = linha['nomeCivil']
    for linha2 in resposta.json()['ultimoStatus']:
        item3 = linha2['nomeEleitoral']
        item4 = linha2['siglaPartido']
        item5 = linha2['siglaUf']
        item6 = linha2['urlFoto']
    for linha3 in resposta.json()['ultimoStatus/gabinete']:
        item7 = linha3['telefone']
        item8 = linha3['email']
        item9 = linha3['sexo']
        item10 = linha3['dataNascimento']
    dicionario = "link_api": item1, "nome_completo": item2, "nome_eleitoral": item3, "partido": item4, "uf": item5, "link_foto": item6, "telefone": item7, "e_mail": item8, "sexo": item9, "data_nascimento": item2    
    perfis.append(dicionario)

这里我有一个错误(字符串索引必须是整数),打印显示代理 API 没有正确读取

<Response [200]>
id

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-21-bfada3632dc2> in <module>()
      6     for linha in resposta.json()['dados']:
      7         print(linha)
----> 8         item1 = linha['uri']
      9         item2 = linha['nomeCivil']
     10     for linha2 in resposta.json()['ultimoStatus']:

TypeError: string indices must be integers

确认一下,“resposta”打印为 = Response [200],“linha” = id。 在“resposta”的情况下应该有 API 链接的 requests.get 值。而“linha”是所选项目的json值

然后我单独测试了一个 API 链接,它工作了:

resposta = requests.get('https://dadosabertos.camara.leg.br/api/v2/deputados/178890')
print(resposta.json())
'dados': 'id': 178890, 'uri': 'https://dadosabertos.camara.leg.br/api/v2/deputados/178890', 'nomeCivil': 'ADELMO CARNEIRO LEAO', 'ultimoStatus': 'id': 178890, 'uri': 'https://dadosabertos.camara.leg.br/api/v2/deputados/178890', 'nome': 'ADELMO CARNEIRO LEÃO', 'siglaPartido': 'PT', 'uriPartido': 'https://dadosabertos.camara.leg.br/api/v2/partidos/36844', 'siglaUf': 'MG', 'idLegislatura': 55, 'urlFoto': 'http://www.camara.leg.br/internet/deputado/bandep/178890.jpg', 'data': '2015-03-06', 'nomeEleitoral': 'ADELMO CARNEIRO LEÃO', 'gabinete': 'nome': '231', 'predio': '4', 'sala': '231', 'andar': '2', 'telefone': '3215-5231', 'email': 'dep.adelmocarneiroleao@camara.leg.br', 'situacao': 'Exercício', 'condicaoEleitoral': 'Suplente', 'descricaoStatus': None, 'cpf': '', 'sexo': 'M', 'urlWebsite': None, 'redeSocial': [], 'dataNascimento': '1949-05-25', 'dataFalecimento': None, 'ufNascimento': 'MG', 'municipioNascimento': 'Itapagipe', 'escolaridade': 'Doutorado', 'links': ['rel': 'self', 'href': 'https://dadosabertos.camara.leg.br/api/v2/deputados/178890']

​可以在此处查看 JSON 页面:https://dadosabertos.camara.leg.br/api/v2/deputados/178890?formato=json

请问这是否意味着当我尝试创建第二个列表时缺少某些参数?

【问题讨论】:

resposta.json()['dados'] 显然是一个字典,因此当您使用 for..in 循环对其进行迭代时,您实际上得到的是它的键,而不是它的值。在末尾添加.values() 以迭代这些值。 也许不是所有的api链接都提供uri 您好,谢谢。我已经将 -> for linha 放在 resposta.json () ['data'] 中。值(): 但“resposta”打印继续响应 [200]。 “linha”打印显示 178957,即 id 值 【参考方案1】:

因为这条线:

for linha in resposta.json()['dados']:

这是您在resposta.json()['dados'] 中的示例:

'ufNascimento': 'MG', 'municipioNascimento': 'Teófilo Otoni', 'redeSocial': [], 'id': 133374, 'dataNascimento': '1964-05-30', 'dataFalecimento': None, 'urlWebsite': None, 'ultimoStatus': 'siglaPartido': 'PODE', 'condicaoEleitoral': 'Suplente', 'idLegislatura': 55, 'nome': 'ADEMIR CAMILO', 'id': 133374, 'nomeEleitoral': 'ADEMIR CAMILO', 'descricaoStatus': None, 'uri': 'https://dadosabertos.camara.leg.br/api/v2/deputados/133374', 'uriPartido': 'https://dadosabertos.camara.leg.br/api/v2/partidos/36896', 'situacao': 'Exercício', 'urlFoto': 'http://www.camara.leg.br/internet/deputado/bandep/133374.jpg', 'gabinete': 'predio': '4', 'nome': '556', 'andar': '5', 'sala': '556', 'telefone': '3215-5556', 'email': 'dep.ademircamilo@camara.leg.br', 'siglaUf': 'MG', 'data': '2016-04-19', 'nomeCivil': 'ADEMIR CAMILO PRATES RODRIGUES', 'cpf': '', 'escolaridade': None, 'sexo': 'M', 'uri': 'https://dadosabertos.camara.leg.br/api/v2/deputados/133374'

这是一本字典。

for x in dictonarydictionarykeys 中循环,因此您在列表中循环:

['urlWebsite', 'sexo', 'nomeCivil', 'cpf', 'ultimoStatus', 'dataFalecimento', 'municipioNascimento', 'uri', 'id', 'escolaridade', 'dataNascimento', 'redeSocial', 'ufNascimento']

所以,写item1 = linha['uri'] 就像写item1 = ['foo', 'bar']['baz'] 这显然没有任何意义。

快速修复:将 for linha in resposta.json()['dados']: 替换为 linha = resposta.json()['dados'] 并取消缩进以下代码。它会工作

【讨论】:

非常感谢。命令 (linha = resposta.json()['dados']) 运行良好。但是当我尝试在“dados”中获取字典时,它不起作用(linha2 = resposta.json()['dados/ultimoStatus'])。它有这个错误: KeyError: KeyError: 'dados/ultimoStatus' 为了在另一个字典中访问一个字典,命令应该是另一个吗? 您不能通过a_dict['foo/bar'] 访问密钥foo > bar。你想要的是linha2 = resposta.json()['dados']['ultimoStatus']

以上是关于如何使用 JSON 正确读取 API 并创建列表?在 Python 中的主要内容,如果未能解决你的问题,请参考以下文章

如何仅使用 JavaScript 正确读取 json 文件 [重复]

无法使用嵌入式对象发布 JSON - 它读取并存储除对象列表 (OneToMany) 之外的所有内容 - Spring Boot API (+ hibernate)

如何从一个文件中读取多个 JSON 数据列表到 Pandas

如何在 Ionic 中正确读取 JSON 文件?

如何在flutter中从API创建多个复选框

如何将数组数据编码为json?