Qual è il modo più rapido per ottenere HTTP in Python?


613

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

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

Ma tutto quello che posso trovare usando Google sono httplibe urllib- e non riesco a trovare un collegamento in quelle librerie.

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

  1. Preferirei non catturare l'output del bombardamento verso wgeto curl.

Ho trovato quello che mi serviva qui: stackoverflow.com/a/385411/1695680
ThorSummoner

Risposte:


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()

Documentazione per urllib.requeste read.


44
Tutto viene pulito bene? Sembra che dovrei chiamare closedopo il tuo read. È necessario?
Frank Krueger,

4
È buona pratica chiuderlo, ma se stai cercando un one-liner veloce, potresti ometterlo. :-)
Nick Presta

28
L'oggetto restituito da urlopen verrà eliminato (e finalizzato, che lo chiude) quando non rientra nell'ambito. Poiché Cpython viene conteggiato come riferimento, puoi fare affidamento su ciò che accade immediatamente dopo il read. Ma un withblocco sarebbe più chiaro e più sicuro per Jython, ecc.
Sah,

8
Non funziona con i siti Web solo HTTPS. requestsfunziona benissimo
OverCoder il

6
Se stai utilizzando Amazon Lambda e hai bisogno di ottenere un URL, la soluzione 2.x è disponibile e integrata. Sembra funzionare anche con HTTPS. Non è altro che di r = urllib2.urlopen("http://blah.com/blah")allora text = r.read(). È sincronizzazione, aspetta solo il risultato in "testo".
Fattie,

412

È possibile utilizzare una libreria denominata richieste .

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

Questo è abbastanza facile Quindi puoi fare così:

>>> print(r.status_code)
>>> print(r.headers)
>>> print(r.content)

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

1
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 piuttosto che usare pip install). Per le librerie non pure, c'è un ulteriore passaggio: è necessario eseguire pip installla lib su un'istanza di AWS Linux (la stessa variante del sistema operativo lambdas funziona sotto), quindi copiare quei file invece in modo da avere la 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 per fortuna sono piuttosto rare.
Chris Johnson,

6
@lawphotog funziona con python3, ma devi farlo pip install requests.
akarilimano,

Anche la libreria standard urllib2 raccomanda richieste
Asfand Qazi

Per quanto riguarda Lambda: se si desidera utilizzare le richieste nelle funzioni AWS Lambda. Esiste anche una libreria di richieste boto3 preinstallata. from botocore.vendored import requests Utilizzo response = requests.get('...')
kmjb

29

Se vuoi che la soluzione con httplib2 sia oneliner, considera l'istanza di un oggetto Http anonimo

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

19

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

import httplib2

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

Dove il contenuto sarebbe il corpo della risposta (come una stringa) e resp conterrà lo stato e le intestazioni della risposta.

Tuttavia, non viene incluso con un'installazione standard di Python (ma richiede solo Python standard), ma vale sicuramente la pena di provarlo.


6

È abbastanza semplice con la potente urllib3libreria.

Importalo in questo modo:

import urllib3

http = urllib3.PoolManager()

E fai una richiesta come questa:

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.

Puoi anche aggiungere intestazioni:

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

Ulteriori informazioni sono disponibili nella documentazione di urllib3 .

urllib3è molto più sicuro e più facile da usare rispetto al modulo integrato urllib.requesto ai httpmoduli ed è stabile.


1
ottimo per il fatto che puoi facilmente fornire un verbo HTTP
Tom

5

la soluzione di theller per wget è davvero utile, tuttavia, ho scoperto che non stampa i progressi durante il processo di download. È perfetto se aggiungi una riga dopo l'istruzione print 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

4

Ecco uno script wget in 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

4

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à ad afferrare il contenuto quando non si specifica un "User-Agent" nelle informazioni dell'intestazione. Quindi di solito le richieste vengono cancellate con qualcosa del tipo: urllib2.HTTPError: HTTP Error 403: Forbiddeno urllib.error.HTTPError: HTTP Error 403: Forbidden.


4

Come inviare anche intestazioni

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)

2

Se si lavora specificamente con API HTTP, esistono anche opzioni più convenienti come Nap .

Ad esempio, ecco come ottenere informazioni 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


2

Soluzioni eccellenti Xuan, Theller.

Affinché funzioni con Python 3 apporta 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 di tipo url sconosciuto.


1

Per python >= 3.6, puoi usare dload :

import dload
t = dload.text(url)

Per json:

j = dload.json(url)

Installare:
pip install dload


0

In realtà in Python possiamo leggere dagli URL come dai file, ecco un esempio per leggere json dall'API.

import json

from urllib.request import urlopen

with urlopen(url) as f:

resp = json.load(f)

return resp['some_key']

Sebbene ti ringraziamo per la tua risposta, sarebbe meglio se fornisse un valore aggiuntivo rispetto alle altre risposte. In questo caso, la tua risposta non fornisce un valore aggiuntivo, poiché un altro utente ha già pubblicato quella soluzione. Se una risposta precedente ti è stata utile, dovresti votarla invece di ripetere le stesse informazioni.
Toby Speight,

0

Se desideri un'API di livello inferiore:

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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.