Search code examples
pandaspython-requestsgoogle-api-python-client

Parsing Requests Module Response JSON


I am trying to use the [OpenMeteo API][1] to download CSVs via script. Using their API Builder, and their click-able site, I am able to do it for a single site just fine.

In trying to write a function to accomplish this in a loop via the requests library, I am stumped. I CANNOT get the json data OUT of the type requests.model.Response and into a JSON or even better CSV/ Pandas format.

Cannot parse the requests module response to anything. It appears to succeed ("200" response), and have data, but I cannot get it out of the response format!

latitude= 60.358
longitude= -148.939

request_txt=r"https://archive-api.open-meteo.com/v1/archive?latitude="+ str(latitude)+"&longitude="+ str(longitude)+ "&start_date=1959-01-01&end_date=2023-02-10&models=era5_land&daily=temperature_2m_max,temperature_2m_min,temperature_2m_mean,shortwave_radiation_sum,precipitation_sum,rain_sum,snowfall_sum,et0_fao_evapotranspiration&timezone=America%2FAnchorage&windspeed_unit=ms"


r=requests.get(request_txt).json()


  [1]: https://open-meteo.com/en/docs/historical-weather-api

Solution

  • The url needs format=csv added as a parameter. StringIO is used to download as an object into memory.

    from io import StringIO
    
    import pandas as pd
    import requests
    
    
    latitude = 60.358
    longitude = -148.939
    
    url = ("https://archive-api.open-meteo.com/v1/archive?"
           f"latitude={latitude}&"
           f"longitude={longitude}&"
           "start_date=1959-01-01&"
           "end_date=2023-02-10&"
           "models=era5_land&"
           "daily=temperature_2m_max,temperature_2m_min,temperature_2m_mean,"
           "shortwave_radiation_sum,precipitation_sum,rain_sum,snowfall_sum,"
           "et0_fao_evapotranspiration&"
           "timezone=America%2FAnchorage&"
           "windspeed_unit=ms&"
           "format=csv")
    
    with requests.Session() as request:
        response = request.get(url, timeout=30)
    if response.status_code != 200:
        print(response.raise_for_status())
    
    
    df = pd.read_csv(StringIO(response.text), sep=",", skiprows=2)
    print(df)