Para poder abordar el objetivo de este artículo, que es aprender a utilizar cURL en Python, primero debemos presentar cURL. Client URL (cURL) es, en resumen, una línea de comandos fácil de usar diseñada para que los desarrolladores puedan recuperar datos de un servidor.
¿Qué es cURL?
¿Cómo se utiliza cURL?
Como ya he mencionado anteriormente, usar cURL es bastante sencillo y permite extraer información con un comando de una sola línea. En primer lugar, debes abrir un terminal y escribir curl seguido de un enlace a un sitio web, por ejemplo:
$ curl 'https://www.webscrapingapi.com/'
Enhorabuena, acabas de realizar tu primera solicitud con cURL. Este sencillo comando solicita información al servidor igual que lo haría un navegador tradicional y devuelve el código HTML de la página. No todos los sitios web te devolverán HTML; hay puntos finales que envían los datos como un objeto JSON. Veamos este ejemplo:
$ curl 'https://jsonplaceholder.typicode.com/todos/1'
Escribe este comando en tu terminal y deberías obtener esta respuesta:
{
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
}La mayoría de las API te devolverán HTML o JSON cuando ejecutes comandos de cURL sobre ellas. Bueno, esto no es todo lo que cURL puede hacer por nosotros. En realidad, es una herramienta muy sofisticada. Si quieres aprender más sobre cURL, te recomiendo encarecidamente que eches un vistazo a la documentación de cURL para comprender mejor sus parámetros. Como alternativa, puedes ejecutar el siguiente comando:
$ curl --help
Esto te mostrará algunas opciones que puedes configurar en cURL:
Usage: curl [options...] <url>
-d, --data <data> HTTP POST data
-f, --fail Fail silently (no output at all) on HTTP errors
-h, --help <category> Get help for commands
-i, --include Include protocol response headers in the output
-o, --output <file> Write to file instead of stdout
-O, --remote-name Write output to a file named as the remote file
-s, --silent Silent mode
-T, --upload-file <file> Transfer local FILE to destination
-u, --user <user:password> Server user and password
-A, --user-agent <name> Send User-Agent <name> to server
-v, --verbose Make the operation more talkative
-V, --version Show version number and quit
This is not the full help, this menu is stripped into categories.
Use "--help category" to get an overview of all categories.For all options use the manual or "--help all".
Como probablemente habrás visto, estas ni siquiera son todas las opciones que puedes configurar en cURL; se trata de un menú dividido en categorías. Probablemente habrás adivinado que, para obtener todas las opciones que te gustaría ejecutar:
$ curl --help all
¿Cómo se utiliza cURL en Python?
Para este paso, hay dos requisitos previos. El primero es bastante obvio: debes instalar Python en tu equipo. Puedes hacerlo accediendo a la página web oficial de Python e instalando la versión adecuada para tu sistema operativo. Asegúrate de que sea una versión reciente, ya que las más antiguas probablemente no incluyan pip, que es necesario para la mayoría de los paquetes que querremos utilizar. A continuación, ejecuta el siguiente comando:
$ pip --version
Si la instalación se ha realizado correctamente, esto debería mostrarte la versión de pip que has instalado.
De lo contrario, lo más probable es que aparezca este mensaje:
"pip" is not considered to be an external or internal command. A batch file is a program to operate.
Es muy importante que tengas pip instalado para poder continuar, ya que lo necesitarás para instalar paquetes.
El segundo requisito previo es que estés familiarizado con la sintaxis de Python o, al menos, que tengas un nivel de principiante en cualquier otro lenguaje de programación.
¿Por qué usar cURL en Python?
Probablemente te estés preguntando: ¿no basta con usar cURL desde la línea de comandos? Solo ejecutamos una línea de comando y la API nos devuelve la información. Esto es cierto, pero en la práctica querremos procesar de alguna manera los datos que recibimos del servidor y por eso necesitamos un lenguaje de programación. Ahí es donde entra en juego Python.
¿Por qué usar Python?
Python es un lenguaje de programación de alto nivel que se utiliza para muchos fines. Su sintaxis sencilla y su simplicidad hacen que sea muy fácil de aprender para los principiantes. Además, cuenta con una enorme comunidad dispuesta a ayudarte, así que, si te encuentras con algún problema, no dudes en preguntar. Un sitio estupendo donde puedes entrar y hacer una pregunta es StackOverflow, y seguro que alguien te responderá.
Cómo integrar cURL en Python
Al igual que antes, cURL en Python también es muy sencillo. Recuerda cuando escribimos un comando de una línea para obtener los datos del servidor. La diferencia es que ahora necesitas escribir dos líneas de código para esta sencilla llamada, por ejemplo:
import osos.system(f'curl "https://www.webscrapingapi.com/product/"')
Ahora veamos la verdadera ventaja de usar un lenguaje de programación. Podemos crear una función que acepte una URL personalizada y ejecute el comando cURL con ella:
import os
def cURL(url):
return os.system(f'curl "{url}"')cURL('https://www.webscrapingapi.com/blog/')
Puedes sustituir https://www.webscrapingapi.com/blog/ por cualquier otro sitio web del que quieras obtener datos. Enhorabuena, en este punto has creado un script que toma una URL, ejecuta el comando cURL y muestra el resultado en la consola. Puedes ejecutar Python directamente en tu terminal, pero para una mejor experiencia de programación te recomiendo encarecidamente que utilices un entorno de desarrollo integrado. Hay muchas opciones entre las que elegir, pero para Python recomiendo PyCharm, que puedes descargar desde aquí
Como ya he mencionado anteriormente, cURL no se limita en absoluto a eso. Puede hacer muchísimas cosas además de enviar solicitudes GET. También puede descargar archivos o enviar solicitudes POST, PUT o DELETE. Aquí tienes un ejemplo de una función de Python que envía una solicitud POST a https://httpbin.org/post:
import os
def cURL(method,url,data):
return os.system(f'curl -X "{method}" --url "{url}" --data {data} ')
data = '{"foo":"bar"}'cURL('POST', 'https://httpbin.org/post', data)
Como probablemente habrás visto, el comando cambia ligeramente al enviar una solicitud POST. En la solicitud anterior no tenías que usar los parámetros -X y –data porque el método predeterminado de cURL es GET. Tras ejecutar este comando, deberías recibir de la API de httpbin una respuesta que contenga tu solicitud, la dirección IP, los parámetros y el cuerpo que has enviado, que sería algo así.
{
"args": {},
"data": "",
"files": {},
"form": {
"{foo:bar}": ""
},
"headers": {
"Accept": "*/*",
"Content-Length": "9",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "curl/X.XX.X",
"X-Amzn-Trace-Id": "Root=X-XXXXX-XXXXXX"
},
"json": null,
"origin": "0.0.0.0",
"url": "https://httpbin.org/post"
}En este punto ya has creado una herramienta sencilla capaz de enviar solicitudes GET, POST, PUT, PATCH, DELETE, etc., para recuperar datos de una API. Ahora podemos simplemente establecer la URL, el método y el cuerpo directamente desde nuestro script de Python en lugar de escribirlo manualmente. Sin embargo, esta es una ventaja menor que obtenemos al usar cURL en Python. La ventaja principal es que ahora podemos procesar los datos de la forma que queramos, incluso si la API no nos ofrece la opción de obtenerlos como nos gustaría. Por ejemplo, supongamos que se nos proporciona una lista de todos los usuarios, pero queremos dividirlos en dos grupos y obtener los usuarios del segundo grupo.
Podemos hacerlo gracias a Python almacenando la respuesta en una variable llamada users, que podemos convertir en una matriz de objetos JSON utilizando el método json.loads(), sobre el que puedes encontrar más información aquí. A continuación, podemos recorrer la matriz de usuarios y mostrar solo los usuarios de la segunda mitad de la lista o aquellos cuyos números de identificación sean mayores que la mitad de la lista. Para entenderlo mejor, así es como se traduce en código:
import subprocess
import json
def cURL(url):
return subprocess.check_output(['curl',url])
users = json.loads(cURL('https://jsonplaceholder.typicode.com/users'))
for user in users:
if(user['id'] > len(users) / 2): print(user)Probablemente hayas notado que, en lugar de os, ahora estamos utilizando las bibliotecas subprocess y json. Utilizamos la biblioteca subprocess porque queremos poder guardar la salida del comando, a diferencia del módulo os, que simplemente ejecuta el comando sin almacenarlo. El código es una simple solicitud GET a una API que nos devuelve una lista de usuarios en forma de objetos JSON. La salida debería ser:
{'id': 6, 'name': 'Mrs. Dennis Schulist', 'username': 'Leopoldo_Corkery', 'email': 'Karley_Dach@jasper.info', 'address': {'street': 'Norberto Crossing', 'suite': 'Apt. 950', 'city': 'South Christy', 'zipcode': '23505-1337', 'geo': {'lat': '-71.4197', 'lng': '71.7478'}}, 'phone': '1-477-935-8478 x6430', 'website': 'ola.org', 'company': {'name': 'Considine-Lockman', 'catchPhrase': 'Synchronised bottom-line interface', 'bs': 'e-enable innovative applications'}}
{'id': 7, 'name': 'Kurtis Weissnat', 'username': 'Elwyn.Skiles', 'email': 'Telly.Hoeger@billy.biz', 'address': {'street': 'Rex Trail', 'suite': 'Suite 280', 'city': 'Howemouth', 'zipcode': '58804-1099', 'geo': {'lat': '24.8918', 'lng': '21.8984'}}, 'phone': '210.067.6132', 'website': 'elvis.io', 'company': {'name': 'Johns Group', 'catchPhrase': 'Configurable multimedia task-force', 'bs': 'generate enterprise e-tailers'}}
{'id': 8, 'name': 'Nicholas Runolfsdottir V', 'username': 'Maxime_Nienow', 'email': 'Sherwood@rosamond.me', 'address': {'street': 'Ellsworth Summit', 'suite': 'Suite 729', 'city': 'Aliyaview', 'zipcode': '45169', 'geo': {'lat': '-14.3990', 'lng': '-120.7677'}}, 'phone': '586.493.6943 x140', 'website': 'jacynthe.com', 'company': {'name': 'Abernathy Group', 'catchPhrase': 'Implemented secondary concept', 'bs': 'e-enable extensible e-tailers'}}
{'id': 9, 'name': 'Glenna Reichert', 'username': 'Delphine', 'email': 'Chaim_McDermott@dana.io', 'address': {'street': 'Dayna Park', 'suite': 'Suite 449', 'city': 'Bartholomebury', 'zipcode': '76495-3109', 'geo': {'lat': '24.6463', 'lng': '-168.8889'}}, 'phone': '(775)976-6794 x41206', 'website': 'conrad.com', 'company': {'name': 'Yost and Sons', 'catchPhrase': 'Switchable contextually-based project', 'bs': 'aggregate real-time technologies'}}
{'id': 10, 'name': 'Clementina DuBuque', 'username': 'Moriah.Stanton', 'email': 'Rey.Padberg@karina.biz', 'address': {'street': 'Kattie Turnpike', 'suite': 'Suite 198', 'city': 'Lebsackbury', 'zipcode': '31428-2261', 'geo': {'lat': '-38.2386', 'lng': '57.2232'}}, 'phone': '024-648-3804', 'website': 'ambrose.net', 'company': {'name': 'Hoeger LLC', 'catchPhrase': 'Centralized empowering task-force', 'bs': 'target end-to-end models'}}Este es solo uno de los usos de cURL en Python. Ya no dependemos de la API para que nos devuelva los datos de la forma que queremos; podemos procesarlos de muchas maneras diferentes, como mostrar si una persona está en una lista de respuestas basándonos en su nombre, correo electrónico, número de teléfono o cualquier otra propiedad única de una persona.
Por ejemplo, supongamos que queremos comprobar si un nombre concreto existe o no en una lista. Para ello, podemos crear una función que tome la respuesta que hemos convertido en una matriz JSON lista para que Python la analice.
import subprocess
import json
def cURL(url):
return subprocess.check_output(['curl',url])
users = json.loads(cURL('https://jsonplaceholder.typicode.com/users'))
def check_if_user_exists(users,name):
for user in users:
if(user['name'] == name): print(f'An user called {name} exists in the list and has the id of {user["id"]}')
check_if_user_exists(users,'Clementina DuBuque')Este bloque de código nos dará entonces este resultado:
An user called Clementina DuBuque exists in the list and has the id of 10
Enhorabuena. Has creado un script que recupera datos de un servidor, los almacena y los analiza posteriormente. Las ventajas de usar Python no se detienen aquí; Python cuenta incluso con una interfaz especial diseñada para usar cURL que se llama PycURL y de la que vamos a hablar ahora.
¿Qué es PycURL?
Como mencionamos antes, PycURL es, en resumen, una herramienta de Python que nos ayuda a utilizar cURL de forma más natural. Una gran ventaja es que PycURL está muy optimizado y admite la concurrencia, lo que significa que es muy rápido (más rápido que la popular biblioteca request de Python). Por otro lado, usar PycURL no es tan fácil como lo que hemos visto antes, ya que es una herramienta dirigida a desarrolladores avanzados. Sin embargo, no debes sentirte intimidado por ello, porque al final obtendrás una comprensión más profunda de las redes y te sentirás más cómodo con Python.
¿Cómo se instala?
Al igual que cualquier otro paquete, puedes instalarlo con pip:
$ pip install pycurl
También te conviene instalar certifi esta vez por motivos de seguridad al utilizar pycurl. Certifi es una herramienta que valida certificados SSL al tiempo que verifica la identidad del host TLS. Para obtener más información sobre certifi, te recomiendo encarecidamente que consultes su documentación. Puedes instalarlo de la misma manera:
$ pip install certifi
Ahora puedes comprobar que la instalación se ha realizado correctamente ejecutando el siguiente script:
import certifiprint(certifi.where())
El resultado debería ser la ubicación donde se ha instalado el paquete:
/usr/local/lib/python3.10/site-packages/certifi/cacert.pem
¿Cómo se utiliza pycURL?
La diferencia con respecto a lo que hicimos antes es que ahora solo escribimos código sin ejecutar comandos directamente. En resumen, creamos una instancia de la clase pycurl.Curl(), recuperamos los datos y los escribimos en un búfer que luego descodificaremos para poder leer los datos recibidos:
import pycurl
import certifi
from io import BytesIO
buffer = BytesIO()
c = pycurl.Curl()
c.setopt(c.URL, 'https://docs.webscrapingapi.com/')
c.setopt(c.WRITEDATA, buffer)
c.setopt(c.CAINFO, certifi.where())
c.perform()
c.close()
body = buffer.getvalue()print(body.decode('iso-8859-1'))
Lo has adivinado, al igual que en nuestros ejemplos anteriores, esto recupera el contenido HTML de la página web WebScrapingAPI y lo imprime en la línea de comandos.
Una solicitud POST no es muy diferente, salvo que debes indicar a tu instancia de la clase pycurl.Curl() que vas a utilizar el método POST, y configurar el cuerpo y los encabezados, si procede. Así es como queda:
import pycurl
import certifi
import json
from io import BytesIO
buffer = BytesIO()
c = pycurl.Curl()
c.setopt(c.URL, 'https://httpbin.org/post')
c.setopt(pycurl.HTTPHEADER, [ 'Content-Type: application/json' , 'Accept: application/json'])
data = json.dumps({"foo": "bar"})
c.setopt(pycurl.POST, 1)
c.setopt(pycurl.POSTFIELDS, data)
c.setopt(c.WRITEDATA, buffer)
c.setopt(c.CAINFO, certifi.where())
c.perform()
c.close()
body = buffer.getvalue()print(body.decode('iso-8859-1'))
Y deberíamos recibir, al igual que antes, una respuesta que contenga tu solicitud, la dirección IP, los parámetros y el cuerpo:
{
"args": {},
"data": "",
"files": {},
"form": {
"{foo:bar}": ""
},
"headers": {
"Accept": "*/*",
"Content-Length": "9",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "curl/X.XX.X",
"X-Amzn-Trace-Id": "Root=X-XXXXX-XXXXXX"
},
"json": null,
"origin": "0.0.0.0",
"url": "https://httpbin.org/post"
}Como ya he mencionado, estas son solo algunas de las cosas básicas que pycURL puede hacer por nosotros. Es una herramienta muy compleja y sofisticada sobre la que podríamos escribir muchos artículos. Si quieres explorar más cosas que puedes hacer con ella, te recomiendo encarecidamente que consultes su documentación.
Resumen
En conclusión, usar cURL en Python es muy eficaz y ahorra mucho tiempo; además, puede ser un punto de partida para algunos proyectos interesantes en temas como el análisis de datos o el web scraping. El enfoque que recomiendo es familiarizarse primero con cURL y Python y luego pasar a usar pycURL. Espero que este recurso te haya resultado útil para aprender a usar cURL en Python y que experimentes con él y crees algunos scripts.




