Introdução
A biblioteca Python requests é uma ferramenta poderosa para interagir com serviços web e APIs. Neste tutorial, você aprenderá como enviar requisições HTTP e analisar dados de resposta usando Python. Ao final deste laboratório, você será capaz de extrair informações valiosas de diferentes tipos de respostas de API, permitindo que você construa aplicações orientadas a dados e automatize interações web.
Instalando a Biblioteca Requests e Fazendo uma Requisição Básica
Neste primeiro passo, instalaremos a biblioteca Python requests e faremos nossa primeira requisição HTTP para recuperar dados de uma API pública.
Instalando Requests
A biblioteca requests é um pacote de terceiros que precisa ser instalado usando o pip, o instalador de pacotes do Python. Vamos começar instalando-o:
pip install requests
Você deve ver uma saída confirmando que o requests foi instalado com sucesso.
Fazendo Sua Primeira Requisição HTTP
Agora, vamos criar um arquivo Python para fazer uma requisição HTTP simples. No WebIDE, crie um novo arquivo chamado basic_request.py no diretório /home/labex/project.
Adicione o seguinte código ao arquivo:
import requests
## Make a GET request to a public API
response = requests.get("https://jsonplaceholder.typicode.com/todos/1")
## Print the status code
print(f"Status code: {response.status_code}")
## Print the raw response content
print("\nRaw response content:")
print(response.text)
## Print the response headers
print("\nResponse headers:")
for header, value in response.headers.items():
print(f"{header}: {value}")
Este código faz uma requisição GET para um endpoint de API de exemplo e imprime informações sobre a resposta.
Entendendo o Objeto de Resposta
Vamos executar o código para ver quais informações recebemos de volta. No terminal, execute:
python basic_request.py
Você deve ver uma saída semelhante a esta:
Status code: 200
Raw response content:
{
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
}
Response headers:
Date: Mon, 01 Jan 2023 12:00:00 GMT
Content-Type: application/json; charset=utf-8
...
O objeto de resposta contém vários atributos importantes:
status_code: Código de status HTTP (200 significa sucesso)text: O conteúdo da resposta como uma stringheaders: Um dicionário de cabeçalhos de resposta
Ao trabalhar com requisições web, esses atributos ajudam você a entender a resposta do servidor e tratá-la adequadamente.
Códigos de Status HTTP
Os códigos de status HTTP indicam se uma requisição foi bem-sucedida ou falhou:
- 2xx (como 200): Sucesso
- 3xx (como 301): Redirecionamento
- 4xx (como 404): Erros do cliente
- 5xx (como 500): Erros do servidor
Vamos modificar nosso código para verificar uma resposta bem-sucedida. Crie um novo arquivo chamado check_status.py com este conteúdo:
import requests
try:
## Make a GET request to a valid URL
response = requests.get("https://jsonplaceholder.typicode.com/todos/1")
## Check if the request was successful
if response.status_code == 200:
print("Request successful!")
else:
print(f"Request failed with status code: {response.status_code}")
## Try an invalid URL
invalid_response = requests.get("https://jsonplaceholder.typicode.com/invalid")
print(f"Invalid URL status code: {invalid_response.status_code}")
except requests.exceptions.RequestException as e:
print(f"An error occurred: {e}")
Execute este código para ver como diferentes URLs retornam diferentes códigos de status:
python check_status.py
Você deve ver que a URL válida retorna o código de status 200, enquanto a URL inválida retorna o código de status 404.
Analisando Dados de Resposta JSON
Muitas APIs modernas retornam dados no formato JSON (JavaScript Object Notation). Nesta etapa, você aprenderá como analisar respostas JSON e trabalhar com os dados em Python.
Entendendo JSON
JSON é um formato leve de intercâmbio de dados que é fácil para humanos lerem e escreverem, e fácil para máquinas analisarem e gerarem. Ele é baseado em pares chave-valor, semelhante aos dicionários Python.
Aqui está um exemplo de um objeto JSON:
{
"name": "John Doe",
"age": 30,
"email": "john@example.com",
"is_active": true,
"hobbies": ["reading", "swimming", "cycling"]
}
Analisando Respostas JSON
A biblioteca requests facilita a análise de respostas JSON usando o método .json(). Vamos criar um novo arquivo chamado parse_json.py e adicionar o seguinte código:
import requests
## Make a request to a GitHub API endpoint that returns JSON data
response = requests.get("https://api.github.com/users/python")
## Check if the request was successful
if response.status_code == 200:
## Parse the JSON response
data = response.json()
## Print the parsed data
print("Parsed JSON data:")
print(f"Username: {data['login']}")
print(f"Name: {data.get('name', 'Not provided')}")
print(f"Followers: {data['followers']}")
print(f"Public repositories: {data['public_repos']}")
## Print the type to verify it's a Python dictionary
print(f"\nType of parsed data: {type(data)}")
## Access nested data
print("\nAccessing specific elements:")
print(f"Avatar URL: {data['avatar_url']}")
else:
print(f"Request failed with status code: {response.status_code}")
Execute este script para ver como os dados JSON são analisados em um dicionário Python:
python parse_json.py
Você deve ver uma saída que exibe informações sobre o usuário do GitHub, incluindo seu nome de usuário, contagem de seguidores e contagem de repositórios.
Trabalhando com Listas de Dados
Muitas APIs retornam listas de objetos. Vamos ver como lidar com esse tipo de resposta. Crie um arquivo chamado json_list.py com este conteúdo:
import requests
## Make a request to an API that returns a list of posts
response = requests.get("https://jsonplaceholder.typicode.com/posts")
## Check if the request was successful
if response.status_code == 200:
## Parse the JSON response (this will be a list of posts)
posts = response.json()
## Print the total number of posts
print(f"Total posts: {len(posts)}")
## Print details of the first 3 posts
print("\nFirst 3 posts:")
for i, post in enumerate(posts[:3], 1):
print(f"\nPost #{i}")
print(f"User ID: {post['userId']}")
print(f"Post ID: {post['id']}")
print(f"Title: {post['title']}")
print(f"Body: {post['body'][:50]}...") ## Print just the beginning of the body
else:
print(f"Request failed with status code: {response.status_code}")
Execute este script para ver como processar uma lista de objetos JSON:
python json_list.py
Você deve ver informações sobre as três primeiras postagens, incluindo seus títulos e o início de seu conteúdo.
Tratamento de Erros com Análise JSON
Às vezes, uma resposta pode não conter dados JSON válidos. Vamos ver como lidar com isso de forma adequada. Crie um arquivo chamado json_error.py com este código:
import requests
import json
def get_and_parse_json(url):
try:
## Make the request
response = requests.get(url)
## Check if the request was successful
response.raise_for_status()
## Try to parse the JSON
try:
data = response.json()
return data
except json.JSONDecodeError:
print(f"Response from {url} is not valid JSON")
print(f"Raw response: {response.text[:100]}...") ## Print part of the raw response
return None
except requests.exceptions.HTTPError as e:
print(f"HTTP error: {e}")
except requests.exceptions.RequestException as e:
print(f"Request error: {e}")
return None
## Test with a valid JSON endpoint
json_data = get_and_parse_json("https://jsonplaceholder.typicode.com/posts/1")
if json_data:
print("\nValid JSON response:")
print(f"Title: {json_data['title']}")
## Test with a non-JSON endpoint
html_data = get_and_parse_json("https://www.example.com")
if html_data:
print("\nThis should not print as example.com returns HTML, not JSON")
else:
print("\nAs expected, could not parse HTML as JSON")
Execute este script para ver como lidar com diferentes tipos de respostas:
python json_error.py
Você deve ver que o código lida com sucesso com respostas JSON válidas e respostas não JSON.
Analisando Conteúdo HTML com BeautifulSoup
Ao trabalhar com dados da web, você frequentemente encontrará respostas HTML. Para analisar HTML, a biblioteca BeautifulSoup do Python é uma excelente ferramenta. Nesta etapa, aprenderemos como extrair informações de respostas HTML.
Instalando BeautifulSoup
Primeiro, vamos instalar BeautifulSoup e seu analisador HTML:
pip install beautifulsoup4
Análise HTML Básica
Vamos criar um arquivo chamado parse_html.py para buscar e analisar uma página da web:
import requests
from bs4 import BeautifulSoup
## Make a request to a webpage
url = "https://www.example.com"
response = requests.get(url)
## Check if the request was successful
if response.status_code == 200:
## Parse the HTML content
soup = BeautifulSoup(response.text, 'html.parser')
## Extract the page title
title = soup.title.text
print(f"Page title: {title}")
## Extract all paragraphs
paragraphs = soup.find_all('p')
print(f"\nNumber of paragraphs: {len(paragraphs)}")
## Print the text of the first paragraph
if paragraphs:
print(f"\nFirst paragraph text: {paragraphs[0].text.strip()}")
## Extract all links
links = soup.find_all('a')
print(f"\nNumber of links: {len(links)}")
## Print the href attribute of the first link
if links:
print(f"First link href: {links[0].get('href')}")
else:
print(f"Request failed with status code: {response.status_code}")
Execute este script para ver como extrair informações básicas de uma página HTML:
python parse_html.py
Você deve ver a saída mostrando o título da página, o número de parágrafos, o texto do primeiro parágrafo, o número de links e a URL do primeiro link.
Encontrando Elementos Específicos
Agora, vamos ver como encontrar elementos específicos usando seletores CSS. Crie um arquivo chamado html_selectors.py:
import requests
from bs4 import BeautifulSoup
## Make a request to a webpage with more complex structure
url = "https://quotes.toscrape.com/"
response = requests.get(url)
## Check if the request was successful
if response.status_code == 200:
## Parse the HTML content
soup = BeautifulSoup(response.text, 'html.parser')
## Find all quote elements
quote_elements = soup.select('.quote')
print(f"Number of quotes found: {len(quote_elements)}")
## Process the first 3 quotes
print("\nFirst 3 quotes:")
for i, quote_element in enumerate(quote_elements[:3], 1):
## Extract the quote text
text = quote_element.select_one('.text').text
## Extract the author
author = quote_element.select_one('.author').text
## Extract the tags
tags = [tag.text for tag in quote_element.select('.tag')]
## Print the information
print(f"\nQuote #{i}")
print(f"Text: {text}")
print(f"Author: {author}")
print(f"Tags: {', '.join(tags)}")
else:
print(f"Request failed with status code: {response.status_code}")
Execute este script para ver como usar seletores CSS para extrair elementos específicos:
python html_selectors.py
Você deve ver a saída mostrando informações sobre as três primeiras citações, incluindo o texto da citação, o autor e as tags.
Construindo um Web Scraper Simples
Vamos juntar tudo para construir um web scraper simples que extrai dados estruturados de uma página da web. Crie um arquivo chamado quotes_scraper.py:
import requests
from bs4 import BeautifulSoup
import json
import os
def scrape_quotes_page(url):
## Make a request to the webpage
response = requests.get(url)
## Check if the request was successful
if response.status_code != 200:
print(f"Request failed with status code: {response.status_code}")
return None
## Parse the HTML content
soup = BeautifulSoup(response.text, 'html.parser')
## Extract all quotes
quotes = []
for quote_element in soup.select('.quote'):
## Extract the quote text
text = quote_element.select_one('.text').text.strip('"')
## Extract the author
author = quote_element.select_one('.author').text
## Extract the tags
tags = [tag.text for tag in quote_element.select('.tag')]
## Add the quote to our list
quotes.append({
'text': text,
'author': author,
'tags': tags
})
## Check if there's a next page
next_page = soup.select_one('.next a')
next_page_url = None
if next_page:
next_page_url = 'https://quotes.toscrape.com' + next_page['href']
return {
'quotes': quotes,
'next_page': next_page_url
}
## Scrape the first page
result = scrape_quotes_page('https://quotes.toscrape.com/')
if result:
## Print information about the quotes found
quotes = result['quotes']
print(f"Found {len(quotes)} quotes on the first page")
## Print the first 2 quotes
print("\nFirst 2 quotes:")
for i, quote in enumerate(quotes[:2], 1):
print(f"\nQuote #{i}")
print(f"Text: {quote['text']}")
print(f"Author: {quote['author']}")
print(f"Tags: {', '.join(quote['tags'])}")
## Save the quotes to a JSON file
output_dir = '/home/labex/project'
with open(os.path.join(output_dir, 'quotes.json'), 'w') as f:
json.dump(quotes, f, indent=2)
print(f"\nSaved {len(quotes)} quotes to {output_dir}/quotes.json")
## Print information about the next page
if result['next_page']:
print(f"\nNext page URL: {result['next_page']}")
else:
print("\nNo next page available")
Execute este script para extrair citações de um site:
python quotes_scraper.py
Você deve ver a saída mostrando informações sobre as citações encontradas na primeira página, e as citações serão salvas em um arquivo JSON chamado quotes.json.
Verifique o arquivo JSON para ver os dados estruturados:
cat quotes.json
O arquivo deve conter uma matriz JSON de objetos de citação, cada um com propriedades de texto, autor e tags.
Trabalhando com Conteúdo de Resposta Binária
Até agora, nos concentramos em respostas baseadas em texto, como JSON e HTML. No entanto, a biblioteca requests também pode lidar com conteúdo binário, como imagens, PDFs e outros arquivos. Nesta etapa, aprenderemos como baixar e processar conteúdo binário.
Baixando uma Imagem
Vamos começar baixando uma imagem. Crie um arquivo chamado download_image.py:
import requests
import os
## URL of an image to download
image_url = "https://httpbin.org/image/jpeg"
## Make a request to get the image
response = requests.get(image_url)
## Check if the request was successful
if response.status_code == 200:
## Get the content type
content_type = response.headers.get('Content-Type', '')
print(f"Content-Type: {content_type}")
## Check if the content is an image
if 'image' in content_type:
## Create a directory to save the image if it doesn't exist
output_dir = '/home/labex/project/downloads'
os.makedirs(output_dir, exist_ok=True)
## Save the image to a file
image_path = os.path.join(output_dir, 'sample_image.jpg')
with open(image_path, 'wb') as f:
f.write(response.content)
## Print information about the saved image
print(f"Image saved to: {image_path}")
print(f"Image size: {len(response.content)} bytes")
else:
print("The response does not contain an image")
else:
print(f"Request failed with status code: {response.status_code}")
Execute este script para baixar uma imagem:
python download_image.py
Você deve ver a saída confirmando que a imagem foi baixada e salva em /home/labex/project/downloads/sample_image.jpg.
Baixando um Arquivo com Progresso
Ao baixar arquivos grandes, pode ser útil exibir um indicador de progresso. Vamos criar um script que mostra o progresso do download. Crie um arquivo chamado download_with_progress.py:
import requests
import os
import sys
def download_file(url, filename):
## Make a request to get the file
## Stream the response to handle large files efficiently
response = requests.get(url, stream=True)
## Check if the request was successful
if response.status_code != 200:
print(f"Request failed with status code: {response.status_code}")
return False
## Get the total file size if available
total_size = int(response.headers.get('Content-Length', 0))
if total_size:
print(f"Total file size: {total_size/1024:.2f} KB")
else:
print("Content-Length header not found. Unable to determine file size.")
## Create a directory to save the file if it doesn't exist
os.makedirs(os.path.dirname(filename), exist_ok=True)
## Download the file in chunks and show progress
print(f"Downloading {url} to {filename}...")
## Initialize variables for progress tracking
downloaded = 0
chunk_size = 8192 ## 8 KB chunks
## Open the file for writing
with open(filename, 'wb') as f:
## Iterate through the response chunks
for chunk in response.iter_content(chunk_size=chunk_size):
if chunk: ## Filter out keep-alive chunks
f.write(chunk)
downloaded += len(chunk)
## Calculate and display progress
if total_size:
percent = downloaded * 100 / total_size
sys.stdout.write(f"\rProgress: {percent:.1f}% ({downloaded/1024:.1f} KB)")
sys.stdout.flush()
else:
sys.stdout.write(f"\rDownloaded: {downloaded/1024:.1f} KB")
sys.stdout.flush()
## Print a newline to ensure the next output starts on a new line
print()
return True
## URL of a file to download
file_url = "https://speed.hetzner.de/100MB.bin"
## Path where the file will be saved
output_path = '/home/labex/project/downloads/test_file.bin'
## Download the file
success = download_file(file_url, output_path)
if success:
## Get file stats
file_size = os.path.getsize(output_path)
print(f"\nDownload complete!")
print(f"File saved to: {output_path}")
print(f"File size: {file_size/1024/1024:.2f} MB")
else:
print("\nDownload failed.")
Execute este script para baixar um arquivo com acompanhamento de progresso:
python download_with_progress.py
Você verá uma barra de progresso sendo atualizada conforme o arquivo é baixado. Observe que isso baixa um arquivo de 100MB, o que pode levar algum tempo dependendo da velocidade da sua conexão.
Para cancelar o download, você pode pressionar Ctrl+C.
Trabalhando com Cabeçalhos de Resposta e Metadados
Ao baixar arquivos, os cabeçalhos de resposta geralmente contêm metadados úteis. Vamos criar um script que examina os cabeçalhos de resposta em detalhes. Crie um arquivo chamado response_headers.py:
import requests
def check_url(url):
print(f"\nChecking URL: {url}")
try:
## Make a HEAD request first to get headers without downloading the full content
head_response = requests.head(url)
print(f"HEAD request status code: {head_response.status_code}")
if head_response.status_code == 200:
## Print all headers
print("\nResponse headers:")
for header, value in head_response.headers.items():
print(f" {header}: {value}")
## Extract content type and size
content_type = head_response.headers.get('Content-Type', 'Unknown')
content_length = head_response.headers.get('Content-Length', 'Unknown')
print(f"\nContent Type: {content_type}")
if content_length != 'Unknown':
size_kb = int(content_length) / 1024
size_mb = size_kb / 1024
if size_mb >= 1:
print(f"Content Size: {size_mb:.2f} MB")
else:
print(f"Content Size: {size_kb:.2f} KB")
else:
print("Content Size: Unknown")
## Check if the server supports range requests
accept_ranges = head_response.headers.get('Accept-Ranges', 'none')
print(f"Supports range requests: {'Yes' if accept_ranges != 'none' else 'No'}")
else:
print(f"HEAD request failed with status code: {head_response.status_code}")
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
## Check a few different URLs
check_url("https://httpbin.org/image/jpeg")
check_url("https://speed.hetzner.de/100MB.bin")
check_url("https://example.com")
Execute este script para ver informações detalhadas sobre os cabeçalhos de resposta:
python response_headers.py
Você verá a saída mostrando os cabeçalhos para diferentes tipos de conteúdo, incluindo imagens, arquivos binários e páginas HTML.
Compreender os cabeçalhos de resposta é crucial para muitas tarefas de desenvolvimento web, como:
- Determinar tipos e tamanhos de arquivos antes de baixar
- Implementar downloads retomáveis com solicitações de intervalo (range requests)
- Verificar políticas de cache e datas de expiração
- Lidar com redirecionamentos e autenticação
Resumo
Neste laboratório, você aprendeu a trabalhar com a biblioteca requests do Python para interagir com serviços web e APIs. Agora você tem as habilidades para:
- Fazer requisições HTTP e lidar com códigos de status e erros de resposta
- Analisar dados JSON de respostas de API
- Extrair informações de conteúdo HTML usando BeautifulSoup
- Baixar e processar conteúdo binário, como imagens e arquivos
- Trabalhar com cabeçalhos de resposta e metadados
Essas habilidades formam a base para muitas aplicações Python, incluindo web scraping, integração de API, coleta de dados e automação. Agora você pode construir aplicações que interagem com serviços web, extraem informações úteis de sites e processam vários tipos de conteúdo web.
Para continuar aprendendo, você pode querer explorar:
- Métodos de autenticação para acessar APIs protegidas
- Trabalhar com APIs mais complexas que exigem cabeçalhos ou formatos de requisição específicos
- Construir um projeto completo de web scraping que coleta e analisa dados
- Criar uma aplicação Python que se integra a múltiplas APIs
Lembre-se que, ao fazer web scraping ou usar APIs, é importante verificar os termos de serviço e respeitar os limites de taxa para evitar ser bloqueado.



