Como executar solicitações HTTP com Python - Parte 1 A Biblioteca Padrão
- 3142
- 980
- Leroy Lebsack
HTTP é o protocolo usado pela World Wide Web, é por isso que ser capaz de interagir com ele programaticamente é essencial: raspar uma página da web, se comunicar com uma APIs de serviço ou mesmo simplesmente baixar um arquivo, são todas as tarefas com base nessa interação. O Python facilita muito essas operações: algumas funções úteis já são fornecidas na biblioteca padrão e, para tarefas mais complexas, é possível (e até recomendado) usar o externo solicitações de
módulo. Neste primeiro artigo da série, focaremos nos módulos internos. Usaremos o Python3 e principalmente trabalharemos dentro da concha interativa do Python: as bibliotecas necessárias serão importadas apenas uma vez para evitar repetições.
Neste tutorial, você aprenderá:
- Como executar solicitações HTTP com Python3 e o urllib.Solicitar biblioteca
- Como trabalhar com respostas ao servidor
- Como baixar um arquivo usando o URLOPEN ou as funções URLrevieve
Solicitação http com python - pt. I: a biblioteca padrão
Requisitos de software e convenções usadas
Categoria | Requisitos, convenções ou versão de software usada |
---|---|
Sistema | Independente do OS |
Programas | Python3 |
Outro |
|
Convenções | # - requer que os comandos Linux sejam executados com privilégios root diretamente como usuário root ou por uso de sudo comando$ - Requer que os comandos do Linux sejam executados como um usuário não privilegiado regular |
Executando solicitações com a biblioteca padrão
Vamos começar com um muito fácil PEGAR
solicitar. O verbo get http é usado para recuperar dados de um recurso. Ao executar esse tipo de solicitação, é possível especificar alguns parâmetros nas variáveis de formulário: essas variáveis, expressas como pares de valor-chave, formam um string de consulta
que é "anexado" ao Url
do recurso. Uma solicitação de get deve sempre ser idempotent
(Isso significa que o resultado da solicitação deve ser independente do número de vezes que é realizado) e nunca deve ser usado para mudar um estado. Executar solicitações de get com python é realmente fácil. Para o bem deste tutorial, aproveitaremos a chamada aberta da API da NASA, que nos vamos recuperar a chamada "foto do dia":
>>> de urllib.Solicite Urlopen de importação >>> com Urlopen ("https: // API.NASA.Gov/planetário/apod?api_key = Demo_key ") como resposta: ... resposta_content = resposta.ler()
cópia de A primeira coisa que fizemos foi importar o urlopen
função do urllib.solicitar
Biblioteca: esta função retorna um http.cliente.Httpro -resposta
objeto que tem alguns métodos muito úteis. Usamos a função dentro de um com
declaração porque o Httpro -resposta
Objeto suporta o gerenciamento de contexto
Protocolo: os recursos são imediatamente fechados após a declaração "com" é executada, mesmo que um exceção
é levantado.
O ler
Método que usamos no exemplo acima retorna o corpo do objeto de resposta como um bytes
e opcionalmente, leva um argumento que representa a quantidade de bytes para ler (veremos mais adiante como isso é importante em alguns casos, especialmente ao baixar arquivos grandes). Se esse argumento for omitido, o corpo da resposta é lido na íntegra.
Neste ponto, temos o corpo da resposta como um objeto de bytes
, referenciado pelo Response_content
variável. Podemos querer transformá -lo em outra coisa. Para transformá -lo em uma corda, por exemplo, usamos o decodificar
Método, fornecendo o tipo de codificação como argumento, normalmente:
>>> Response_Content.Decode ('UTF-8')
No exemplo acima, usamos o UTF-8
codificação. A chamada da API que usamos no exemplo, no entanto, retorna uma resposta em JSON
formato, portanto, queremos processá -lo com a ajuda do JSON
módulo:
>>> Importar json json_ropnse = json.Cargas (Response_Content)
cópia de O JSON.Cargas
Método desaperializa a corda
, a bytes
ou a bytearray
instância contendo um documento JSON em um objeto Python. O resultado de chamar a função, neste caso, é um dicionário:
>>> De Pprint Importar Pprint >>> Pprint (JSON_RESPONIFICADO) 'DATE': '2019-04-14', 'Explicação': 'Sente-se e assista a dois buracos negros mesclados mesclar. Inspirado na 'Primeira detecção direta de ondas gravitacionais em 2015, este vídeo de simulação é reproduzido em câmera lenta, mas aceitaria' 'um terço de segundo se for executado em tempo real. Situado em um palco cósmico, os buracos negros são colocados na frente de estrelas, gás e '' poeira. Sua extrema gravidade lentes a luz por trás deles '' em Einstein toca enquanto eles se aproximam e finalmente se fundem '' em um. As ondas gravitacionais invisíveis '' geradas à medida que os objetos maciços se fundem rapidamente fazem com que a imagem visível '' ondule e slosh, dentro e fora dos anéis de 'Einstein, mesmo depois que os buracos negros se fundiram. Apelidado de '' GW150914, as ondas gravitacionais detectadas pelo LIGO são '' consistentes com a fusão de 36 e 31 orifícios de preto de massa solar 'a uma distância de 1.3 bilhões de anos-luz. O final, '' Hole Black Hole tem 63 vezes a massa do sol, com as 3 massas solares restantes convertidas em energia em '' ondas gravitacionais. Desde então, os observatórios de ondas gravitacionais do Ligo e Virgem relataram várias outras detecções de fusão de sistemas maciços, enquanto na semana passada o telescópio '' do evento Horizon relatou a primeira imagem da escala de horizonte de um buraco negro de um buraco negro.',' Media_type ':' Video ',' Service_version ':' V1 ',' Title ':' Simulation: Two Black Hole Merge ',' Url ':' https: // www.YouTube.COM/INCED/I_88S8DWBCU?rel = 0 '
cópia de Como alternativa, também poderíamos usar o json_load
função (observe a falta de "s" que faltava). A função aceita um como um arquivo
objeto como argumento: isso significa que podemos usá -lo diretamente no Httpro -resposta
objeto:
>>> com urlopen ("https: // API.NASA.Gov/planetário/apod?api_key = Demo_key ") como resposta: ... JSON_RESPONSENTE = JSON.Carga (resposta)
cópia de Lendo os cabeçalhos de resposta
Outro método muito útil utilizável no Httpro -resposta
objeto é Getheaders
. Este método retorna o cabeçalhos
da resposta como uma variedade de tuplas. Cada tupla contém um parâmetro de cabeçalho e seu valor correspondente:
>>> Pprint (resposta.GETHEADERS ()) [('servidor', 'OpenResty'), ('Date', 'Sun, 14 de abril de 2019 10:08:48 GMT'), ('Content-Type', 'Application/json'), ( 'Length-comprimento', '1370'), ('Connection', 'Close'), ('Vary', 'Acep-Encoding'), ('X-Ratelimit-Limit', '40'), ('X x -Ratelimit-Remaining ',' 37 '), (' via ',' 1.1 VEGUR, HTTP/1.1 API-UBRELLA (APACHETRAFFICSERVER [CMSSF]) '), (' Age ',' 1 '), (' X-cache ',' Miss '), (' Access-Control-Alow-Origin ','*') , ('Strict-Transport-Security', 'Max-Iage = 31536000; Preload')]]
Você pode notar, entre os outros, o Tipo de conteúdo
parâmetro, que, como dissemos acima, é Aplicação/JSON
. Se quisermos recuperar apenas um parâmetro específico, podemos usar o GETHEADER
Método, em vez disso, passando o nome do parâmetro como argumento:
>>> resposta.Getheader ('Content-Type') 'Aplicativo/JSON'
cópia de Obtendo o status da resposta
Obtendo o código de status e Phrase da razão
devolvido pelo servidor após uma solicitação HTTP também é muito fácil: tudo o que precisamos fazer é acessar o status
e razão
propriedades do Httpro -resposta
objeto:
>>> resposta.Status 200 >>> Resposta.razão 'ok'
cópia de Incluindo variáveis no pedido de get
O URL da solicitação que enviamos acima continha apenas uma variável: Chave API
, e seu valor era "Demo_key"
. Se quisermos passar várias variáveis, em vez de conectá-las ao URL manualmente, podemos fornecer a elas e seus valores associados como pares de valor-chave de um dicionário Python (ou como uma sequência de tuplas de dois elementos); Este dicionário será passado para o urllib.analisar.urlencode
método, que construirá e retornará o string de consulta
. A chamada da API que usamos acima, permita -nos especificar uma variável opcional de "data", para recuperar a imagem associada a um dia específico. Aqui está como poderíamos proceder:
>>> de urllib.Parse importar urlencode >>> query_params = ..."API_KEY": "Demo_Key", ..."Date": "2019-04-11" >>> Query_string = urlencode (query_params) >>> query_string 'api_key = Demo_key & date = 2019-04-11'
cópia de Primeiro, definimos cada variável e seu valor correspondente como pares de valor-chave de um dicionário, do que passamos o referido dicionário como um argumento para o urlencode
função, que retornou uma sequência de consulta formatada. Agora, ao enviar o pedido, tudo o que precisamos fazer é anexá -lo ao URL:
>>> url = "?".Junte -se (["https: // API.NASA.Gov/planetário/apod ", query_string])
Se enviarmos a solicitação usando o URL acima, obtemos uma resposta diferente e uma imagem diferente:
'Date': '2019-04-11', 'Explicação': 'Como é um buraco negro? Para descobrir, o rádio "Telescópios de todo o mundo coordenou observações de" buracos negros com os maiores horizontes de eventos conhecidos no "céu. Sozinho, os buracos negros são apenas negros, mas esses atratores de monstro são conhecidos por estarem cercados por gás brilhante. A "primeira imagem foi lançada ontem e resolveu a área" ao redor do buraco negro no centro do Galaxy M87 em uma escala "abaixo da esperada para o seu evento no evento. Na foto, a "região central escura não é o horizonte de eventos, mas a sombra do buraco negro - a região central da emissão de gás" "escurecida pela gravidade do buraco negro central. O tamanho e "'' Shap of the Shadow são determinados por gás brilhante perto do" Evento Horizon, por fortes deflexões de lentes gravitacionais "e pelo spin do buraco negro. Ao resolver o "Shadow, o telescópio de horizonte de eventos (EHT) reforçou as evidências" de que a gravidade de Einstein funciona mesmo em regiões extremas, e "" deu evidências claras de que o M87 tem um buraco de giro central "de cerca de 6 bilhões de massas solares. O EHT não está pronto -"Observações futuras serão voltadas para uma resolução ainda mais alta", melhor rastreamento da variabilidade e explorando a "vizinhança imediata do buraco negro no centro de nossa" galáxia da Via Láctea.',' hdurl ':' https: // apod.NASA.Gov/apod/imagem/1904/m87bh_eht_2629.JPG ',' Media_type ':' Image ',' Service_version ':' V1 ',' Title ':' Primeira imagem em escala de horizonte de um buraco negro ',' url ':' https: // apod.NASA.gov/apod/imagem/1904/m87bh_eht_960.jpg '
Caso você não tenha notado, o URL da imagem devolvido aponta para a primeira foto recentemente revelada de um buraco negro:
A imagem devolvida pela chamada da API - a primeira imagem de um buraco negro
Enviando um pedido de postagem
Enviando uma solicitação de postagem, com variáveis 'contidas' dentro do corpo da solicitação, usando a biblioteca padrão, requer etapas adicionais. Primeiro de tudo, como fizemos antes, construímos os dados post na forma de um dicionário:
>>> dados = ... "variável1": "value1", ... "variável2": "value2" ...
cópia de Depois que construímos nosso dicionário, queremos usar o urlencode
funcionar como antes e codificar adicionalmente a string resultante em ASCII
:
>>> post_data = urlencode (dados).Encodes ('ASCII')
Finalmente, podemos enviar nossa solicitação, passando os dados como o segundo argumento do urlopen
função. Nesse caso, usaremos https: // httpbin.org/post
como URL de destino (httpbin.Org é um serviço de solicitação e resposta):
>>> com urlopen ("https: // httpbin.org/post ", post_data) como resposta: ... JSON_RESPONSENTE = JSON.carregamento (resposta) >>> pprint (json_Response) 'args': , 'dados': ", 'arquivos': , 'form': 'variable1': 'value1', 'variable2': ' Value2 ',' cabeçalhos ': ' aceit-e-codificação ':' identidade ',' content-comprimento ':' 33 ',' content-type ':' aplicativo/x-www-corm-urlencoded ',' host ' : 'httpbin.org ',' user-agent ':' python-urllib/3.7 ',' json ': nenhum,' origem ':' xx.xx.xx.xx, xx.xx.xx.xx ',' url ':' https: // httpbin.org/post '
cópia de O pedido foi bem -sucedido e o servidor retornou uma resposta JSON, que inclui informações sobre a solicitação que fizemos. Como você pode ver, as variáveis que passamos no corpo da solicitação são relatadas como o valor do 'forma'
chave no corpo de resposta. Lendo o valor do cabeçalhos
chave, também podemos ver que o tipo de conteúdo da solicitação era APLICAÇÃO/X-WWW-FORM-URLENCODED
e o agente do usuário 'Python-urllib/3.7 '
.
Enviando dados JSON no pedido
E se quisermos enviar uma representação JSON de dados com nosso pedido? Primeiro, definimos a estrutura dos dados, do que convertemos para JSON:
>>> pessoa = ... "FirstName": "Luke", ... "LastName": "Skywalker", ... "Título": "Jedi Knight" ...
cópia de Também queremos usar um dicionário para definir cabeçalhos personalizados. Nesse caso, por exemplo, queremos especificar que nosso conteúdo de solicitação é Aplicação/JSON
:
>>> Custom_headers = ... "Tipo de Conteúdo": "Aplicativo/JSON" ...
cópia de Finalmente, em vez de enviar a solicitação diretamente, criamos um Solicitar
Objeto e passamos, em ordem: o URL de destino, os dados de solicitação e os cabeçalhos de solicitação como argumentos de seu construtor:
>>> de urllib.solicitar solicitação de importação >>> req = solicitação ( ... "https: // httpbin.org/post ", ... JSON.Lumps (pessoa).Encodes ('ASCII'), ... Custom_Headers ...)
cópia de Uma coisa importante a perceber é que usamos o JSON.lixões
função que passa o dicionário que contém os dados que queremos ser incluídos na solicitação como seu argumento: esta função é usada para serializar
um objeto em uma corda formatada JSON, que codificamos usando o codificar
método.
Neste ponto, podemos enviar nosso Solicitar
, passando como o primeiro argumento do urlopen
função:
>>> com urlopen (req) como resposta: ... JSON_RESPONSENTE = JSON.Carga (resposta)
cópia de Vamos verificar o conteúdo da resposta:
'args': , 'dados': '"FirstName": "Luke", "LastName": "Skywalker", "Title": "Jedi" Knight "', 'arquivos': , ' formulário ': ,' cabeçalhos ': ' aceitar-codificação ':' identidade ',' content-length ':' 70 ',' content-type ':' Application/json ',' host ':' httpbin.org ',' user-agent ':' python-urllib/3.7 ',' JSON ': ' FirstName ':' Luke ',' LastName ':' Skywalker ',' Title ':' Jedi Knight ',' Origin ':' xx.xx.xx.xx, xx.xx.xx.xx ',' url ':' https: // httpbin.org/post '
Desta vez, podemos ver que o dicionário associado à chave "forma" no corpo de resposta está vazio, e o associado à chave "json" representa os dados que enviamos como json. Como você pode observar, mesmo o parâmetro de cabeçalho personalizado que enviamos foi recebido corretamente.
Enviando uma solicitação com um verbo http diferente de obter ou postar
Ao interagir com as APIs, podemos precisar usar Verbos http
Além de apenas obter ou postar. Para realizar esta tarefa, devemos usar o último parâmetro do Solicitar
construtor de classe e especifique o verbo que queremos usar. O verbo padrão é Get se o dados
parâmetro é Nenhum
, Caso contrário, a postagem é usada. Suponha que queremos enviar um COLOCAR
solicitar:
>>> req = request ( ... "https: // httpbin.org/put ", ... JSON.Lumps (pessoa).Encodes ('ASCII'), ... Custom_Headers, ... método = 'put' ...)
cópia de Baixando um arquivo
Outra operação muito comum que podemos querer executar é baixar algum tipo de arquivo da web. Usando a biblioteca padrão, existem duas maneiras de fazê -lo: usando o urlopen
função, lendo a resposta em pedaços (especialmente se o arquivo para download for grande) e escrevendo -os em um arquivo local "manualmente" ou usando o urlretrieve
A função, que, como declarada na documentação oficial, é considerada parte de uma interface antiga e pode ser preterida no futuro. Vamos ver um exemplo de ambas as estratégias.
Download de um arquivo usando Urlopen
Digamos que queremos baixar o tarball que contém a versão mais recente do código -fonte do kernel Linux. Usando o primeiro método que mencionamos acima, escrevemos:
>>> Último.núcleo.org/pub/linux/kernel/v5.X/Linux-5.0.7.alcatrão.xz ">>> com urlopen (mais last_kernel_tarball) como resposta: ... com open ('mais recente-kernel.alcatrão.xz ',' wb ') como tarball: ... enquanto é verdade: ... Chunk = resposta.Leia (16384) ... Se Chunk: ... Tarball.Escreva (Chunk) ... outro: ... quebrar
cópia de No exemplo acima, usamos primeiro os dois urlopen
função e o abrir
Um dentro com declarações e, portanto, usando o protocolo de gerenciamento de contexto para garantir que os recursos sejam limpos imediatamente após o bloco de código onde são usados. Dentro de a enquanto
loop, em cada iteração, o pedaço
Variável Referências Os bytes lidos da resposta (16384 neste caso - 16 Kibibytes). Se pedaço
não está vazio, escrevemos o conteúdo para o objeto de arquivo ("Tarball"); Se estiver vazio, significa que consumimos todo o conteúdo do corpo de resposta, portanto quebramos o loop.
Uma solução mais concisa envolve o uso do Shutil
biblioteca e o copyfileobj
função, que copia os dados de um objeto semelhante a um arquivo (neste caso "resposta") para outro objeto semelhante a um arquivo (neste caso, "tarball"). O tamanho do buffer pode ser especificado usando o terceiro argumento da função, que, por padrão, é definido como 16384 bytes):
>>> Importar fechado ... com urlopen (mais last_kernel_tarball) como resposta: ... com open ('mais recente-kernel.alcatrão.xz ',' wb ') como tarball: ... Shutil.copyfileobj (resposta, tarball)
cópia de Download de um arquivo usando a função de urlrete
O método alternativo e ainda mais conciso para baixar um arquivo usando a biblioteca padrão é pelo uso do urllib.solicitar.urlretrieve
função. A função leva quatro argumentos, mas apenas os dois primeiros se interessam agora: a primeira é obrigatória e é o URL do recurso a ser baixado; O segundo é o nome usado para armazenar o recurso localmente. Se não for fornecido, o recurso será armazenado como um arquivo temporário em /tmp
. O código se torna:
>>> de urllib.Solicitar importação de importação >>> urlretrieve ("https: // cdn.núcleo.org/pub/linux/kernel/v5.X/Linux-5.0.7.alcatrão.xz ") ('mais recente-kernel.alcatrão.xz ', )
cópia de Muito simples, não é? A função retorna uma tupla que contém o nome usado para armazenar o arquivo (isso é útil quando o recurso é armazenado como arquivo temporário, e o nome é gerado aleatório) e o HttpMessage
objeto que mantém os cabeçalhos da resposta HTTP.
Conclusões
Nesta primeira parte da série de artigos dedicados às solicitações Python e HTTP, vimos como enviar vários tipos de solicitações usando apenas funções de biblioteca padrão e como trabalhar com respostas. Se você tiver dúvidas ou quiser explorar mais as coisas em profundidade, consulte o urllib oficial oficial.Solicite documentação. A próxima parte da série se concentrará na biblioteca de solicitações HTTP do Python.
Tutoriais do Linux relacionados:
- Uma introdução à automação, ferramentas e técnicas do Linux
- Mastering Bash Script Loops
- Loops aninhados em scripts de basquete
- Mint 20: Melhor que o Ubuntu e o Microsoft Windows?
- Coisas para instalar no Ubuntu 20.04
- Como trabalhar com a API de Rest WooCommerce com Python
- Como lançar processos externos com Python e…
- Manipulando a entrada do usuário em scripts bash
- Como carregar, descarregar e listar os módulos do kernel Linux
- Sistema Linux Hung? Como escapar para a linha de comando e…
- « Introdução ao banco de dados se junta ao mariadb e exemplos de junção mysql
- Como executar solicitações HTTP com Python - Parte 2 - A biblioteca de solicitações »