Usando cURL en Python con PycURL

En este tutorial, vamos a aprender a usar PycURL, que es una interfaz para la biblioteca cURL en Python. cURL es una herramienta utilizada para transferir datos a un...

Introducción

En este tutorial, aprenderemos a usar PycURL, que es una interfaz para la biblioteca cURL en Python. rizo es una herramienta utilizada para transferir datos hacia y desde un servidor y para realizar varios tipos de solicitudes de datos. PycURL es excelente para probar API REST, descargar archivos, etc. Algunos desarrolladores prefieren usar Postman para probar las API, pero PycURL es otra opción adecuada para hacerlo, ya que admite múltiples protocolos como FILE, FTPS, HTTPS, IMAP, POP3, SMTP, SCP, SMB, etc. Además, PycURL resulta útil cuando de conexiones simultáneas, rápidas y fiables.

Como se mencionó anteriormente, PycURL es una interfaz para la biblioteca libcURL en Python; por lo tanto PycURL hereda todas las capacidades de libcURL. PycURL es extremadamente rápido (se sabe que es mucho más rápido que Peticiones, que es una biblioteca de Python para solicitudes HTTP), tiene soporte multiprotocolo y también contiene sockets para soportar las operaciones de la red.

Requisitos previos {#requisitos previos}

Antes de continuar con este tutorial, tenga en cuenta que existen algunos requisitos previos. Debe tener una comprensión básica de la sintaxis de Python y/o tener al menos experiencia de programación de nivel principiante en algún otro idioma. Además, debe tener una buena comprensión de los conceptos de red comunes, como los protocolos y sus tipos, y el modo de comunicación cliente-servidor. La familiaridad con estos conceptos es esencial para comprender la biblioteca PycURL.

Instalación

El proceso de instalación de PycURL es bastante simple y directo para todos los sistemas operativos. Solo necesita tener libcURL instalado en su sistema para usar PycURL.

Sistema operativo Mac/Linux

Para Mac OS y Linux, la instalación de PycURL es la más sencilla ya que no tiene dependencias y libcURL se instala de manera predeterminada. Simplemente ejecute el siguiente comando en su terminal y la instalación se completará:

Instalación a través de pip {#instalación a través de pip}
1
$ pip install pycurl 
Instalación a través de easy_install {#instalación a través de easy_install}
1
$ easy_install pycurl

Sistema operativo Windows

Para Windows, sin embargo, hay algunas dependencias que deben instalarse antes de que PyCURL pueda usarse en sus programas. Si está utilizando una distribución oficial de Python (es decir, ha descargado una versión de Python del sitio web oficial https://www.python.org), así como pip, simplemente necesita ejecutar el siguiente comando en su línea de comando y la instalación se realizará:

1
$ pip install pycurl

Si no está utilizando pip, los instaladores EXE y MSI están disponibles en [Ventanas PycURL] (https://dl.bintray.com/pycurl/pycurl). Puede descargarlos e instalarlos directamente desde allí, como cualquier otra aplicación.

Ejemplos de código básico

En esta sección, cubriremos algunos ejemplos de codificación de PycURL que demuestran las diferentes funcionalidades de la interfaz.

Como se mencionó en la sección de introducción, PycURL admite muchos protocolos y tiene muchas características sofisticadas. Sin embargo, en nuestros ejemplos, trabajaremos con el protocolo HTTP para probar las API REST utilizando los métodos más utilizados de HTTP: GET, POST, PUT y DELETE, junto con algunos otros ejemplos. Escribiremos la sintaxis para declararlos en Python 3, y explicaremos lo que hacen.

¡Así que comencemos!

Ejemplo 1: envío de una solicitud HTTP GET

Una operación de red simple de PycURL es recuperar información de un servidor dado usando su URL. Esto se denomina solicitud GET, ya que se utiliza para “obtener” un recurso de red.

Se puede realizar una solicitud GET simple usando PycURL importando el módulo BytesIO y creando su objeto. Se crea un objeto CURL para transferir datos y archivos a través de URL.

La URL deseada se establece mediante la función setopt(), que se utiliza como setopt(opción, valor). El parámetro opción especifica qué opción establecer, p. URL, WRITEDATA, etc., y el parámetro value especifica el valor dado a esa opción en particular.

Los datos recuperados de la URL establecida se escriben en forma de bytes en el objeto BytesIO. Luego, los bytes se leen del objeto BytesIO mediante la función getvalue() y, posteriormente, se decodifican para imprimir el HTML en la consola.

Aquí hay un ejemplo de cómo hacer esto:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import pycurl
from io import BytesIO 

b_obj = BytesIO() 
crl = pycurl.Curl() 

# Set URL value
crl.setopt(crl.URL, 'https://wiki.python.org/moin/BeginnersGuide')

# Write bytes that are utf-8 encoded
crl.setopt(crl.WRITEDATA, b_obj)

# Perform a file transfer 
crl.perform() 

# End curl session
crl.close()

# Get the content stored in the BytesIO object (in byte characters) 
get_body = b_obj.getvalue()

# Decode the bytes stored in get_body to HTML and print the result 
print('Output of GET request:\n%s' % get_body.decode('utf8')) 

Producción:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
Output of GET request:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv = "Content-Type" content = "text/html; charset = utf-8">
<meta name="robots" content="index,nofollow">

<title>BeginnersGuide - Python Wiki</title>
<script type="text/javascript" src = "/wiki/common/js/common.js" ></script>

<script type = "text/javascript" >
<!--
var search_hint = "Search";
//-->
</script>
.
.
.

Ejemplo 2: Examen de encabezados de respuesta GET

También puede recuperar los encabezados de respuesta de un sitio web con la ayuda de PycURL. Los encabezados de respuesta se pueden examinar por varias razones, por ejemplo, para averiguar qué codificación se ha enviado con la respuesta y si está de acuerdo con la codificación proporcionada por el servidor.

En nuestro ejemplo, examinaremos los encabezados de respuesta simplemente para encontrar varios nombres de atributos y sus valores correspondientes.

Para examinar los encabezados de respuesta, primero debemos extraerlos, y lo hacemos usando la opción HEADERFUNCTION y mostrándolos usando nuestra función autodefinida (display_header() en este caso).

Proporcionamos la URL del sitio cuyos encabezados de respuesta deseamos examinar; HEADERFUNCTION envía los encabezados de respuesta a la función display_header() donde tienen el formato adecuado. Los encabezados de respuesta se decodifican de acuerdo con el estándar especificado y se dividen en sus nombres y valores correspondientes. Los espacios en blanco entre los nombres y los valores se eliminan y luego se convierten a minúsculas.

Los encabezados de respuesta luego se escriben en el objeto BytesIO, se transfieren al solicitante y finalmente se muestran en el formato adecuado.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from io import BytesIO
import pycurl

headers = {}

def display_header(header_line):
    header_line = header_line.decode('iso-8859-1')

    # Ignore all lines without a colon
    if ':' not in header_line:
        return

    # Break the header line into header name and value
    h_name, h_value = header_line.split(':', 1)

    # Remove whitespace that may be present
    h_name = h_name.strip()
    h_value = h_value.strip()
    h_name = h_name.lower() # Convert header names to lowercase
    headers[h_name] = h_value # Header name and value.

def main():
    print('**Using PycURL to get Twitter Headers**')
    b_obj = BytesIO()
    crl = pycurl.Curl()
    crl.setopt(crl.URL, 'https://twitter.com')
    crl.setopt(crl.HEADERFUNCTION, display_header)
    crl.setopt(crl.WRITEDATA, b_obj)
    crl.perform()
    print('Header values:-')
    print(headers)
    print('-' * 20)
    
main()

Producción:

1
2
3
4
**Using PycURL to get Twitter Headers**
Header values:-
{'cache-control': 'no-cache, no-store, must-revalidate, pre-check=0, post-check=0', 'content-length': '303055', 'content-type': 'text/html;charset=utf-8', 'date': 'Wed, 23 Oct 2019 13:54:11 GMT', 'expires': 'Tue, 31 Mar 1981 05:00:00 GMT', 'last-modified': 'Wed, 23 Oct 2019 13:54:11 GMT', 'pragma': 'no-cache', 'server': 'tsa_a', 'set-cookie': 'ct0=ec07cd52736f70d5f481369c1d762d56; Max-Age=21600; Expires=Wed, 23 Oct 2019 19:54:11 GMT; Path=/; Domain=.twitter.com; Secure', 'status': '200 OK', 'strict-transport-security': 'max-age=631138519', 'x-connection-hash': 'ae7a9e8961269f00e5bde67a209e515f', 'x-content-type-options': 'nosniff', 'x-frame-options': 'DENY', 'x-response-time': '26', 'x-transaction': '00fc9f4a008dc512', 'x-twitter-response-tags': 'BouncerCompliant', 'x-ua-compatible': 'IE=edge,chrome=1', 'x-xss-protection': '0'}
--------------------

En los casos en que tengamos varios encabezados con el mismo nombre, solo se almacenará el último valor del encabezado. Para almacenar todos los valores en encabezados de varios valores, podemos usar el siguiente código:

1
2
3
4
5
6
7
if h_name in headers:
    if isinstance(headers[h_name], list):
        headers[name].append(h_value)
    else:
        headers[h_name] = [headers[h_name], h_value]
else:
    headers[h_name] = h_value

Ejemplo 3: envío de datos de formulario a través de HTTP POST

Una solicitud POST es la que envía datos a un servidor web encerrándolos en el cuerpo de la solicitud HTTP. Cuando carga un archivo o envía un formulario, básicamente está enviando una solicitud POST al servidor designado.

Se puede realizar una solicitud POST usando PycURL configurando primero la URL para enviar los datos del formulario a través de la función setopt. Los datos que se enviarán primero se almacenan en forma de diccionario (en pares de valores clave) y luego se codifican en URL utilizando la función urlencode que se encuentra en el módulo urllib.parse.

Usamos la opción POSTFIELDS para enviar datos de formulario, ya que establece automáticamente el método de solicitud HTTP en POST, y también maneja nuestros datos pf.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
from urllib.parse import urlencode
import pycurl

crl = pycurl.Curl()
crl.setopt(crl.URL, 'https://www.code-learner.com/post/')
data = {'field': 'value'}
pf = urlencode(data)

# Sets request method to POST,
# Content-Type header to application/x-www-form-urlencoded
# and data to send in request body.
crl.setopt(crl.POSTFIELDS, pf)
crl.perform()
crl.close()

Nota: Si desea especificar otro método de solicitud, puede utilizar la opción CUSTOMREQUEST para hacerlo. Simplemente escriba el nombre del método de solicitud de su elección en las comillas vacías que siguen a crl.CUSTOMREQUEST.

1
crl.setopt(crl.CUSTOMREQUEST, '')

Ejemplo 4: Carga de archivos con POST de varias partes

Hay varias formas en las que puede replicar cómo se carga un archivo en un formulario HTML usando PycURL:

  1. Si los datos que se enviarán a través de la solicitud POST están en un archivo en su sistema, primero debe configurar la URL donde desea enviar los datos. Luego especifica su método de solicitud como HTTPPOST y usa la opción fileupload para cargar el contenido del archivo deseado.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import pycurl

crl = pycurl.Curl()
crl.setopt(crl.URL, 'https://www.code-learner.com/post/')

crl.setopt(crl.HTTPPOST, [
    ('fileupload', (
        # Upload the contents of the file
        crl.FORM_FILE, './my-resume.doc',
    )),
])
crl.perform()
crl.close()

Nota: Si desea cambiar el nombre y/o el tipo de contenido del archivo, puede hacerlo haciendo ligeras modificaciones al código anterior:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
crl.setopt(crl.HTTPPOST, [
    ('fileupload', (
        # Upload the contents of this file
        crl.FORM_FILE, './my-resume.doc',
        # Specify a file name of your choice
        crl.FORM_FILENAME, 'updated-resume.doc',
        # Specify a different content type of upload
        crl.FORM_CONTENTTYPE, 'application/msword',
    )),
])
  1. Para los datos de archivo que tiene en la memoria, todo lo que varía en la implementación de la solicitud POST es FORM_BUFFER y FORM_BUFFERPTR en lugar de FORM_FILE, ya que estos obtienen los datos que se publicarán, directamente desde la memoria.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import pycurl

crl = pycurl.Curl()
crl.setopt(crl.URL, 'https://www.code-learner.com/post/')

crl.setopt(crl.HTTPPOST, [
    ('fileupload', (
        crl.FORM_BUFFER, 'contact-info.txt',
        crl.FORM_BUFFERPTR, 'You can reach me at [correo electrónico protegido]',
    )),
])

crl.perform()
crl.close()

Ejemplo 5: Subir un archivo con HTTP PUT

La solicitud PUT es de naturaleza similar a la solicitud POST, excepto por el hecho de que se puede usar para cargar un archivo en el cuerpo de la solicitud. Utiliza una solicitud PUT cuando conoce la URL del objeto que desea crear o sobrescribir. Básicamente, PUT reemplaza lo que existe actualmente en la URL de destino con algo más.

Si los datos que desea cargar se encuentran en un archivo físico, primero debe configurar la URL de destino, luego carga el archivo y lo abre. Es importante que el archivo se mantenga abierto mientras el objeto cURL lo usa. Luego, los datos se leen del archivo usando READDATA.

Finalmente, la transferencia de archivos (carga) se realiza utilizando la función perform y luego finaliza la sesión de cURL. Por último, se cierra el archivo que se abrió inicialmente para el objeto CURL.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import pycurl

crl = pycurl.Curl()
crl.setopt(crl.URL, 'https://www.code-learner.com/post/')

dat_file = open('data.txt')

crl.setopt(crl.UPLOAD, 1)
crl.setopt(crl.READDATA, dat_file)

crl.perform()
crl.close()
dat_file.close()

Si los datos del archivo se encuentran en un búfer, la implementación de PycURL es prácticamente la misma que la carga de datos ubicados en un archivo físico, con ligeras modificaciones. El objeto BytesIO codifica los datos utilizando el estándar especificado. Esto se debe a que READDATA requiere un objeto similar a IO y los datos codificados son esenciales para Python 3. Esos datos codificados se almacenan en un búfer y ese búfer luego se lee. La carga de datos se lleva a cabo y al completar la carga, se finaliza la sesión de cURL.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import pycurl
crl = pycurl.Curl()
crl.setopt(crl.URL, 'https://www.code-learner.com/post/')

data = '{"person":{"name":"billy","email":"[correo electrónico protegido]"}}'
buffer = BytesIO(data.encode('utf-8'))

crl.setopt(crl.UPLOAD, 1)
crl.setopt(crl.READDATA, buffer)

crl.perform()
crl.close()

Ejemplo 6: envío de una solicitud de ELIMINACIÓN HTTP

Otro método HTTP importante y muy utilizado es DELETE. El método DELETE solicita que el servidor elimine el recurso identificado por la URL de destino. Se puede implementar utilizando la función CUSTOMREQUEST, como se puede ver en el ejemplo de código a continuación:

1
2
3
4
5
6
7
import pycurl

crl = pycurl.Curl()
crl.setopt(crl.URL, "http://api.example.com/user/148951")
crl.setopt(crl.CUSTOMREQUEST, "DELETE")
crl.perform()
crl.close()

Ejemplo 7: escribir en un archivo

PycURL también se puede usar para guardar una respuesta en un archivo. Usamos la función abrir para abrir el archivo y la respuesta se devuelve como un objeto de archivo. La función abrir tiene la forma: abrir(archivo, modo). El parámetro archivo representa la ruta y el nombre del archivo que se abrirá y modo representa el modo en el que desea abrir el archivo. En nuestro ejemplo, es importante tener el archivo abierto en modo binario (es decir, wb) para evitar la codificación y decodificación de la respuesta.

1
2
3
4
5
6
7
8
9
import pycurl

file = open('pycurl.md','wb')

crl = pycurl.Curl()
crl.setopt(crl.URL, 'https://wiki.python.org/moin/BeginnersGuide')
crl.setopt(crl.WRITEDATA, file)
crl.perform()
crl.close()

Conclusión

En este tutorial, aprendimos sobre la interfaz PycURL en Python. Comenzamos hablando sobre algunas de las funciones generales de PycURL y su relevancia con la biblioteca libcURL en Python. Luego vimos el proceso de instalación de PycURL para diferentes sistemas operativos.

Por último, revisamos algunos de los ejemplos generales de PycURL que demostraron las diversas funcionalidades que ofrece PycURL, como los métodos HTTP GET, POST, PUT y DELETE. Después de seguir este tutorial, debería poder recuperar objetos identificados por una URL dentro de un programa de Python con facilidad.

Licensed under CC BY-NC-SA 4.0