Cargando datos con API-REST

¿Qué es API-REST?

API es la Application Programming Interface, es decir nuestra forma de interactuar con una aplicación. REST quiere decir REpresentational State Transfer. Normalmente cuando hablamos de REST, estamos hablando de una interfaz para obtener datos usando directamente HTTP, es decir es un tipo de web API.

De manera sencilla podemos decir que es una Interfaz con la que se interactúa mediante URLs normalmente para obtener datos.

La principal diferencia entre esto y una URL común, es que la URL de una página web devolverá algo que tu navegador puede interpretar y mostrar de forma "bonita", mientras que una API web mandará datos o instrucciones útiles para ti o tu ordenador.


In [1]:
# preserve
from IPython.display import HTML

Veamos la respuesta a una página web clásica


In [ ]:

Veamos la respuesta de una web api


In [ ]:

En definitiva, cuando utilizamos una WEB API, están involucrados:

  • Cliente: realiza la petición a través de la url
  • Servidor: da una respuesta a la url recibida
  • Protocolo: se establece en la especificación de la API

¿Cómo utilizar una API?

El uso de WEB APIs permite: obtener información que sería cosotsa de obtener y procesar de otra manera (incluso en tiempo real).

En algunas ocasiones, la API es pública y cualquiera puede hacer una petición, pero en otras es necesario tener una api key que nos identifica. Por lo tanto, el proceso para obtener datos suele ser:

  1. Comprobar si existe una API-REST para obtener dichos datos
  2. Obtener una api key en caso de que sea necesaria
  3. Leer la especificación de la API para saber cómo componer la URL y como interpretar la respuesta
  4. Utilizar la API, en nuestro caso desde Python.

Ejemplo: descargando datos de AEMET

Esta es la página principal de su API:

https://opendata.aemet.es/centrodedescargas/inicio

Aquí podemos encontrar: información general, el lugar donde obtener nuestra API key, una interfaz para acceder a los datos para público general


In [ ]:

Módulo requests

Aunque existen otras formas y librería para trabajar con HTTP en Python, el módulo requests está específicamente pensado para trabajar con APIs web.

Como siempre hasta ahora, lo primero es importarlo:


In [ ]:

Necesitaremos cargar nuesta API key, lo más cómodo es almacenarla en un fichero y cargarla desde ahí. Creemos una función para leerla:


In [6]:
# preserve
def load_api_key(file):
    """Returns the contents in the file without the final line break
    """
    with open(file, 'r') as f:
        api_key = f.read().rstrip()
    return api_key

In [ ]:
# cargamos la api_key

Debemos saber cuál es la url a la que vamos a hacer la petición:


In [ ]:
# Fijamos la url y los parámetros
# Predicción costera de Asturias, Cantabria y País Vasco debemos introducir
# https://opendata.aemet.es/opendata/api/prediccion/maritima/costera/costa/41

Por último, lanzamos la petición:


In [ ]:
# Lanzamos la request

Comprobando la respuesta:


In [ ]:
# Vemos la respuesta

Vemos que hemos obtenido una respuesta con código 200, esto quiere decir, en el código habitual de las API-REST, que todo ha ido bien. De hecho, es conveniente ver que todo ha ido bien antes de hacer nada más:


In [ ]:
# código de estado

Otra información que podemos obtener es, por ejemplo;


In [12]:
# preserve
# Tiempo en procesar la petición
print("Elapsed: ", response.elapsed)
# Información del servidor
print("Headers: ", response.headers)


Elapsed:  0:00:00.150871
Headers:  {'Date': 'Sun, 04 Jun 2017 21:05:01 GMT', 'Server': 'Apache/2.2.15 (CentOS)'}

Pero... ¿dónde están nuestros datos?


In [ ]:

¡Parece que esto es un json!


In [ ]:

Efectivamente, la mayoría de las WEB APIs devuelven json o xml. Pero, otra vez... ¿dónde están nuestros datos?


In [ ]:


In [ ]:


In [ ]:


In [ ]:

En definitiva, podríamos reagrupar todo lo anterior como:


In [19]:
# preserve

from warnings import warn

def get_prediction_for_cantabria(api_key):
    url = "https://opendata.aemet.es/opendata/api/prediccion/maritima/costera/costa/41"
    querystring = {"api_key": api_key}
    
    response = requests.get(url, params=querystring, verify=False)
    
    prediction = None
     
    if response.status_code == requests.codes.ok:
        r_data = requests.get(content['datos'], verify=False)
        if r_data.status_code == requests.codes.ok:
            data = r_data.json()
            prediction = data[0]['prediccion']
    
    elif response.status_code == requests.codes.TOO_MANY_REQUESTS:
        warn('Too many requests')
        
    elif response.status.code == requests.codes.NOT_FOUND:
        warn('No data for the response')
        
    else:
        warn('Code error {}'.format(response.status_code))
            
    return prediction

Conclusiones

  • Si el proveedor de los datos dispone de una API-REST podemos aprovecharla para automatizar la obtención de los mismos
  • En la mayoría de los casos necesitaremos una api-key y conocer la especificación de la API
  • A través de la URL podemos configurar nuestra petición
  • El módulo requests nos permite realizar este proceso en Python de manera secilla


¡Síguenos en Twitter!


Este notebook ha sido realizado por: Álex Sáez y Francisco Navarro



<span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Curso de introducción a Python: procesamiento y análisis de datos</span> por <span xmlns:cc="http://creativecommons.org/ns#" property="cc:attributionName">Juan Luis Cano Rodriguez, Alejandro Sáez Mollejo y Francisco J. Navarro Brull</span> se distribuye bajo una Licencia Creative Commons Atribución 4.0 Internacional.
La mayor parte de material de este curso es un resumen adaptado del magnífico Curso de AeroPython realizado por: Juan Luis Cano y Álex Sáez