【问题标题】:Iterate JSON in Python在 Python 中迭代 JSON
【发布时间】:2019-10-24 05:23:16
【问题描述】:

我正在尝试从以 JSON 对象形式返回数据的 API 中提取数据。我有 API 调用,它返回看起来像这样的数据(为简洁起见,此处缩短)


   "status":"OK",
   "copyright":"Copyright (c) 2017 Pro Publica Inc. All Rights Reserved.",
   "results":[
      {
         "num_results": 10,
         "offset": 0,
         "bills": [
              {
                 "bill_id": "hr2739-113",
                 "bill_type": "hr",
                 "number": "H.R.2739",
                 "bill_uri": "https://api.propublica.org/congress/v1/113/bills/hr2739.json",
                 "title": "Efficient Use of Government Spectrum Act of 2013",
                 "sponsor_title": "Rep.",
                 "sponsor_id": "M001163",
                 "sponsor_name": "Doris Matsui",
                 "sponsor_state": "CA",
                 "sponsor_party": "D",
                 "sponsor_uri": "https://api.propublica.org/congress/v1/members/M001163.json",
                 "gpo_pdf_uri": "http://www.gpo.gov/fdsys/pkg/BILLS-113hr2739ih/pdf/BILLS-113hr2739ih.pdf",
                 "congressdotgov_url": "https://www.congress.gov/bill/113th-congress/house-bill/2739",
                 "govtrack_url": "https://www.govtrack.us/congress/bills/113/hr2739",
                 "introduced_date": "2013-07-18",
                 "committees": "House Armed Services Committee",
                 "committee_codes": ["HSAS","HSIF"],
                 "subcommittee_codes": ["HSAS26","HSIF16"],
                 "primary_subject": "Science, Technology, Communications",
                 "summary_short": "Efficient Use of Government Spectrum Act of 2013 - Directs the Federal Communications Commission (FCC), within three years after enactment of the Middle Class Tax Relief and Job Creation Act of 2012, to: (1) reallocate electromagnetic spectrum between the frequencies from 1755 to 1780 megahertz (currently, such frequencies are occupied by the Department of Defense [DOD] and other federal agencies); and (2) as part of the competitive bidding auctions required by such Act, grant new initial lic...",
                 "latest_major_action_date": "2013-08-29",
                 "latest_major_action": "Referred to the Subcommittee on Intelligence, Emerging Threats & Capabilities."
              },
                           {
                 "bill_id": "hr3355-113",
                 "bill_type": "hr",
                 "number": "H.R.3355",
                 "bill_uri": "https://api.propublica.org/congress/v1/113/bills/hr3355.json",
                 "title": "Reducing Employer Burdens, Unleashing Innovation, and Labor Development Act of 2013",
                 "sponsor_title": "Rep.",
                 "sponsor_id": "G000558",
                 "sponsor_name": "Brett Guthrie",
                 "sponsor_state": "KY",
                 "sponsor_party": "R",
                 "sponsor_uri": "https://api.propublica.org/congress/v1/members/G000558.json",
                 "gpo_pdf_uri": "http://www.gpo.gov/fdsys/pkg/BILLS-113hr3355ih/pdf/BILLS-113hr3355ih.pdf",
                 "congressdotgov_url": "https://www.congress.gov/bill/113th-congress/house-bill/3355",
                 "govtrack_url": "https://www.govtrack.us/congress/bills/113/hr3355",
                 "introduced_date": "2013-10-28",
                 "committees": "House Armed Services Committee",
                 "primary_subject": "Economics and Public Finance",
                 "summary_short": "Reducing Employer Burdens, Unleashing Innovation, and Labor Development Act of 2013 - Expresses the sense of Congress that increasing the competitiveness of U.S. manufacturers will strengthen the national economy. Title I: Investing in America's Workforce - Investing in America's Workforce Act - Amends the Workforce Investment Act of 1998 to require state or local workforce investment systems to use youth activities funds allocated to a local area for programs that provide training, which may...",
                 "latest_major_action_date": "2014-01-24",
                 "latest_major_action": "Referred to the Subcommittee on Intelligence, Emerging Threats & Capabilities."
              },

使用 Python,我正在尝试遍历数据并返回所有值,如下所示:

import requests
import json

r = requests.get({url and credentials here}).text

resp = json.loads(r)


for bill in resp['results']['bills']:
    name = bill['results']['bills']['title']
    type = item['results']['bills']['bill_type']

print(name, type)

但是,每当我尝试运行它时,我都会得到 ​​p>

TypeError: list indices must be integers or slices, not str

为什么我不能将列表索引用作 str?存在大量使用 str 的示例。

【问题讨论】:

  • 可以使用字符串作为键访问字典,但列表必须使用整数或切片(例如:some_list[3:-1])。

标签: python json python-3.x python-requests


【解决方案1】:

json 中的“票据”是一个对象列表(例如 "bills" : [ - 左括号是方括号,表示一个列表)。

你必须使用整数来访问列表的元素,所以你可以说;

resp['results'][0]['bills'][0]

例如,访问第一张账单。

但是,您的代码在循环中有点混乱,bill 变量将包含每张账单的信息,因此您可以直接引用键,例如在第一个结果中循环账单

for bill in resp['results'][0]['bills']:
    name = bill['title']
    type = bill['bill_type']

    print(name, type)

变量“名称”和“类型”将仅包含循环块期间每个账单的详细信息。

你可以嵌套循环来遍历所有结果

for result in resp['results']:
  for bill in result['bills']:
      name = bill['title']
      type = bill['bill_type']

      print(name, type)

【讨论】:

  • 完美!我必须做的唯一编辑是在关于如何嵌套循环的第二个示例中为 for 添加一个冒号。
【解决方案2】:

bill 是一个没有resultsbills 作为字符串索引的json 对象。请尝试以下操作:

for bill in resp['results']['bills']:
    name = bill['title']
    type = item['bill_type']

    print(name, type)

【讨论】:

  • 它不是真正的 JSON 对象,它是一个 Python 字典,其行为与 JSON 对象非常相似。 loads 将 JSON 字符串反序列化为 Python 字典。
【解决方案3】:

在 json 数据中,results 是一个字典列表。 所以首先迭代结果。 然后为每个结果遍历账单以检索账单的名称和类型。

for result in resp['results']:
    for bill in result['bills']:
        name = bill['title']
        type = item['bill_type']
        print(name, type)

【讨论】:

    【解决方案4】:

    同样在您的代码中,名称等于:

    name = bill['results']['bills']['title'] -> resp['results']['bills']['results']['bills']['title']
    

    【讨论】:

      【解决方案5】:

      如果您收到 JSON 响应,请找到以下两种解析方法。

      方法 1:正常方式 - 这是您正在尝试的方法

      import requests
      
      
      resp = requests.get(url="url",auth="cred").json()
      
      for bill in resp['results'][0]['bills']:
          bill_name = bill['title']
          bill_type = bill['bill_type']
      
      print(bill_name, bill_type)
      

      方法 2:访问 json 响应的更简洁方法

      for bill_dict in resp.get("results", []):  # returns None if "results" field is not found
          for bill in bill_dict.get('bills', []): 
              bill_name = bill.get('title')  # None is assigned to bill_name if key 'title' is not found
              bill_type = bill.get('bill_type')  # None is assigned to bill_name if key 'title' is not found error OR you can assign default value if key is not found Ex: bill.get('bill_type', 'bill type unavailable')
      
      print(bill_name, bill_type)
      

      还有很多其他方法。

      【讨论】:

      • 对于方法 2:应该是 resp.get("results", []) 和 bill_dict.get('bills', []) 因为如果没有结果或账单,您将得到 None but NoneType对象不可迭代。
      • 你是绝对正确的,我在我的代码注释中添加了但不知何故错过了在这里添加这一点,谢谢你的指出。
      猜你喜欢
      • 2013-09-19
      • 2017-11-22
      • 1970-01-01
      • 1970-01-01
      • 2013-02-26
      • 2012-12-14
      • 1970-01-01
      • 2017-11-02
      • 2018-04-18
      相关资源
      最近更新 更多