Apa cara tercepat untuk mendapatkan HTTP dengan Python?


613

Apa cara tercepat untuk mendapatkan HTTP dengan Python jika saya tahu konten akan menjadi string? Saya mencari dokumentasi untuk satu-liner cepat seperti:

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

Tapi yang bisa saya temukan menggunakan Google adalah httplibdan urllib- dan saya tidak dapat menemukan jalan pintas di perpustakaan itu.

Apakah standar Python 2.5 memiliki jalan pintas dalam beberapa bentuk seperti di atas, atau haruskah saya menulis fungsi url_get?

  1. Saya lebih suka untuk tidak menangkap output dari penembakan ke wgetatau curl.

Saya menemukan apa yang saya butuhkan di sini: stackoverflow.com/a/385411/1695680
ThorSummoner

Jawaban:


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

Dokumentasi untuk urllib.requestdan read.


44
Apakah semuanya dibersihkan dengan baik? Sepertinya saya harus memanggil closeAnda read. Apakah itu perlu?
Frank Krueger

4
Ini adalah praktik yang baik untuk menutupnya, tetapi jika Anda mencari one-liner cepat, Anda bisa menghilangkannya. :-)
Nick Presta

28
Objek yang dikembalikan oleh urlopen akan dihapus (dan diselesaikan, yang menutupnya) ketika jatuh keluar dari ruang lingkup. Karena Cpython dihitung referensi, Anda dapat mengandalkan itu terjadi segera setelah read. Tapi satu withblok akan lebih jelas dan lebih aman untuk Jython, dll.
sah

8
Itu tidak berfungsi dengan situs web HTTPS saja. requestsberfungsi dengan baik
OverCoder

6
Jika Anda menggunakan Amazon Lambda dan perlu mendapatkan URL, solusi 2.x tersedia dan terintegrasi. Tampaknya berfungsi dengan https juga. Tidak lebih dari r = urllib2.urlopen("http://blah.com/blah")dan kemudian text = r.read(). Sinkronisasi, hanya menunggu hasil dalam "teks".
Fattie

412

Anda bisa menggunakan perpustakaan yang disebut permintaan .

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

Ini cukup mudah. Maka Anda bisa melakukan ini:

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

1
@ JoBlow ingat bahwa Anda harus mengimpor perpustakaan eksternal untuk menggunakannya
MikeVelazco

1
Hampir semua perpustakaan Python dapat digunakan di AWS Lambda. Untuk Python murni, Anda hanya perlu "vendor" perpustakaan itu (salin ke folder modul Anda daripada menggunakan pip install). Untuk pustaka non-murni, ada langkah tambahan - Anda perlu pip installlib ke instance AWS Linux (varian OS yang sama lambda berjalan di bawah), kemudian salin file-file itu sebagai gantinya sehingga Anda akan memiliki kompatibilitas biner dengan AWS Linux. Satu-satunya perpustakaan yang Anda tidak selalu dapat menggunakan di Lambda adalah mereka dengan distribusi biner saja, yang untungnya cukup langka.
Chris Johnson

6
@ lawphotog ini TIDAK bekerja dengan python3, tetapi Anda harus melakukannya pip install requests.
akarilimano

Bahkan perpustakaan standar urllib2 merekomendasikan permintaan
Asfand Qazi

Mengenai Lambda: jika Anda ingin menggunakan permintaan dalam fungsi AWS Lambda. Ada juga pustaka permintaan boto3 yang sudah diinstal sebelumnya. from botocore.vendored import requests Penggunaan response = requests.get('...')
kmjb

29

Jika Anda ingin solusi dengan httplib2 menjadi oneliner pertimbangkan instantiating objek Http anonim

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

19

Lihat httplib2 , yang - di sebelah banyak fitur yang sangat berguna - memberikan apa yang Anda inginkan.

import httplib2

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

Di mana konten akan menjadi badan respons (sebagai string), dan resp akan berisi header status dan respons.

Itu tidak disertakan dengan instalasi python standar (tetapi hanya membutuhkan python standar), tapi itu pasti patut dicoba.


6

Cukup sederhana dengan urllib3perpustakaan yang kuat .

Impor seperti ini:

import urllib3

http = urllib3.PoolManager()

Dan buat permintaan seperti ini:

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.

Anda juga dapat menambahkan tajuk:

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

Info lebih lanjut dapat ditemukan di dokumentasi urllib3 .

urllib3jauh lebih aman dan lebih mudah digunakan daripada builtin urllib.requestatau httpmodul dan stabil.


1
bagus untuk fakta Anda dapat dengan mudah memberikan kata kerja HTTP
Tom

5

solusi theller untuk wget benar-benar berguna, namun, saya menemukan itu tidak mencetak kemajuan selama proses pengunduhan. Ini sempurna jika Anda menambahkan satu baris setelah pernyataan cetak di publikasi ulang.

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

Berikut ini skrip wget dalam 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

Tanpa impor lebih lanjut yang diperlukan solusi ini bekerja (untuk saya) - juga dengan 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()

Saya sering mengalami kesulitan mengambil konten ketika tidak menentukan "User-Agent" di informasi header. Maka biasanya permintaan dibatalkan dengan sesuatu seperti: urllib2.HTTPError: HTTP Error 403: Forbiddenatau urllib.error.HTTPError: HTTP Error 403: Forbidden.


4

Cara juga mengirim tajuk

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

Jika Anda bekerja dengan API HTTP secara khusus, ada juga pilihan yang lebih nyaman seperti Nap .

Misalnya, inilah cara mendapatkan intisari dari Github sejak 1 Mei 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())

Contoh lainnya: https://github.com/kimmobrunfeldt/nap#examples


2

Solusi terbaik Xuan, Theller.

Agar bisa bekerja dengan python 3 buat perubahan berikut

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

Juga, URL yang Anda masukkan harus didahului dengan "http: //", jika tidak maka akan muncul kesalahan jenis url yang tidak dikenal.


1

Untuk python >= 3.6, Anda dapat menggunakan dload :

import dload
t = dload.text(url)

Untuk json:

j = dload.json(url)

Install:
pip install dload


0

Sebenarnya dengan python kita dapat membaca dari url seperti dari file, berikut adalah contoh untuk membaca json dari API.

import json

from urllib.request import urlopen

with urlopen(url) as f:

resp = json.load(f)

return resp['some_key']

Meskipun kami berterima kasih atas jawaban Anda, akan lebih baik jika memberikan nilai tambahan di atas jawaban lainnya. Dalam hal ini, jawaban Anda tidak memberikan nilai tambahan, karena pengguna lain sudah memposting solusi itu. Jika jawaban sebelumnya bermanfaat bagi Anda, Anda harus memilihnya alih-alih mengulangi informasi yang sama.
Toby Speight

0

Jika Anda ingin API tingkat lebih rendah:

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)
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.