尝试解析某些json时,我始终收到以下错误:
Traceback (most recent call last):
File "/Users/batch/projects/kl-api/api/helpers.py", line 37, in collect_youtube_data
keywords = channel_info_response_data['items'][0]['brandingSettings']['channel']['keywords']
KeyError: 'brandingSettings'
在将其分配给变量之前,如何确保检查JSON输出的密钥?如果找不到密钥,那么我只想分配一个默认值。下面的代码:
try:
channel_id = channel_id_response_data['items'][0]['id']
channel_info_url = YOUTUBE_URL + '/channels/?key=' + YOUTUBE_API_KEY + '&id=' + channel_id + '&part=snippet,contentDetails,statistics,brandingSettings'
print('Querying:', channel_info_url)
channel_info_response = requests.get(channel_info_url)
channel_info_response_data = json.loads(channel_info_response.content)
no_of_videos = int(channel_info_response_data['items'][0]['statistics']['videoCount'])
no_of_subscribers = int(channel_info_response_data['items'][0]['statistics']['subscriberCount'])
no_of_views = int(channel_info_response_data['items'][0]['statistics']['viewCount'])
avg_views = round(no_of_views / no_of_videos, 0)
photo = channel_info_response_data['items'][0]['snippet']['thumbnails']['high']['url']
description = channel_info_response_data['items'][0]['snippet']['description']
start_date = channel_info_response_data['items'][0]['snippet']['publishedAt']
title = channel_info_response_data['items'][0]['snippet']['title']
keywords = channel_info_response_data['items'][0]['brandingSettings']['channel']['keywords']
except Exception as e:
raise Exception(e)
答案 0 :(得分:2)
您可以将所有作业都包装为
try:
keywords = channel_info_response_data['items'][0]['brandingSettings']['channel']['keywords']
except KeyError as ignore:
keywords = "default value"
,或者说,使用.has_key(...)
。恕我直言,您最好采用第一种解决方案
答案 1 :(得分:2)
假设您有一个字典,则有两个选项可以处理关键不存在的情况:
1)获取具有默认值的密钥,例如
d = {}
val = d.get('k', 10)
val
将为10,因为没有名为k
的键
2)试用-
d = {}
try:
val = d['k']
except KeyError:
val = 10
这种方式更加灵活,因为您可以在except
块中执行任何操作,如果您真的不在乎它,甚至可以使用pass
语句忽略该错误。
答案 2 :(得分:1)
如何确保检查JSON输出
此时,您的“ JSON输出”只是一个普通的本地Python dict
为键分配一个变量之前?如果找不到密钥,那么我只想分配一个默认值
现在您知道自己有一个dict
,浏览dict
方法的官方文档应该会回答以下问题:
https://docs.python.org/3/library/stdtypes.html#dict.get
获取(键[,默认])
如果key在字典中,则返回key的值,否则返回默认值。如果未指定default,则默认为None,因此此方法永远不会引发KeyError。
所以一般情况是:
var = data.get(key, default)
现在,如果您在深层嵌套的字典/列表中可能缺少任何键或索引,则捕获KeyErrors和IndexErrors会更简单:
try:
var = data[key1][index1][key2][index2][keyN]
except (KeyError, IndexError):
var = default
请注意:您的代码段中包含重复的channel_info_response_data['items'][0]['statistics']
和channel_info_response_data['items'][0]['snippet']
表达式。使用中间变量将使您的代码更具可读性,更易于维护,并且速度更快:
# always set a timeout if you don't want the program to hang forever
channel_info_response = requests.get(channel_info_url, timeout=30)
# always check the response status - having a response doesn't
# mean you got what you expected. Here we use the `raise_for_status()`
# shortcut which will raise an exception if we have anything else than
# a 200 OK.
channel_info_response.raise_for_status()
# requests knows how to deal with json:
channel_info_response_data = channel_info_response.json()
# we assume that the response MUST have `['items'][0]`,
# and that this item MUST have "statistics" and "snippets"
item = channel_info_response_data['items'][0]
stats = item["statistics"]
snippet = item["snippet"]
no_of_videos = int(stats.get('videoCount', 0))
no_of_subscribers = int(stats.get('subscriberCount', 0))
no_of_views = int(stats.get('viewCount', 0))
avg_views = round(no_of_views / no_of_videos, 0)
try:
photo = snippet['thumbnails']['high']['url']
except KeyError:
photo = None
description = snippet.get('description', "")
start_date = snippet.get('publishedAt', None)
title = snippet.get('title', "")
try:
keywords = item['brandingSettings']['channel']['keywords']
except KeyError
keywords = ""
您可能还想了解字符串格式(污染字符串很容易出错并且几乎不可读),以及how to pass arguments to requests.get()