Parsing JSON response from API with Python

178 views Asked by At

Goal: Reach the first set of keys/values in the Reviews area

Error: Other error occurred: string indices must be integers - running into this no matter how I try to iterate with an integer through this JSON. I want to be able to build a for loop that help me EVENTUALLY store just one set of keys/values to a Postgres Database

JSON response:

{
"reviews": [
    {
        "id": "SlqmHe5QqR7GPpNADoUpng",
        "url": "https://www.yelp.com/biz/sofresh-tampa-2?adjust_creative=K92cc-wV-   6BEaunuQQ-BqA&hrid=SlqmHe5QqR7GPpNADoUpng&utm_campaign=yelp_api_v3&utm_medium=api_v3_business_reviews&utm_source=K92cc-wV-6BEaunuQQ-BqA",
        "text": "food is delicious!!!!!  prices are ultra reasonable for the great quality .   service was fast & my personal experience was superb.  \nEric at the Westshore...",
        "rating": 5,
        "time_created": "2022-01-07 12:46:41",
        "user": {
            "id": "jWW3MKgZ4KgLmDqIuYxCGg",
            "profile_url": "https://www.yelp.com/user_details?userid=jWW3MKgZ4KgLmDqIuYxCGg",
            "image_url": "https://s3-media3.fl.yelpcdn.com/photo/Fy0nJ-IFeO8ae-AmOoq7Qw/o.jpg",
            "name": "Hannah R."
        }
    },
    {
        "id": "ItgpAb6iV182Pvf4_etM-Q",
        "url": "https://www.yelp.com/biz/sofresh-tampa-2?adjust_creative=K92cc-wV-6BEaunuQQ-BqA&hrid=ItgpAb6iV182Pvf4_etM-Q&utm_campaign=yelp_api_v3&utm_medium=api_v3_business_reviews&utm_source=K92cc-wV-6BEaunuQQ-BqA",
        "text": "Great place and various locations to grab a quick healthy bite to eat! This was my first time here and I was able to get so many mix-ins along with the...",
        "rating": 4,
        "time_created": "2022-03-28 15:35:21",
        "user": {
            "id": "jVPVdamhMp7_neUT2I-ODA",
            "profile_url": "https://www.yelp.com/user_details?userid=jVPVdamhMp7_neUT2I-ODA",
            "image_url": "https://s3-media2.fl.yelpcdn.com/photo/gioRxeXyjj4PdXP0HIqDGg/o.jpg",
            "name": "Toni T."
        }
    }```
import requests
from requests.exceptions import HTTPError


url = 'https://api.yelp.com/v3/businesses/sofresh-tampa-2/reviews'
api_key = 'Q32IKVXICNApFwtabS5hqrYr6I41BxjO86TpN5ANWqt82apCwG6ed3vcQb91euh8pJF5ZtS27CmEi2SzFbYpjJHBz8L3V_VXtCYb-J6TCM5fugKDGnO3kSa1qrBHYnYx'
headers = {
        'Authorization': 'Bearer %s' % api_key,
    }
reviewCatcher = {
    "id_Review":[],
    "body_Review":[],
    "rating_Review":[],
    "platform_Review":[],
    "locationId_Review":[],
    "userId_Review":[],
    "brandId_Review}":[],
    "timeCreated_Review":[]
    }


try:
    response = requests.get(url, headers=headers)
    json_data = json.loads(response.text)
    reviews = json_data['reviews']
    for items in reviews[1]:
        reviewCatcher['id_Review'].append('{}'.format(items['id']))
        print(reviewCatcher['id_Review'])

except HTTPError as http_err:
    print(f'HTTP error occurred: {http_err}')
except Exception as err:
    print(f'Other error occurred: {err}')```
1

There are 1 answers

0
larsks On

First, you probably want to generate a new api key and discard the one you've posted here in your question.


Next, stop doing this:

except Exception as err:
    print(f'Other error occurred: {err}')```

By suppressing the traceback, you're obscuring the location of the error, making it harder to debug your code. If you remove that over-broad except, you'll get:

Traceback (most recent call last):
  File "/home/lars/tmp/python/yelper.py", line 28, in <module>
    reviewCatcher["id_Review"].append("{}".format(items["id"]))
TypeError: string indices must be integers

If we look at the location of the error, we see:

    for items in reviews[1]:
        reviewCatcher["id_Review"].append("{}".format(items["id"]))
        print(reviewCatcher["id_Review"])

But looking at your JSON data, reviews[1] will be a dictionary. If you iterate over a dictionary, you get a list of keys, so items is going to be id, then url, then text, etc. So when you write:

items["id"]

You get the error:

TypeError: string indices must be integers

Because items is, in fact, a string.

It looks like you probably want to iterate over reviews rather than reviews[1], like this:

    for items in reviews:
        reviewCatcher["id_Review"].append("{}".format(items["id"]))
        print(reviewCatcher["id_Review"])

With this change, running your code produces as output:

['SlqmHe5QqR7GPpNADoUpng']
['SlqmHe5QqR7GPpNADoUpng', 'ItgpAb6iV182Pvf4_etM-Q']
['SlqmHe5QqR7GPpNADoUpng', 'ItgpAb6iV182Pvf4_etM-Q', 'YBPV3cdmSrNKIG47SYYZFA']

And reviewCatcher will contain:

{
  "id_Review": [
    "SlqmHe5QqR7GPpNADoUpng",
    "ItgpAb6iV182Pvf4_etM-Q",
    "YBPV3cdmSrNKIG47SYYZFA"
  ],
  "body_Review": [],
  "rating_Review": [],
  "platform_Review": [],
  "locationId_Review": [],
  "userId_Review": [],
  "brandId_Review}": [],
  "timeCreated_Review": []
}