Qual é a maneira mais rápida de obter HTTP HTTP em Python?

613

Qual é a maneira mais rápida de obter HTTP HTTP em Python se eu souber que o conteúdo será uma string? Estou pesquisando na documentação por uma única linha rápida, como:

contents = url.get("http://example.com/foo/bar")

Mas tudo o que consigo encontrar usando o Google é httplibe urllib- e não consigo encontrar um atalho nessas bibliotecas.

O Python 2.5 padrão possui um atalho de alguma forma, como acima, ou devo escrever uma função url_get?

  1. Eu preferiria não capturar a saída do bombardeio para wgetou curl.
Frank Krueger
fonte
Eu encontrei o que precisava aqui: stackoverflow.com/a/385411/1695680
ThorSummoner

Respostas:

872

Python 3:

import urllib.request
contents = urllib.request.urlopen("http://example.com/foo/bar").read()

Python 2:

import urllib2
contents = urllib2.urlopen("http://example.com/foo/bar").read()

Documentação para urllib.requeste read.

Nick Presta
fonte
44
Tudo fica bem limpo? Parece que eu deveria ligar para closevocê read. Isso é necessário?
Frank Krueger
4
É uma boa prática fechá-lo, mas se você estiver procurando por uma linha única, poderá omitir. :-) #
22640 Nick Presta #:
28
O objeto retornado pelo urlopen será excluído (e finalizado, que o fecha) quando ficar fora do escopo. Como o Cpython é contado como referência, você pode contar com isso acontecendo imediatamente após o read. Mas um withbloco seria mais clara e mais seguro para Jython, etc.
sah
8
Não funciona com sites somente HTTPS. requestsfunciona bem
OverCoder
6
Se você estiver usando o Amazon Lambda e precisar obter um URL, a solução 2.x estará disponível e embutida. Parece funcionar com https também. Não é nada mais do que r = urllib2.urlopen("http://blah.com/blah")e então text = r.read(). É sincronização, apenas espera pelo resultado em "texto".
Fattie
412

Você pode usar uma biblioteca chamada solicitações .

import requests
r = requests.get("http://example.com/foo/bar")

Isso é bem fácil. Então você pode fazer assim:

>>> print(r.status_code)
>>> print(r.headers)
>>> print(r.content)
Alex K
fonte
1
@JoeBlow lembre-se de que você deve importar as bibliotecas externas para usá-las
MikeVelazco
1
Quase qualquer biblioteca Python pode ser usada no AWS Lambda. Para Python puro, você só precisa "vender" essa biblioteca (copie para as pastas do módulo em vez de usar pip install). Para bibliotecas não puras, há uma etapa extra - você precisa fazer pip installa lib em uma instância do AWS Linux (a mesma lambda de variante do SO executada) e depois copiar esses arquivos para obter compatibilidade binária com o AWS Linux. As únicas bibliotecas que você nem sempre poderá usar no Lambda são aquelas com apenas distribuições binárias, que felizmente são muito raras.
Chris Johnson
6
@lawphotog isso funciona com python3, mas você precisa pip install requests.
akarilimano
Mesmo a biblioteca padrão urllib2 recomenda pedidos
Asfand Qazi
Em relação ao Lambda: se você deseja usar solicitações nas funções do AWS Lambda. Também existe uma biblioteca de solicitações boto3 pré-instalada. from botocore.vendored import requests Uso response = requests.get('...')
kmjb 21/08/19
29

Se você deseja que a solução com o Activplib2 seja oneliner, considere instanciar um objeto Http anônimo

import httplib2
resp, content = httplib2.Http().request("http://example.com/foo/bar")
to-chomik
fonte
19

Dê uma olhada no httplib2 , que - ao lado de muitos recursos muito úteis - fornece exatamente o que você deseja.

import httplib2

resp, content = httplib2.Http().request("http://example.com/foo/bar")

Onde o conteúdo seria o corpo da resposta (como uma string) e o resp conteria os cabeçalhos de status e resposta.

No entanto, ele não vem incluído em uma instalação python padrão (mas requer apenas python padrão), mas definitivamente vale a pena conferir.

hennr
fonte
6

É simples o suficiente com os poderosos urllib3 biblioteca.

Importe-o assim:

import urllib3

http = urllib3.PoolManager()

E faça uma solicitação como esta:

response = http.request('GET', 'https://example.com')

print(response.data) # Raw data.
print(response.data.decode('utf-8')) # Text.
print(response.status) # Status code.
print(response.headers['Content-Type']) # Content type.

Você também pode adicionar cabeçalhos:

response = http.request('GET', 'https://example.com', headers={
    'key1': 'value1',
    'key2': 'value2'
})

Mais informações podem ser encontradas na documentação do urllib3 .

urllib3é muito mais seguro e fácil de usar do que o módulo urllib.requestou httpmódulos internos e é estável.

Juniorized
fonte
1
ótimo para o fato de que você pode facilmente fornecer um verbo HTTP
Tom
5

A solução do wget para o wget é realmente útil, no entanto, descobri que não imprime o progresso durante o processo de download. É perfeito se você adicionar uma linha após a declaração de impressão no reporthook.

import sys, urllib

def reporthook(a, b, c):
    print "% 3.1f%% of %d bytes\r" % (min(100, float(a * b) / c * 100), c),
    sys.stdout.flush()
for url in sys.argv[1:]:
    i = url.rfind("/")
    file = url[i+1:]
    print url, "->", file
    urllib.urlretrieve(url, file, reporthook)
print
Xuan
fonte
4

Aqui está um script wget no Python:

# From python cookbook, 2nd edition, page 487
import sys, urllib

def reporthook(a, b, c):
    print "% 3.1f%% of %d bytes\r" % (min(100, float(a * b) / c * 100), c),
for url in sys.argv[1:]:
    i = url.rfind("/")
    file = url[i+1:]
    print url, "->", file
    urllib.urlretrieve(url, file, reporthook)
print
caixa
fonte
4

Sem mais importações necessárias, esta solução funciona (para mim) - também com https:

try:
    import urllib2 as urlreq # Python 2.x
except:
    import urllib.request as urlreq # Python 3.x
req = urlreq.Request("http://example.com/foo/bar")
req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36')
urlreq.urlopen(req).read()

Frequentemente, tenho dificuldade em capturar o conteúdo quando não especifico um "User-Agent" nas informações do cabeçalho. Normalmente, os pedidos são cancelados com algo como: urllib2.HTTPError: HTTP Error 403: Forbiddenou urllib.error.HTTPError: HTTP Error 403: Forbidden.

michael_s
fonte
4

Como também enviar cabeçalhos

Python 3:

import urllib.request
contents = urllib.request.urlopen(urllib.request.Request(
    "https://api.github.com/repos/cirosantilli/linux-kernel-module-cheat/releases/latest",
    headers={"Accept" : 'application/vnd.github.full+json"text/html'}
)).read()
print(contents)

Python 2:

import urllib2
contents = urllib2.urlopen(urllib2.Request(
    "https://api.github.com",
    headers={"Accept" : 'application/vnd.github.full+json"text/html'}
)).read()
print(contents)
Ciro Santilli adicionou uma nova foto
fonte
2

Se você estiver trabalhando especificamente com APIs HTTP, também há opções mais convenientes, como Nap .

Por exemplo, veja como obter dicas do Github desde 1º de maio de 2014 :

from nap.url import Url
api = Url('https://api.github.com')

gists = api.join('gists')
response = gists.get(params={'since': '2014-05-01T00:00:00Z'})
print(response.json())

Mais exemplos: https://github.com/kimmobrunfeldt/nap#examples

Kimmo
fonte
2

Excelentes soluções Xuan, Theller.

Para que ele funcione com o python 3, faça as seguintes alterações

import sys, urllib.request

def reporthook(a, b, c):
    print ("% 3.1f%% of %d bytes\r" % (min(100, float(a * b) / c * 100), c))
    sys.stdout.flush()
for url in sys.argv[1:]:
    i = url.rfind("/")
    file = url[i+1:]
    print (url, "->", file)
    urllib.request.urlretrieve(url, file, reporthook)
print

Além disso, o URL digitado deve ser precedido por um "http: //", caso contrário, ele retornará um erro de tipo de URL desconhecido.

Akshar
fonte
1

Para python >= 3.6, você pode usar o dload :

import dload
t = dload.text(url)

Para json:

j = dload.json(url)

Instalar:
pip install dload

CONvid19
fonte
0

Na verdade, em python, podemos ler URLs como arquivos, aqui está um exemplo para ler json da API.

import json

from urllib.request import urlopen

with urlopen(url) as f:

resp = json.load(f)

return resp['some_key']
Katrych Taras
fonte
Apesar de agradecermos sua resposta, seria melhor se ela fornecesse valor adicional além das outras respostas. Nesse caso, sua resposta não fornece valor adicional, pois outro usuário já postou essa solução. Se uma resposta anterior foi útil para você, vote em vez de repetir a mesma informação.
Toby Speight
0

Se você deseja uma API de nível inferior:

import http.client

conn = http.client.HTTPSConnection('example.com')
conn.request('GET', '/')

resp = conn.getresponse()
content = resp.read()

conn.close()

text = content.decode('utf-8')

print(text)
Juniorized
fonte