¡Esta es una revisión vieja del documento!
Tabla de Contenidos
Crear un cliente HTTP con requests
Módulo perteneciente al curso Python avanzado para proyectos de seguridad
Poder interactuar con una API RESTful basadas en HTTP es una tarea cada vez más común en proyectos en cualquier lenguaje de programación.
En Python, también tenemos la opción de interactuar con una API REST de una manera simple con el módulo requests. En esta sección, revisamos las diferentes formas en que podemos interactuar con una API basada en HTTP utilizando el paquete de requests de Python.
Introducción al módulo requests
Una de las mejoras opciones dentro del ecosistema de Python para realizar peticiones HTTP es la librería de terceros requests. Puede instalar la biblioteca de solicitudes en su sistema de una manera fácil con el comando pip:
pip install requests
Este módulo está disponible en el repositorio oficial de python PyPi.
Documentación oficial del módulo requests
Para probar el módulo en nuestro script, solo tiene que importarlo como los otros módulos. Básicamente, requests es un contenedor de urllib junto con otros módulos de Python para proporcionarnos métodos con los cuales realizar peticiones a un sitio web o a una API REST, ya que contamos con los métodos “POST”, “GET”, “PUT”, “PATCH”, “DELETE” que son todos los métodos disponibles para comunicarse con una API RESTful.
Este módulo tiene una forma muy simple de implementación, por ejemplo, una petición GET usando el módulo requests sería:
>>> import requests >>> response = requests.get('http://www.python.org')
Comprobar respuesta de una petición
Como podemos ver aquí, el método request.get() está devolviendo un objeto response que contiene la respuesta. En este objeto encontrará toda la información correspondiente a la respuesta de nuestra petición. Estas son las principales propiedades y métodos que ofrece el objeto de respuesta, en nuestro caso llamado response:
response.status_code: este es el código HTTP devuelto por el servidor.response.content: Aquí encontraremos el contenido de la respuesta del servidor.response.json(): en el caso de que la respuesta sea un JSON, este método serializa la cadena y devuelve una estructura de diccionario con la estructura JSON correspondiente. En el caso de no recibir un JSON para cada respuesta, el método devolvería una excepción que podríamos controlar.
Podemos acceder a las propiedades del objeto de respuesta para verificar el código de estado, la url y el tipo de contenido:
>>> response.status_code 200 >>> response.reason 'OK' >>> response.url 'http://www.python.org' >>> response.headers['content-type'] 'text/html; charset=utf-8'
También podemos acceder a las propiedades de las cabeceras a través del objeto de respuesta donde podemos ver que el user-agent corresponde a la versión de la librería requests que estamos utilizando:
>>> response.request.headers {'User-Agent': 'python-requests/2.23.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}
Obtener el fichero robots.txt de un dominio con el módulo requests
En el siguiente ejemplo utilizamos el módulo requests para obtener el fichero robots.txt de un domino con una simple petición GET con el módulo requests. Puede encontrar el siguiente código en el archivo leer_web_robots.py:
import requests import sys def main(url): robot_url = f'{url}/robots.txt' response = requests.get(robot_url) print(response.text) if __name__ == "__main__": url = sys.argv[1] main(url)
Para ejecutar el script anterior necesitamos pasar como parámetro el dominio del cual queremos obtener el fichero robots.txt.
En este ejemplo estamos extrayendo la información del dominio www.python.org:
$ python leer_web_robots.py http://www.python.org
Resultado de la ejecución del script:
# Directions for robots. See this URL: # http://www.robotstxt.org/robotstxt.html # for a description of the file format. User-agent: HTTrack User-agent: puf User-agent: MSIECrawler Disallow: / # The Krugle web crawler (though based on Nutch) is OK. User-agent: Krugle Allow: / Disallow: /~guido/orlijn/ Disallow: /webstats/ # No one should be crawling us with Nutch. User-agent: Nutch Disallow: / # Hide old versions of the documentation and various large sets of files. User-agent: * Disallow: /~guido/orlijn/ Disallow: /webstats/
Actividad práctica: Obtener número de palabras de un fichero con el módulo requests
Escribir una función que recibe por parámetro una url de un fichero de texto y devuelve el número de palabras que contiene.
Parámetros:
- url: Es una cadena con la url del fichero de texto.
Devuelve:
- El número de palabras que contiene el fichero de texto dado por la url.
Pasos a seguir:
- Importar el módulo requests.
- Definir función y realizar la petición con el módulo requests, añadiendo también control de excepciones.
- Obtener el número de palabras del contenido de la respuesta.
Ejemplo de url con fichero de texto: https://www.gutenberg.org/cache/epub/2000/pg2000.txt.
Solución
import requests def palabras_url(url): try: response = requests.get(url) except Exception: return('¡La url ' + url + ' no existe!') else: contenido = response.text return len(contenido.split()) print(palabras_url('https://www.gutenberg.org/cache/epub/2000/pg2000.txt')) # Prueba con excepción: print(palabras_url('https://no-existe.txt'))
Obtener cabeceras con el módulo request
En el siguiente script podemos ver las cabeceras de la respuesta y de la petición a través del objeto response en el dominio http://python.org
Puede encontrar el siguiente código en el archivo obtener_cabeceras_requests.py:
import requests response = requests.get("http://www.python.org") print(response.content) print("Status code: "+str(response.status_code)) print("Cabeceras de respuesta: ") for header, value in response.headers.items(): print(header, '-->', value) print("Cabeceras de la peticion:") for header, value in response.request.headers.items(): print(header, '-->', value)
La instrucción response.headers proporciona las cabeceras de la respuesta del servidor web. Básicamente, la respuesta es un diccionario de objetos, y con el método items(), podemos iterar con el formato clave-valor para acceder a las diferentes cabeceras.
Al ejecutar el script anterior podemos resaltar la presencia de python-request en la cabecera User-Agent en las cabeceras de la petición.
Cabeceras de la peticion:
User-Agent --> python-requests/2.23.0 Accept-Encoding --> gzip, deflate Accept --> */* Connection --> keep-alive
De de la misma forma, podríamos obtener solo las claves con el método keys() del diccionario de respuesta.
Puede encontrar el siguiente código en el archivo obtener_cabeceras_keys.py:
import requests import requests if __name__ == "__main__": response = requests.get("http://www.python.org") for header in response.headers.keys(): print(header + ":" + response.headers[header])
Ventajas del módulo requests
El módulo requests facilita el uso de peticiones HTTP en Python en comparación con urllib. A menos que tenga un requisito para usar urllib, siempre recomendaría el uso de requests para sus proyectos en Python. Entre las principales ventajas del módulo de requests podemos destacar las siguientes:
- Una biblioteca enfocada en la creación de clientes HTTP completamente funcionales.
- Soporta todos los métodos y características definidos en el protocolo HTTP.
- Es “Pythonic”, es decir, está completamente escrito en Python y todas las operaciones se realizan de manera simple y con solo unas pocas líneas de código.
- Tareas como la integración con servicios web, la creación de un pool de conexiones HTTP, la codificación de datos POST en formularios y el manejo de cookies, se manejan automáticamente.
- Se trata de una librería que implementa las funcionalidades de urllib3 y las extiende.
Realizar peticiones GET a una API REST
Para probar a realizar peticiones con este módulo podríamos usar el servicio <a data-saferedirecturl=“https://www.google.com/url?q=http://httpbin.org&source=gmail&ust=1589737843429000&usg=AFQjCNEvzqoA28kuM04d3mW15oG_Y9-Ucw” href=“http://httpbin.org” target=“_blank”>http://httpbin.org</a>, ejecutando cada tipo de petición por separado. En todos los casos, el código a ejecutar para obtener el resultado deseado será el mismo, lo único que cambiará será el tipo de petición y los datos que se envían al servidor:</p>
×
<p><a href=“http://httpbin.org” target=“_blank”>Servicio httpbin.org</a></p>
<p>http://httpbin.org ofrece un servicio que le permite probar las solicitudes REST a través de puntos finales predefinidos utilizando los métodos get, post, patch, put y delete.</p> <p>Puede encontrar el siguiente código en el archivo <b>testing_api_rest_get_method.py</b></p> <pre class=“prettyprint linenums” style=“user-select: text;”>
<code python> import requests,json
response = requests.get(“http://httpbin.org/get”,timeout=5)
print(“Código de estado HTTP: ” + str(response.status_code))
print(response.headers)
if response.status_code == 200:
results = response.json()
for result in results.items():
print(result)
print("Cabeceras de la respuesta: ")
for header, value in response.headers.items():
print(header, '-->', value)
print("Cabeceras de la petición : ")
for header, value in response.request.headers.items():
print(header, '-->', value)
print("Server:" + response.headers['server'])
else:
print("Error code %s" % response.status_code)
</<code>
