2009-03-14 13 views
397

Qual è il modo più veloce per HTTP GET in Python se so che il contenuto sarà una stringa? Sto cercando la documentazione per un rapido uno-liner come:Qual è il modo più rapido per HTTP GET in Python?

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

Ma tutto quello che posso trovare con Google sono httplib e urllib - e non riesco a trovare una scorciatoia in quelle librerie.

Il Python 2.5 standard ha una scorciatoia in qualche modo come sopra, o dovrei scrivere una funzione url_get?

  1. preferirei non per catturare l'uscita di sborsare per wget o curl.
+20

Le one-liner non sono necessariamente più veloci. Non feticizzare il codice golf. Devi misurare la velocità; non linee di codice. –

+69

uhm, no, ho cercato su Google perché dovevo aggiungere una riga a un esperimento che sto scrivendo; non il prodotto finito. Il tempo della CPU è molto, molto più economico del tempo del programmatore! – Phlip

+0

Ho trovato ciò di cui avevo bisogno qui: http://stackoverflow.com/a/385411/1695680 – ThorSummoner

risposta

594

Python 2.x:

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

Python 3.x:

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

documentazione per urllib.request e read.

Come è?

+25

Tutto viene pulito bene? Sembra che dovrei chiamare 'close' dopo aver 'letto'. È necessario? –

+4

È buona norma chiuderlo, ma se stai cercando un quick one-liner, potresti ometterlo. :-) –

+0

Per quello che vale, la stessa cosa funziona con urllib al posto di urllib2 (almeno per la maggior parte degli URL). –

17

Dai un'occhiata allo httplib2, che - accanto a molte funzioni molto utili - fornisce esattamente ciò che desideri.

import httplib2 

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

Dove il contenuto sarebbe il corpo di risposta (come una stringa), e resp conterrebbe le intestazioni di stato e di risposta.

Non è incluso in una installazione standard di Python (ma richiede solo Python standard), ma vale sicuramente la pena di provarlo.

27

Se si desidera una soluzione con httplib2 per essere oneliner considerare instatntinating oggetto HTTP anonime

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

Ecco uno script wget in Python: soluzione

# 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 
6

di theller per wget è veramente utile, tuttavia, ho trovato che non stampa i progressi durante il processo di download. È perfetto se aggiungi una riga dopo la dichiarazione di stampa in 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 
267

È possibile utilizzare una libreria denominata requests.

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

Questo è abbastanza facile. Poi si può fare in questo modo:

>>> print r.status_code 
>>> print r.headers 
>>> print r.content 
+2

Ho notato che non è disponibile in Amazon Lambda ... – Fattie

+0

@JoeBlow ricorda che è necessario importare le librerie esterne per poterle utilizzare – MikeVelazco

+0

Quasi tutte le librerie Python possono essere utilizzate in AWS Lambda. Per puro Python, devi solo "vendor" quella libreria (copia nelle cartelle del tuo modulo invece di usare 'pip install'). Per le librerie non pure, c'è un passo in più - devi 'pipinstallare 'il lib su un'istanza di AWS Linux (la stessa variante del sistema operativo lambdas eseguito sotto), quindi copiare questi file invece avrai una compatibilità binaria con AWS Linux. Le uniche librerie che non sarai sempre in grado di utilizzare in Lambda sono solo quelle con distribuzioni binarie, che sono per fortuna piuttosto rare. –

2

Se si sta lavorando con le API HTTP specifico, ci sono anche scelte più convenienti, come Nap.

Ad esempio, ecco come ottenere GIST da Github dal 1 maggio 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()) 

Altri esempi: https://github.com/kimmobrunfeldt/nap#examples

3

soluzioni eccellenti Xuan, Theller.

Per farlo funzionare con Python 3 apportare le seguenti modifiche

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 

Inoltre, l'URL inserito deve essere preceduto da un "http: //", altrimenti restituisce un errore sconosciuto tipo di URL.

1

Senza ulteriori importazioni necessarie questa soluzione funziona (per me) - anche con 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() 

spesso ho difficoltà a catturare il contenuto quando non specificare un "User-Agent" nelle informazioni di intestazione. Di solito le richieste vengono cancellate con qualcosa come: urllib2.HTTPError: HTTP Error 403: Forbidden o urllib.error.HTTPError: HTTP Error 403: Forbidden.

Problemi correlati