Guia para usar cURL com Python

Neste artigo, aprenderá como o Python e o cURL podem ser utilizados em conjunto para automatizar pedidos GET, POST e PUT, e para descarregar ficheiros e páginas web.
14 min read
Guide to using cURL with Python

O cURL é uma ferramenta versátil de linha de comandos de código aberto para transferir dados através de uma rede. É fornecido com uma grande variedade de parâmetros para que possa lidar com quase todos os pedidos. Além disso, o cURL é extensível e tem uma interface em praticamente todas as linguagens de programação modernas.

A utilização do cURL com uma linguagem de programação oferece muitas vantagens. Por exemplo, a realização de pedidos pode ser automatizada para casos de utilização de depuração ou de raspagem da web.

Neste artigo, aprenderá como o Python e o cURL podem ser utilizados em conjunto para automatizar pedidos GET, POST e PUT, e para descarregar ficheiros e páginas web.

O que é o cURL?

 

O cURL é um projeto de software, mas o seu nome também é utilizado em dois produtos: uma biblioteca conhecida como libcurl e uma ferramenta de linha de comandos conhecida como curl (que utiliza a libcurl). Neste artigo, o curl refere-se a ferramenta de linha de comandos.

O curl é considerado versátil; no entanto, a sua tarefa principal é simples: transferir dados através de vários protocolos de rede. Dada a complexidade da web atual, o curl vem com uma enorme lista de opções para lidar com os pedidos mais complexos.

O curl foi lançado pela primeira vez em 1996 como HttpGet e mais tarde foi chamado urlget antes de se tornar curl. O seu primeiro caso de utilização foi a obtenção de taxas de câmbio para as utilizar num canal IRC. Atualmente, o curl suporta a transferência de dados através de uma série de métodos, incluindo FTP(S), HTTP(S) (POST, GET, PUT), IMAP, POP3, MQTT e SMB. Além disso, o curl pode lidar com cookies e certificados SSL.

Quando o curl estabelece uma ligação via HTTPS, obtém o certificado do servidor remoto e verifica-o no seu repositório de certificados CA para garantir que o servidor remoto é aquele que diz ser. Por exemplo, o seguinte pedido envia um pedido HTTPS para o sítio web da Bright Data e define um cookie conhecido como greeting com o valor hello:

curl --cookie "greeting=hello" https://www.brightdata.com

Por que usar curl com Python?

Embora o curl seja uma ferramenta versátil, ainda há uma razão principal para querer usá-lo com Python: Python pode automatizar seus pedidos. Seguem-se três casos de utilização em que esta combinação é valiosa:  

Raspagem da Web

A raspagem da web é a prática de coletar (frequentemente grandes) quantidades de dados de uma ou mais páginas web. Para raspar dados com Python, as pessoas geralmente confiam na biblioteca requests. Para fazer raspagem de forma recursiva, pode utilizar wget. No entanto, para casos avançados de utilização de raspagem com chamadas HTTP(S) complexas, curl com Python é ideal.

Embora os dados de uma página web possam ser coletados com um único comando curl que gera e processa um pedido HTTP(S), não o pode fazer recursivamente. Ao incorporar o curl no código Python, pode simular um caminho de navegação num sítio web, manipulando elementos como os parâmetros de pedido, os cookies e os agentes de usuário.

A navegação nem precisa ser corrigida. Ao fazer com que dependa do conteúdo extraído, cada novo pedido pode ser totalmente dinâmico.

Por exemplo, se estiver a coletar a seção de comentários de um sítio web de notícias popular e só quiser coletar a página de perfil do autor, se o comentário contiver palavras-chave de ódio, pode criar uma declaração condicional que dependa dos comentários raspados e aplicar facilmente este filtro dinâmico.

Além disso, muitos sítios web têm mecanismos de segurança que dificultam a raspagem de muitas páginas: pense na proteção contra a negação de serviço distribuída (DDoS) ou num pedido reCAPTCHA. Aplicando certas regras e pausas entre os pedidos, é possível simular um comportamento humano que é mais difícil de detetar.

Testes e depuração

Utilizar o curl no seu próprio sítio web parece um disparate, mas é útil num contexto de testes e depuração. Testar ou depurar uma ou mais características de uma aplicação é muitas vezes uma tarefa complicada. Deve ser testada de forma recorrente e com uma variedade de definições ou parâmetros. Embora existam muitas ferramentas de teste disponíveis no mercado, Python e curl facilitam a configuração de alguns testes rápidos.

Por exemplo, se estiver a lançar um novo fluxo de caixa para o seu serviço em linha (complexo) que utiliza cookies, depende do referenciador, tem pequenas diferenças por navegador (ou seja, agente de usuário) e inclui todos os passos do fluxo de caixa no corpo de um pedido POST, testar manualmente todas as variações pode levar anos. Em Python, é possível criar um dicionário que contenha todo o conjunto de parâmetros e enviar um pedido utilizando curl para cada combinação possível.

Automatização do fluxo de trabalho

Para além dos testes, da depuração e da raspagem da web, o curl pode ser utilizado em casos de uso de automatização do fluxo de trabalho. Por exemplo, muitos canais de integração de dados começam com um despejo recorrente de uma exportação de dados, como um arquivo CSV ou Apache Parquet. Com uma aplicação de Python que procura novos ficheiros num servidor (S)FTP, a cópia de despejos de dados pode ser totalmente automatizada.

Ou considere a possibilidade de configurar mailhooks. Imagine quantas tarefas diárias poderiam ser automatizadas se uma aplicação pudesse procurar mensagens de correio eletrónico que contivessem uma consulta. Ao sondar novas mensagens através do protocolo POP3 ou IMAP, as aplicações de Python podem ser acionadas quando uma caixa de correio recebe um correio específico.

Como usar cURL com Python

Existem várias maneiras de fazer pedidos usando curl em Python. Este artigo aborda duas opções. A primeira é simular pedidos curl na linha de comando através dos pacotes de Python os e subprocess. Esta abordagem simples envia comandos de forma programática para a interface de linha de comandos do seu sistema operativo.

A segunda opção é usar o pacote PycURL. Se você quiser aprender sobre outras formas de raspar sítios web com Python (sem usar curl), pode consultar este guia de Raspagem com Python da Bright Data.

Pré-requisitos

Antes de começar este tutorial, certifique-se de ter baixado e instalado o curl. Se você usa o Windows, certifique-se de adicionar curl à sua variável de ambiente PATH para que você possa simplesmente executar o comando curl .

Para criar uma interface Python com o seu sistema operativo, pode utilizar vários pacotes. No entanto, os dois mais populares são os e subprocess. Para instalar os dois, execute o seguinte comando pip:

pip install os subprocess

Fazer um pedido usando curl e os

O pacote os é um pacote extremamente simples. Executar um pedido curl sem processar a resposta requer apenas duas linhas de código. Só precisa de passar o cookie descrito no exemplo anterior, e o resultado é escrito no ficheiro output.txt:

import os
os.system('curl -o output.txt --cookie "greeting=hello" -k https://curl.se')

Se quiser processar a resposta em Python em vez de a escrever num ficheiro, deve utilizar o pacote subprocess discutido na próxima secção.

O código a seguir executará a mesma instrução, mas em vez de escrever a resposta num ficheiro, emitirá o stdout e o stderr como uma tupla. Esta saída pode então ser processada com outros pacotes de Python, como o Beautiful Soup:

import shlex
import subprocess
shell_cmd = shlex.split('curl --cookie "greeting=hello" -k https://curl.se')
process = subprocess.Popen(shell_cmd,
                    stdout = subprocess.PIPE,
                    stderr = subprocess.PIPE,
                    text = True,
                    shell = True
                    )
std_out, std_err = process.communicate()
std_out.strip(), std_err

Usar PycURL

Em vez de fazer a interface com o seu terminal em Python, pode utilizar o pacote PycURL. Se é um usuário de Linux, está com sorte, pois pode instalar o PycURL utilizando o pip:

pip install pycurl
pip install certifi

Deve também instalar certifi para fazer a interface através do protocolo HTTPS. Se tiver problemas, siga estas instruções do Stack Overflow.

Embora o PycURL também possa ser instalado no Windows, é uma tarefa muito frustrante. Se você tentar instalá-lo via pip, retornará o seguinte erro:

Please specify --curl-dir=/path/to/built/libcurl

É por isso que é necessário instalá-lo a partir da fonte, o que “não é para os fracos de coração devido à multiplicidade de dependências possíveis, e cada uma dessas dependências tem a sua própria estrutura de diretórios, estilo de configuração, parâmetros e peculiaridades“. Por este motivo, recomenda-se a utilização do pacote requests para pedidos de rede básicos se estiver a trabalhar numa máquina Windows.

Como fazer pedidos com PycURL

O restante deste artigo aborda a criação de vários tipos de pedidos usando o pacote PycURL.

Fazer um pedido GET com PycURL

O pedido mais fácil que pode fazer usando PycURL é um pedido GET. É basicamente um modelo para todos os outros modelos desta seção.

É possível identificar cinco etapas no código seguinte:

  1. Todos os pacotes necessários são importados.
  2. Dois objetos são criados: o buffer (memória intermédia) no qual o pedido curl armazenará sua resposta, e o objeto curl, que é usado para fazer o pedido.
  3. As opções da solicitação são especificadas: o URL, o destino e a validação de SSL.
  4. A execução do pedido.
  5. O resultado do pedido.
# Preparation
import pycurl
import certifi
from io import BytesIO

# Set buffer and Curl object.
buffer = BytesIO()
c = pycurl.Curl()

# Set request options.
## Set the request destination.
c.setopt(c.URL, 'http://pycurl.io/')

## Set the buffer as the destination of the request's response.
c.setopt(c.WRITEDATA, buffer)

## Refer to the installed certificate authority bundle for validating the SSL certificate.
c.setopt(c.CAINFO, certifi.where())

# Execute and close the request.
c.perform()
c.close()

# Print the buffer's content with a Latin1 (iso-8859-1) encoding.
body = buffer.getvalue()
data = body.decode('iso-8859-1')
print(data)

Fazer um pedido POST com PycURL

Fazer um pedido POST com PycURL é muito semelhante a fazer um pedido GET. No entanto, uma opção extra é adicionada ao pedido: o corpo do POST. No trecho de código a seguir, um valor-chave é definido e codificado por URL para garantir que seja processado adequadamente:

# Preparation
import pycurl
import certifi
from io import BytesIO

# Set buffer and Curl object.
buffer = BytesIO()
c = pycurl.Curl()

# Set request options.
## Set the request destination.
c.setopt(c.URL, 'http://pycurl.io/')

## Set the request's body.
post_body = {'greeting': 'hello'}
postfields = urlencode(post_body)
c.setopt(c.POSTFIELDS, postfields)

## Set the buffer as the destination of the request's response.
c.setopt(c.WRITEDATA, buffer)

## Refer to the installed certificate authority bundle for validating the SSL certificate.
c.setopt(c.CAINFO, certifi.where())

# Execute and close the request.
c.perform()
c.close()

# Print the buffer's content with a Latin1 (iso-8859-1) encoding.
body = buffer.getvalue()
print(body.decode('iso-8859-1'))

Fazer um pedido PUT com PycURL

O pedido POST que criou na seção anterior também pode ser enviado como um pedido PUT. Em vez de enviar o valor-chave no corpo do pedido, você o enviará como uma representação de ficheiro codificada em UTF-8. Este método também pode ser utilizado para carregar ficheiros:

import pycurl
import certifi
from io import BytesIO

c = pycurl.Curl()

# Set request options.
## Set the request destination.
c.setopt(c.URL, 'http://pycurl.io/')

## Set data for the PUT request.
c.setopt(c.UPLOAD, 1)
data = '{"greeting": "hello"}'
buffer = BytesIO(data.encode('utf-8'))
c.setopt(c.READDATA, buffer)

## Refer to the installed certificate authority bundle for validating the SSL certificate.
c.setopt(c.CAINFO, certifi.where())

# Execute and close the request.
c.perform()
c.close()

Baixar um ficheiro com PycURL

O próximo trecho demonstra como baixar um ficheiro usando PycURL. Uma imagem JPEG aleatória é solicitada e um fluxo de registo é aberto para some_image.jpg e passado para PycURL como o destino do ficheiro:

import pycurl
import certifi

c = pycurl.Curl()

# Set the request destination.
c.setopt(c.URL, 'http://pycurl.io/some_image.jpg')

# Refer to the installed certificate authority bundle for validating the SSL certificate.
c.setopt(c.CAINFO, certifi.where())

# Execute and close the request.
with open('some_image.jpg', 'w') as f:
    c.setopt(c.WRITEFUNCTION, f.write)
    c.perform()

c.close()

Baixar e processar uma página web com PycURL

Como muitos casos de uso do PycURL envolvem raspagem da web, o próximo trecho descreve como você pode processar a resposta de um pedido com Beautiful Soup, um pacote popular para analisar arquivos HTML.

Primeiro, instale Beautiful Soup 4 usando o pip:

pip install beautifulsoup4

Depois, coloque o próximo trecho logo atrás do primeiro trecho PycURL que fez um pedido GET. Isto fará com que o Beautiful Soup processe os dados de resposta.

Para demonstração, o método find_all é utilizado para encontrar todos os elementos do parágrafo e o conteúdo dos parágrafos individuais é impresso:

from bs4 import BeautifulSoup

# Parsing data using BeautifulSoup
soup = BeautifulSoup(data, 'html.parser')

# Find all paragraphs
paragraphs = soup.find_all('p')
for p in paragraphs:
   print(p.text)

Usar um Proxy com PycURL

A raspagem da web em escala funciona melhor quando se trabalha com proxies. A vantagem é que pode emular o comportamento de navegação em paralelo sem que o seu raspador seja assinalado como um bot ou como tendo um comportamento anómalo.

Nesta seção final, aprenderá como pode criar um pedido com PycURL através de um proxy. Isto é conseguido ajustando as opções de pedido, como fez anteriormente. Em seguida, quatro configurações são descritas, mas você pode ajustá-las à sua situação:

  1. Para facilitar, proxies inseguros são habilitados.
  2. O servidor proxy está definido.
  3. O script autentica-se com o servidor.
  4. O proxy está definido como HTTPS.
# Enable insecure proxies
c.setopt(c.PROXY_SSL_VERIFYHOST, 0)
c.setopt(c.PROXY_SSL_VERIFYPEER, 0)

# Set proxy server
c.setopt(pycurl.PROXY, <YOUR_HTTPS_PROXY_SERVER>)

# Authenticate with the proxy server
c.setopt(pycurl.PROXYUSERPWD, f"{<YOUR_USERNAME>}:{<YOUR_PASSWORD>}")

# Set proxy type to https
c.setopt(pycurl.PROXYTYPE, 2)

Estas opções podem ser inseridas em qualquer parte de um trecho de código descrito anteriormente para fazer com que o pedido seja redirecionado através do servidor proxy.

Conclusão

Neste artigo, a combinação de curl e Python foi explicada em detalhes, destacando por que você gostaria de usá-los juntos para gerar pedidos complexos para casos de uso de raspagem da web e teste de aplicativos. Vários exemplos foram fornecidos para demonstrar a versatilidade do PycURL para gerar uma infinidade de pedidos de rede.

Em alternativa, pode utilizar a Rede de Proxy da Bright Data e o seu IDE para Raspador da Web, que foi especificamente concebido para lidar com todo o trabalho pesado para os programadores. Desta forma, pode concentrar-se em trabalhar com os dados extraídos em vez de se preocupar em ultrapassar os mecanismos antirraspagem.