Analizando la Respuesta
Profundiza en el objeto Response devuelto por requests. Descubre cómo extraer el texto sin formato, acceder a las cabeceras del servidor y entender la codificación de caracteres empleada.
Una petición HTTP solo cobra sentido cuando entendemos lo que el servidor devuelve. Al realizar una solicitud con la biblioteca requests, el flujo de red se transforma en un objeto Response, una potente interfaz que almacena mucho más que el contenido de una página.
En este capítulo aprenderás a auditar con precisión el ciclo de retorno de tus datos. Descubriremos la anatomía interna de este objeto, la diferencia crítica entre procesar texto decodificado o bytes puros, la forma correcta de inspeccionar los metadatos ocultos en las cabeceras sin cometer errores de capitalización y cómo rastrear de forma automatizada el historial de redirecciones en la red.
5.1. El objeto Response al detalle
Cada vez que ejecutas una petición con la biblioteca requests, el servidor devuelve una respuesta HTTP. En el código, esta respuesta se materializa como una instancia de la clase requests.models.Response. Este objeto no es simplemente una cadena de texto con el contenido de la página; es un contenedor sofisticado que encapsula la totalidad de la transacción de vuelta, incluyendo metadatos, configuraciones de red, el estado de la conexión y el cuerpo de los datos.
Para comprender cómo interactúa requests con el servidor, es útil visualizar el ciclo completo de intercambio de objetos:
TEXT
Cuando invocas requests.get(), la biblioteca traduce tus argumentos en un objeto interno de petición preparada (PreparedRequest). Tras enviarlo y recibir la contestación del servidor, requests construye el objeto Response. Este objeto actúa como una interfaz unificada para inspeccionar todo lo que el servidor ha devuelto.
Anatomía interna del objeto Response
El objeto Response no almacena la información de forma estática, sino que expone un conjunto de atributos y métodos que expondremos en detalle a continuación. Podemos agrupar sus componentes principales en cuatro áreas funcionales:
TEXT
Atributos esenciales y su comportamiento
A continuación se detalla el comportamiento y la utilidad de los atributos fundamentales del objeto Response:
status_code: Un entero que representa el código de estado HTTP devuelto por el servidor (por ejemplo,200para una solicitud exitosa o404para un recurso no encontrado).ok: Una propiedad booleana muy útil para flujos de control rápidos. DevuelveTruesi elstatus_codees menor que 400 (lo que significa que la petición se completó con éxito o se redireccionó). DevuelveFalsesi el código está en los rangos de error de cliente (4xx) o de servidor (5xx).reason: Una cadena de texto que contiene la descripción textual del código de estado HTTP provista por el estándar del protocolo (por ejemplo, "OK" para un código 200, o "Not Found" para un 404).url: Contiene la cadena de texto de la URL final. Esto es especialmente importante si la petición original pasó por una o varias redirecciones;.urlmostrará el destino definitivo donde se detuvo la transferencia, no necesariamente la dirección que escribiste en el método inicial.elapsed: Un objeto de la clasedatetime.timedeltaque mide el tiempo transcurrido entre el envío de la petición y la recepción completa de las cabeceras de la respuesta. Es excelente para realizar mediciones básicas de rendimiento y latencia del servicio web.
Inspección básica en código
Para observar cómo interactúan estas propiedades en un entorno real, analiza el siguiente bloque de código enfocado en desglosar la respuesta de una petición estándar:
Python
El vínculo con la petición original: el atributo request
Un aspecto avanzado pero crucial del objeto Response es su propiedad .request. Mantener la trazabilidad en aplicaciones de red es vital. Por ello, requests vincula directamente la respuesta con el objeto PreparedRequest que la generó.
A través de respuesta.request, puedes auditar con precisión qué cabeceras exactas envió la biblioteca tras bambalinas, la URL original con sus parámetros ya codificados o los cuerpos de datos adjuntos en operaciones de escritura. Esto convierte al objeto Response en una bitácora bidireccional de toda la transacción HTTP.
5.2. Propiedades de texto y codificación
Cuando el servidor web responde a una petición, envía una secuencia de bytes puros a través de la red junto con metadatos que describen el tipo de contenido. El objeto Response de la biblioteca requests procesa este flujo de datos subyacente y proporciona dos mecanismos principales para acceder al cuerpo de la respuesta: uno optimizado para datos basados en texto (.text) y otro diseñado para datos puros o binarios (.content).
Comprender la diferencia matemática y operativa entre estas dos propiedades, así como la lógica que utiliza la biblioteca para gestionar la codificación de caracteres, es fundamental para evitar la corrupción de datos y los errores de lectura de caracteres especiales.
TEXT
La propiedad .text y la decodificación implícita
La propiedad .text devuelve el cuerpo de la respuesta en forma de cadena de caracteres de Python (str). Cuando invocas esta propiedad, requests realiza automáticamente una decodificación de los bytes crudos que recibió del servidor.
Para lograr esto, la biblioteca necesita saber qué mapa de caracteres (o codificación) se utilizó para transformar el texto original en los bytes transmitidos. Aquí es donde entra en juego el atributo .encoding.
La lógica interna que sigue requests para determinar el valor de .encoding y resolver el texto se basa en el siguiente orden de prioridades:
- Cabecera HTTP
Content-Type: La biblioteca examina las cabeceras de la respuesta en busca de la directivacharsetdentro deContent-Type(por ejemplo,Content-Type: text/html; charset=utf-8). Si está presente, asigna ese valor a.encoding. - Heurística de
chardetocharset_normalizer: Si el servidor omitió especificar elcharseten las cabeceras,requestsno asume una codificación universal. En su lugar, analiza estadísticamente los primeros bytes del cuerpo de la respuesta utilizando una biblioteca interna de detección para adivinar cuál es la codificación más probable (comúnmente detectando variaciones comoISO-8859-1outf-8). - Soporte predeterminado para texto: De acuerdo con el estándar RFC 2616 de HTTP, si el tipo de medio es de la familia
text/(comotext/html) y no se define un juego de caracteres, la especificación dicta que se debe asumirISO-8859-1. La biblioteca adopta este comportamiento como último recurso si las cabeceras no ayudan.
Diferencias operativas: .text frente a .content
Es importante distinguir cuándo delegar la lectura en .text y cuándo es obligatorio recurrir a .content:
response.text: Retorna un tipostr. Debe utilizarse única y exclusivamente para recursos que representen formatos de texto plano legibles, tales como páginas HTML, documentos XML, estructuras JSON o archivos de configuración CSV.response.content: Retorna un tipobytes. Ignora por completo cualquier configuración de.encodingy entrega la información exactamente como llegó del socket de red. Debe utilizarse para archivos binarios como imágenes (PNG, JPEG), flujos de audio/video, instaladores ejecutables o archivos comprimidos (ZIP, TAR). Intentar leer un binario a través de.textforzará una decodificación innecesaria que probablemente corromperá el archivo o lanzará excepciones.
Control manual de la codificación
El proceso de detección automática no es infalible. Existen situaciones en las que el servidor declara una codificación incorrecta o simplemente no aporta suficiente información, lo que provoca que caracteres especiales (como eñes, acentos o emojis) se muestren dañados o alterados en .text (un fenómeno conocido como mojibake).
Afortunadamente, el atributo .encoding no es de solo lectura; es completamente mutable. Si conoces de antemano la codificación real del recurso, puedes sobrescribir el atributo antes de acceder a .text. Al cambiar .encoding, requests utilizará inmediatamente el nuevo mapa de caracteres la próxima vez que evalúe la propiedad .text.
Implementación práctica en código
El siguiente script ejemplifica cómo comprobar la codificación asignada automáticamente, cómo difieren los tipos de datos devueltos por ambas propiedades y cómo forzar una codificación específica cuando sea necesario:
Python
5.3. Inspección de cabeceras de respuesta
Las cabeceras de respuesta HTTP son parejas de clave-valor que el servidor envía de vuelta junto con el recurso solicitado. Estas cabeceras contienen metadatos cruciales sobre la transacción, como el tipo de servidor, la fecha de emisión, las directivas de almacenamiento en caché, las cookies de sesión y la longitud o tipo de contenido que se va a transferir.
En la biblioteca requests, las cabeceras de la respuesta se exponen a través del atributo .headers. Este atributo no es un diccionario estándar de Python (dict), sino una instancia de una clase interna especializada llamada requests.structures.CaseInsensitiveDict.
TEXT
El diccionario insensible a mayúsculas y minúsculas
La especificación del protocolo HTTP (RFC 7230) establece explícitamente que los nombres de los campos de las cabeceras no deben distinguir entre mayúsculas y minúsculas. Esto significa que Content-Type, content-type y CONTENT-TYPE hacen referencia exactamente a la misma información.
Si requests utilizara un diccionario común de Python, los desarrolladores se verían obligados a escribir condicionales complejos para prever cómo ha estructurado el servidor sus respuestas, ya que un error de capitalización devolvería una excepción KeyError. Al implementar CaseInsensitiveDict, la biblioteca resuelve este problema de raíz: puedes consultar las cabeceras utilizando cualquier combinación de mayúsculas y minúsculas de forma totalmente transparente.
Recuperación segura de datos con .get()
Aunque las cabeceras se pueden consultar utilizando la sintaxis tradicional de corchetes (respuesta.headers['Cache-Control']), no todos los servidores web envían el mismo conjunto de metadatos. Si intentas acceder a una cabecera que el servidor omitió mediante corchetes, Python lanzará un error de ejecución deteniendo tu programa.
Para escribir código robusto y tolerante a fallos, la mejor práctica consiste en utilizar el método .get(). Este método funciona exactamente igual que el de los diccionarios nativos: permite realizar la consulta de manera segura y definir un valor de retorno por defecto (o None si se omite) en caso de que la cabecera no se encuentre en la respuesta.
Cabeceras comunes de respuesta y su utilidad
Al analizar datos remotos, existen ciertos metadatos que querrás inspeccionar con regularidad:
Content-Type: Indica el tipo de medio del recurso (MIME type). Te ayuda a validar si el servidor te ha devuelto lo que esperabas (por ejemplo,application/jsonfrente atext/html).Content-Length: Expresa el tamaño del cuerpo de la respuesta en bytes puros. Es sumamente útil para validar la integridad de una descarga antes de procesarla por completo.Server: Identifica el software que gestiona el servidor web de origen (por ejemplo,nginx,Apache,cloudflare).Date: La fecha y hora exactas en las que el servidor generó la respuesta HTTP, útil para sincronizar marcas de tiempo.
Implementación práctica en código
El siguiente ejemplo práctico demuestra la insensibilidad a las mayúsculas, la extracción segura de metadatos de red y la iteración completa sobre la estructura de cabeceras:
Python
5.4. Historial de redirecciones
En el ecosistema web, es muy común que un servidor no entregue el recurso directamente en la URL solicitada, sino que ordene al cliente dirigirse a una ubicación diferente. Este fenómeno se conoce como redirección HTTP (identificado comúnmente por códigos de estado de la serie 3xx, como 301 para mudanzas permanentes o 302 para desplazamientos temporales).
Por defecto, la biblioteca requests sigue de forma automática casi todas las redirecciones cuando realizas peticiones de lectura (como GET, OPTIONS o HEAD). Sin embargo, para no perder el rastro de la ruta original que recorrió la petición, el objeto Response final almacena la cadena completa de saltos dentro de su atributo .history.
TEXT
El atributo .history al detalle
El atributo .history es una lista ordenada de Python que contiene objetos Response. Cada elemento de esta lista representa una de las paradas o saltos intermedios que el cliente tuvo que realizar antes de llegar al destino definitivo.
Si una petición va directo a su objetivo sin desvíos, la lista .history estará completamente vacía. En cambio, si el servidor aplica un enrutamiento en cadena, los objetos dentro de .history aparecerán en el orden cronológico exacto en que ocurrieron, permitiéndote auditar los códigos de estado intermedios y las URLs de origen.
El parámetro allow_redirects
Aunque la automatización de redirecciones es cómoda, hay escenarios avanzados —como la auditoría de seguridad, el web scraping preciso o la depuración de APIs— donde necesitas capturar la primera respuesta del servidor sin que la biblioteca salte automáticamente al siguiente enlace.
Para modificar este comportamiento, todos los métodos de petición de requests exponen el parámetro booleano allow_redirects.
allow_redirects=True(Predeterminado enGET,OPTIONS,POST, etc.): Sigue todo el camino hasta el final y rellena el historial.allow_redirects=False: Detiene la ejecución inmediatamente al recibir el primer código 3xx. El objeto devuelto corresponderá a la redirección misma, permitiéndote leer sus cabeceras (como la cabeceraLocation, que indica hacia dónde pretendía enviarte el servidor) y dejando la lista.historyvacía.
Implementación práctica en código
El siguiente ejemplo práctico ilustra cómo inspeccionar un viaje de redirección completo y cómo desactivar el comportamiento automático para analizar la respuesta intermedia:
Python
Resumen del capítulo
En este Capítulo 5: Analizando la Respuesta, hemos explorado a fondo la anatomía de la respuesta que nos devuelve el servidor web al interactuar con la biblioteca requests.
- Aprendimos que el objeto
Responsecentraliza toda la información de la transacción, permitiendo comprobar el éxito de la petición mediante propiedades directas como.status_codeu.ok. - Distinguimos de forma operativa el acceso a datos textuales mediante
.text(que depende de la propiedad mutable.encodingpara la interpretación de caracteres) frente al acceso a datos puros binarios mediante.content. - Analizamos el comportamiento de las cabeceras HTTP a través de la estructura
CaseInsensitiveDict, la cual elimina la sensibilidad a mayúsculas y minúsculas para prevenir errores al buscar metadatos del servidor. - Por último, estudiamos cómo rastrear la ruta de las peticiones que sufren desvíos en la red utilizando el atributo
.history, y cómo tomar el control manual de estos saltos utilizando el parámetroallow_redirects=False.
© 2026 Esdocu. Contenido bajo licencia MIT.
Editar esta página