自分のキャリアをあれこれ考えながら、Pythonで様々なデータを分析していくブログです

PythonでJSON形式の文字列から必要な項目を抽出する2つの方法

Python
Python

ちょうど昨日ですが大きいサイズのJSONのような文字列を処理する必要があったのですが、Pythonで処理するには重かったのでどう対応したのかまとめておきます。

JSONデータの文字数としては22万文字ほどになります。

最終的にjsonライブラリを使うのではなく、正規表現で必要な文字列を抽出する方式で目的達成しました。

JSON形式のデータ処理の試行錯誤のプロセスとしては下記になります。

  1. Jupyter notebookからimport jsonとjson.loads(JSONデータ)で読み込もうとしたがフリーズ。
  2. How to speed up process of loading and reading JSON files in Python?を参考にimport jsonではなく、import ujsonもしくは import orjsonを使うが変わらずフリーズ。
  3. jupyter notebookからではなくipythonで実行すると時間はかかるがフリーズしなかったが、JSONDecodeErrorが発生。22万文字を見直すのは辛いので他の方法を考えることになった。

    JSONDecodeError: Expecting property name enclosed in double quotes: line 2 column 2 (char 2)

  4. 正規表現で必要な情報を抽出する方法に変更するとフリーズもしないし時間もそれほどかからず目的達成

json.loadsでデータ処理する方法も便利なので方法として記載しておきます。

サンプルデータとして下記JSON文字列を用意しました。
タスクとしてはJSON文字列からURLの値(https://url1.xxx.xxxhttps://url2.yyy.yyy) を抽出すると仮定します。

JSONデータ
json_str="""
{
"data1":{
  "info1": [
    1,
    2,
    3
  ],
  "info2": true,
  "info3": "gold",
  "info4": null,
  "info5": 123,
  "info6": {
    "food": "banana",
    "place": "Tokyo"
  },
  "url": "https://url1.xxx.xxx",
  "info7": "free comments"
},
"data2":{
  "info1": [
    4,
    5,
    6
  ],
  "info2": false,
  "info3": "white",
  "info4": 1,
  "info5": 456,
  "info6": {
    "food": "tomato",
    "place": "Osaka"
  },
  "url": "https://url2.yyy.yyy",
  "info7": "free comments2"
}
}
"""
スポンサーリンク

方法1: JSONデータとして読み込んだ後に欲しい項目を取得する方法

JSONデータからURL情報を抜き出したいと思います。(https://url1.xxx.xxxhttps://url2.yyy.yyy)

JSONデータの読み込み
import json # ujsonやorjsonでもOK
json_data = json.loads(json_str)
json_data
Out[0]
{'data1': {'info1': [1, 2, 3],
  'info2': True,
  'info3': 'gold',
  'info4': None,
  'info5': 123,
  'info6': {'food': 'banana', 'place': 'Tokyo'},
  'url': 'https://url1.xxx.xxx',
  'info7': 'free comments'},
 'data2': {'info1': [4, 5, 6],
  'info2': False,
  'info3': 'white',
  'info4': 1,
  'info5': 456,
  'info6': {'food': 'tomato', 'place': 'Osaka'},
  'url': 'https://url2.yyy.yyy',
  'info7': 'free comments2'}}
data1の情報を見る
json_data["data1"]
Out[0]
{'info1': [1, 2, 3],
 'info2': True,
 'info3': 'gold',
 'info4': None,
 'info5': 123,
 'info6': {'food': 'banana', 'place': 'Tokyo'},
 'url': 'https://url1.xxx.xxx',
 'info7': 'free comments'}
data1のurlの情報を見る
json_data["data1"]["url"]
Out[0]
'https://url1.xxx.xxx'
data1とdata2からurl情報を抽出する
for key in json_data:
    print(json_data[key]["url"])
Out[0]
https://url1.xxx.xxx
https://url2.yyy.yyy

出来ました。データ量が少ない場合は分かりやすくて良い方法だと思います。

スポンサーリンク

方法2: JSON形式の文字列から正規表現で目的の項目を取得する方法

正規表現で取得してみます。

正規表現で使っている(https[^"]*)の[^"]という部分はダブルクオテーション以外の文字という意味になります。

import re

# 正規表現
pattern = r'"url":\s"(https[^"]*)"'

# マッチする全ての文字列を取得
matches = re.findall(pattern, json_str)

# 中身を表示。URLに必要ない文字列が含まれていた場合はreplaceする
for i in matches:
    print(i.replace('\\', ''))
Out[0]
https://url1.xxx.xxx
https://url2.yyy.yyy

取得できました。

スポンサーリンク

まとめ

JSON形式のデータが大きすぎると私の環境だとjson.loads()する時点でフリーズしたり読み込みにかなり時間がかかってしまいました。

正規表現で取得することによる不具合はいまのところ起きていませんが、個人的にはjsonライブラリで取得する方が美しいので好みです 笑

タイトルとURLをコピーしました