Извлечение информации из json .файла, где поле находится в разных местах в разных условиях. - PullRequest
0 голосов
/ 02 мая 2020

Я извлекаю из вложенного json .file в python 3.8 с большим количеством диктов и получаю следующую ключевую ошибку:

extended_tweet = data [str (i)] ['extended_tweet' ] ['full_text'] KeyError: 'extended_tweet'

Как искать во вложенных json .file-файлах поле, которое скрыто в разных структурах в каждом диктовке? Я думаю, что мой негибкий способ определения полей мешает правильному выводу, но я не могу понять, как это исправить.

for i in data:
    date = data[str(i)]['created_at']
    account = data[str(i)]['user']['name']
    location = data[str(i)]['user']['location']
    truncated = data[str(i)]['truncated']
    tweet = data[str(i)]['text']
    extended_tweet = data[str(i)]['extended_tweet']['full_text']
    retweeted_status = data[str(i)]['retweeted_status']['extended_tweet']['full_text']
    if truncated == 'True':
        print(truncated, date, account, location, extended_tweet)
    elif 'RT' in tweet:
        print(truncated, date, account, location, retweeted_status)
    else:
        print(truncated, date, account, location, tweet)

Вот пример одного из диктов в моем json .file , Число «3» обозначает диктовку, и мне нужно получить данные из поля extended_tweet.full_text. Каждый указатель пути отображает путь x.extended_tweet.full_text. Но если я использую это, я получаю ошибку, показанную выше.

"3": {
  "created_at": "time",
  "id": id,
  "id_str": "id",
  "text": "text",
  "display_text_range": [
   0,
   140
  ],
  "source": "",
  "truncated": true,
  "in_reply_to_status_id": null,
  "in_reply_to_status_id_str": null,
  "in_reply_to_user_id": null,
  "in_reply_to_user_id_str": null,
  "in_reply_to_screen_name": null,
  "user": {
   "id": ,
   "id_str": "",
   "name": "",
   "screen_name": "name",
   "location": "location",
   "url": "url",
   "description": "description",
   "translator_type": "none",
   "derived": {
    "locations": [
     {
      "country": "country",
      "country_code": "land",
      "locality": "locality",
      "region": "region",
      "full_name": "full_name",
      "geo": {
       "coordinates": [
        number,
        number
       ],
       "type": "point"
      }
     }
    ]
   },
   "protected": false,
   "verified": true,
   "followers_count": number,
   "friends_count": number,
   "listed_count": number,
   "favourites_count": number,
   "statuses_count": number,
   "created_at": "time",
   "utc_offset": null,
   "time_zone": null,
   "geo_enabled": false,
   "lang": null,
   "contributors_enabled": false,
   "is_translator": false,
   "profile_background_color": "number",
   "profile_background_image_url": "gif",
   "profile_background_image_url_https": "link",
   "profile_background_tile": true,
   "profile_link_color": "607696",
   "profile_sidebar_border_color": "FFFFFF",
   "profile_sidebar_fill_color": "EFEFEF",
   "profile_text_color": "333333",
   "profile_use_background_image": true,
   "profile_image_url": "link",
   "profile_image_url_https": "link",
   "profile_banner_url": "bannerurl",
   "default_profile": false,
   "default_profile_image": false,
   "following": null,
   "follow_request_sent": null,
   "notifications": null
  },
  "geo": null,
  "coordinates": null,
  "place": null,
  "contributors": null,
  "is_quote_status": false,
  "extended_tweet": {
   "full_text": "full_text",

1 Ответ

0 голосов
/ 03 мая 2020

Привет, тестер :) Я поместил ваш пример JSON в файл, поместил некоторые значения в различные поля и добавил объект retweeted_status, затем в основном запустил ваш код следующим образом:

import json
import os

with open( os.path.join(os.path.realpath('.'), 'src/test/x.json') ) as file1:
    data = json.load(file1)

for i in data:
    date = data[str(i)]['created_at']
    account = data[str(i)]['user']['name']
    location = data[str(i)]['user']['location']
    truncated = data[str(i)]['truncated']
    tweet = data[str(i)]['text']
    extended_tweet = data[str(i)]['extended_tweet']['full_text']
    retweeted_status = data[str(i)]['retweeted_status']['extended_tweet']['full_text']
    if truncated == 'True':
        print(truncated, date, account, location, extended_tweet)
    elif 'RT' in tweet:
        print(truncated, date, account, location, retweeted_status)
    else:
        print(truncated, date, account, location, tweet)

Работает хорошо для меня и печатает:

True time  location text

Вот JSON Я положил в файл:

{"3": {
    "created_at": "time",
    "id": 1234,
    "id_str": "id",
    "text": "text",
    "display_text_range": [
     0,
     140
    ],
    "source": "",
    "truncated": true,
    "in_reply_to_status_id": null,
    "in_reply_to_status_id_str": null,
    "in_reply_to_user_id": null,
    "in_reply_to_user_id_str": null,
    "in_reply_to_screen_name": null,
    "user": {
     "id": 1234,
     "id_str": "",
     "name": "",
     "screen_name": "name",
     "location": "location",
     "url": "url",
     "description": "description",
     "translator_type": "none",
     "derived": {
      "locations": [
       {
        "country": "country",
        "country_code": "land",
        "locality": "locality",
        "region": "region",
        "full_name": "full_name",
        "geo": {
         "coordinates": [
          100,
          100
         ],
         "type": "point"
        }
       }
      ]
     },
     "protected": false,
     "verified": true,
     "followers_count": 100,
     "friends_count": 100,
     "listed_count": 100,
     "favourites_count": 100,
     "statuses_count": 100,
     "created_at": "time",
     "utc_offset": null,
     "time_zone": null,
     "geo_enabled": false,
     "lang": null,
     "contributors_enabled": false,
     "is_translator": false,
     "profile_background_color": "number",
     "profile_background_image_url": "gif",
     "profile_background_image_url_https": "link",
     "profile_background_tile": true,
     "profile_link_color": "607696",
     "profile_sidebar_border_color": "FFFFFF",
     "profile_sidebar_fill_color": "EFEFEF",
     "profile_text_color": "333333",
     "profile_use_background_image": true,
     "profile_image_url": "link",
     "profile_image_url_https": "link",
     "profile_banner_url": "bannerurl",
     "default_profile": false,
     "default_profile_image": false,
     "following": null,
     "follow_request_sent": null,
     "notifications": null
    },
    "geo": null,
    "coordinates": null,
    "place": null,
    "contributors": null,
    "is_quote_status": false,
    "extended_tweet": {
     "full_text": "full_text"
    },
    "retweeted_status": {
        "extended_tweet": {
            "full_text": "full_text"
        }
       }
   }}

Глядя на полные данные, ясно, что иногда элементы не существуют , Способ обработки пропущенных ключей без использования исключений заключается в использовании метода dict get. Этот метод позволяет вернуть значение по умолчанию, если ключ отсутствует. Вот код, который обрабатывает отсутствующие элементы в расширенных и ретвитнутых твитах, не вызывая исключений, и печатает то, что отсутствует. Этот код обрабатывает все 499 твитов в ваших данных.

full_tweet = data[str(i)]
extended_tweet = full_tweet.get('extended_tweet', 'extended_tweet missing')
if extended_tweet != 'extended_tweet missing':
    extended_tweet = extended_tweet.get('full_text', 'full_text missing')
retweeted_status = full_tweet.get('retweeted_status', 'retweeted_status missing')
if retweeted_status != 'retweeted_status missing':
    retweeted_status = retweeted_status.get('extended_tweet', 'extended_tweet missing')
    if retweeted_status != 'extended_tweet missing':
        retweeted_status = retweeted_status['full_text']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...