0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[Python] ネストされた辞書からkeyのリストでvalueを取り出す

Last updated at Posted at 2023-06-30

1. はじめに

書籍情報APIから返ってくるjsonデータが思った以上に扱いにくくて、個別にキーを指定して必要な情報を抽出するのは面倒だったので、キーを羅列したリストを用意して、for文で回せるようにしてみました。

2. ネストされた辞書の例

2.1. 書籍情報APIから返ってくるjsonデータ

例として以下のコードで返ってくるjsonデータを見てみますが、蔵書目録を作るという程度の目的であれば、必要なデータは一部で済むことになります。

ISBNを使ってAPIから書籍情報を抽出
import json
import urllib
import pprint

url = f'https://api.openbd.jp/v1/get?isbn=9784873117584'
urlopen = urllib.request.urlopen(url)
bookdata = json.loads(urlopen.read().decode('utf-8'))
pprint.pprint(bookdata)
openBDから返ってきたjsonデータ
[{'hanmoto': {'datecreated': '2016-08-31 16:02:14',
              'datemodified': '2016-08-31 16:02:14'},
  'onix': {'CollateralDetail': {'TextContent': [{'ContentAudience': '00',
                                                 'Text': 'ディープラーニングの本格的な入門書。外部のライブラリに頼らずPython '
                                                         '3によってゼロからディープラーニングを作成できる。',
                                                 'TextType': '02'},
                                                {'ContentAudience': '00',
                                                 'Text': '実際にシステムを作りながらディープラーニングを学ぶ!\n'
                                                         'ディープラーニングの本格的な入門書。外部のライブラリに頼らずに、Python '
                                                         '3によってゼロからディープラーニングを作ることで、ディープラーニングの原理を楽しく学びます。ディープラーニングやニューラルネットワークの基礎だけでなく、誤差逆伝播法や畳み込みニューラルネットワークなども実装レベルで理解できます。ハイパーパラメータの決め方や重みの初期値といった実践的なテクニック、Batch '
                                                         'NormalizationやDropout、Adamといった最近のトレンド、自動運転や画像生成、強化学習などの応用例、さらには、なぜディープラーニングは優れているのか? '
                                                         'なぜ層を深くすると認識精度がよくなるのか? '
                                                         'といった“Why”に関する問題も取り上げます。',
                                                 'TextType': '03'}]},
           'DescriptiveDetail': {'Audience': [{'AudienceCodeType': '22',
                                               'AudienceCodeValue': '00'}],
                                 'Contributor': [{'ContributorRole': ['A01'],
                                                  'PersonName': {'collationkey': 'サイトウ '
                                                                                 'コウキ',
                                                                 'content': '斎藤 '
                                                                            '康毅'},
                                                  'SequenceNumber': '1'}],
                                 'Extent': [{'ExtentType': '11',
                                             'ExtentUnit': '03',
                                             'ExtentValue': '320'}],
                                 'Language': [{'CountryCode': 'JP',
                                               'LanguageCode': 'jpn',
                                               'LanguageRole': '01'}],
                                 'ProductComposition': '00',
                                 'ProductForm': 'BA',
                                 'ProductFormDetail': 'B108',
                                 'Subject': [{'MainSubject': '',
                                              'SubjectCode': '3055',
                                              'SubjectSchemeIdentifier': '78'},
                                             {'SubjectCode': '20',
                                              'SubjectSchemeIdentifier': '79'}],
                                 'TitleDetail': {'TitleElement': {'Subtitle': {'collationkey': 'パイソンデマナブディープラーニングノリロントジッソウ',
                                                                               'content': 'Pythonで学ぶディープラーニングの理論と実装'},
                                                                  'TitleElementLevel': '01',
                                                                  'TitleText': {'collationkey': 'ゼロカラツクルディープラーニング',
                                                                                'content': 'ゼロから作るDeep '
                                                                                           'Learning'}},
                                                 'TitleType': '01'}},
           'NotificationType': '03',
           'ProductIdentifier': {'IDValue': '9784873117584',
                                 'ProductIDType': '15'},
           'ProductSupply': {'SupplyDetail': {'Price': [{'CurrencyCode': 'JPY',
                                                         'PriceAmount': '3400',
                                                         'PriceType': '03'}],
                                              'ProductAvailability': '99',
                                              'ReturnsConditions': {'ReturnsCode': '03',
                                                                    'ReturnsCodeType': '04'}}},
           'PublishingDetail': {'Imprint': {'ImprintIdentifier': [{'IDValue': '87311',
                                                                   'ImprintIDType': '19'},
                                                                  {'IDValue': '0742',
                                                                   'ImprintIDType': '24'}],
                                            'ImprintName': 'オライリー・ジャパン'},
                                'Publisher': {'PublisherIdentifier': [{'IDValue': '274',
                                                                       'PublisherIDType': '19'},
                                                                      {'IDValue': '0742',
                                                                       'PublisherIDType': '24'}],
                                              'PublisherName': '株式会社オーム社',
                                              'PublishingRole': '01'},
                                'PublishingDate': [{'Date': '20160924',
                                                    'PublishingDateRole': '01'}]},
           'RecordReference': '9784873117584'},
  'summary': {'author': '斎藤康毅/著',
              'cover': '',
              'isbn': '9784873117584',
              'pubdate': '20160924',
              'publisher': 'オライリー・ジャパン',
              'series': '',
              'title': 'ゼロから作るDeep Learning',
              'volume': ''}}]

2.2. 書籍情報APIのjsonデータを扱う上での問題点

書籍情報APIのjsonデータの特徴として以下の点が挙げられます。

  1. ネストが深い
  2. dictとlistが混ざっている
  3. キーが常に存在するとは限らない

そして上記の理由から、以下のような問題が発生します。

  1. キーを事前に用意してfor文で回すことができない
  2. キーが存在しない場合にtry-exceptで補足しないとKeyErrorになる

そのため上記問題点を解消するために、辞書のキーと配列のインデックスをまとめたリストを用意しておいて、valueを取り出す関数を検討しました。

3. 作成した関数

def get_value_from_json(self, parent_data, key_list):
    value = ''
    for key in key_list:
        if type(parent_data) is dict:
            value = parent_data.get(key, '')
        elif type(parent_data) is list and type(key) is int:
            value = parent_data[key] if key < len(parent_data) else ''
        else:
            value = ''
        if value == '':
            break
        parent_data = value
    return value
出力例
get_value_from_json(bookdata, [])
# 

get_value_from_json(bookdata, [0, 'onix', 'DescriptiveDetail', 'TitleDetail', 'TitleElement', 'TitleText', 'content'])
# 'ゼロから作るDeep Learning'

get_value_from_json(bookdata, [0, 'summary', 'author'])
# '斎藤康毅/著'

get_value_from_json(bookdata, ['null']) # ※存在しないキー
# 
  • 関数では最初にresult = Noneとして、第二引数のリストが空だった場合に''を返します(Noneでもいいですが、処理によっては文字列のNoneが情報として入るので''の方が使い勝手が良い気がしています)。
  • for文でキーorインデックスのリストを1つずつ処理していきますが、valueの型をdictlistか判定して、キーかインデックスが有効な値であればvalueresultに代入していき、最後に代入したvalueを返します。
  • キーorインデックスが有効でなければresultにはNoneを代入して、for文をbreakして、Noneを返します。

4. 活用例

この関数を用意しておくことで、以下のような形で書籍情報APIのjsonデータから情報を抽出できます。

keys = [[0, 'onix', 'DescriptiveDetail', 'TitleDetail', 'TitleElement', 'TitleText', 'content'],
        [0, 'onix', 'DescriptiveDetail', 'TitleDetail', 'TitleElement', 'Subtitle', 'content'],
        [0, 'summary', 'author'],
        [0, 'summary', 'publisher'],
        [0, 'onix', 'CollateralDetail', 'TextContent', 0, 'Text'],
        [0, 'summary', 'pubdate'],
        [0, 'summary', 'isbn']]

for key in keys:
    print(get_value_from_json(bookdata, key))
出力
ゼロから作るDeep Learning
Pythonで学ぶディープラーニングの理論と実装
斎藤康毅/著
オライリー・ジャパン
ディープラーニングの本格的な入門書。外部のライブラリに頼らずPython 3によってゼロからディープラーニングを作成できる。
20160924
9784873117584
0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?