Python 2'de bir HEAD HTTP isteğini nasıl gönderirsiniz?


114

Burada yapmaya çalıştığım şey, belirli bir URL'nin başlıklarını almak, böylece MIME türünü belirleyebilirim. http://somedomain/foo/Örneğin, bir HTML belgesi mi yoksa bir JPEG resmi mi döndüreceğini görmek istiyorum . Bu nedenle, içeriği indirmek zorunda kalmadan MIME türünü okuyabilmem için bir HEAD isteğinin nasıl gönderileceğini bulmam gerekiyor. Bunu yapmanın kolay bir yolunu bilen var mı?

Yanıtlar:


104

edit : Bu cevap işe yarıyor, ancak günümüzde sadece aşağıdaki diğer cevaplarda belirtildiği gibi istek kitaplığını kullanmalısınız .


Httplib kullanın .

>>> import httplib
>>> conn = httplib.HTTPConnection("www.google.com")
>>> conn.request("HEAD", "/index.html")
>>> res = conn.getresponse()
>>> print res.status, res.reason
200 OK
>>> print res.getheaders()
[('content-length', '0'), ('expires', '-1'), ('server', 'gws'), ('cache-control', 'private, max-age=0'), ('date', 'Sat, 20 Sep 2008 06:43:36 GMT'), ('content-type', 'text/html; charset=ISO-8859-1')]

getheader(name)Belirli bir başlık almak için bir de var .


2
bu yanıt yanıtlandı olarak işaretlendi, ancak istek kütüphanesine bakılmalıdır . Dalius'un biraz aşağıda olan yanıtına bakın.
Bahadır Cambel

Bu gerçekten güzel, ancak ana bilgisayar ve isteğin yolu için ayrı değerlere sahip olmanızı gerektiriyor. urlparseBazı düşük dereceli yanıtlarla gösterilen, elinizin altında olması yararlıdır .
Tomasz Gandor

7
Python 3 için not; httplibolarak yeniden adlandırıldı http.client.
Santosh Kumar

2
Ne yazık ki, requestsvarsayılan olarak Python ile birlikte gönderilmez.
2013

@rook sizin programınız değil :)
Eevee

109

urllib2 bir HEAD isteği gerçekleştirmek için kullanılabilir. Urllib2, URL'yi ana bilgisayar adına ve yoluna bölmenizi gerektirmek yerine sizin için URL'yi ayrıştırdığından, httplib kullanmaktan biraz daha iyidir.

>>> import urllib2
>>> class HeadRequest(urllib2.Request):
...     def get_method(self):
...         return "HEAD"
... 
>>> response = urllib2.urlopen(HeadRequest("http://google.com/index.html"))

Başlıklar daha önce olduğu gibi response.info () aracılığıyla kullanılabilir. İlginç bir şekilde, yönlendirildiğiniz URL'yi bulabilirsiniz:

>>> print response.geturl()
http://www.google.com.au/index.html

1
response.info () .__ str __ (), elde ettiğiniz sonuçla bir şeyler yapmak istemeniz durumunda, başlığın dize biçimini döndürecektir.
Shane

6
bunu python 2.7.1 (ubuntu natty) ile denemenin dışında, bir yönlendirme varsa, hedefte bir HEAD değil, bir GET yapar ...
eichin

1
httplib.HTTPConnectionYönlendirmeleri otomatik olarak işlemeyen, avantajı budur .
Ehtesh Choudhury

ama doshea'nın cevabıyla. zaman aşımı nasıl ayarlanır? Kötü URL'ler, yani artık canlı olmayan URL'ler nasıl işlenir.
fanchyna

65

Zorunlu Requestsyol:

import requests

resp = requests.head("http://www.google.com")
print resp.status_code, resp.text, resp.headers

36

İstekler kütüphanesinin de belirtilmesi gerektiğine inanıyorum .


5
Bu cevap daha fazla ilgiyi hak ediyor. Sorunu önemsiz kılan oldukça iyi bir kitaplığa benziyor.
Nick Retallack

3
Kabul ediyorum: İstekte bulunmak çok basitti: {kod} içe aktarma istekleri r = istekler.head (' github.com' ) {kod}
Luis R.

@LuisR .: bir yönlendirme varsa GET / POST / PUT / DELETE'i de takip eder.
jfs

@Nick Retallack: Yeniden yönlendirmeleri devre dışı bırakmanın kolay bir yolu yoktur. allow_redirectsyalnızca POST / PUT / DELETE yönlendirmelerini devre dışı bırakabilir. Örnek: baş isteği yönlendirme yok
jfs

@JFSebastian Örneğinizin bağlantısı kesilmiş görünüyor. Aşağıdaki yeniden yönlendirmelerle ilgili sorunu ayrıntılarıyla açıklayabilir misiniz?
Piotr Dobrogost

17

Sadece:

import urllib2
request = urllib2.Request('http://localhost:8080')
request.get_method = lambda : 'HEAD'

response = urllib2.urlopen(request)
response.info().gettype()

Düzenleme: httplib2: D olduğunu fark ettim.

import httplib2
h = httplib2.Http()
resp = h.request("http://www.google.com", 'HEAD')
assert resp[0]['status'] == 200
assert resp[0]['content-type'] == 'text/html'
...

bağlantı metni


Get_method'u bağlanmak yerine bağlı olmayan bir işlev olarak bırakmanız nedeniyle biraz kötü request. (Viz, işe yarayacak ama kötü bir tarz ve selfiçinde kullanmak istiyorsanız - zor.)
Chris Morgan

4
Bu çözümün artıları ve eksileri hakkında biraz daha ayrıntı verebilir misiniz? Gördüğünüz gibi bir Python uzmanı değilim, bu yüzden ne zaman kötüye gidebileceğini bilmek faydalı olabilir;) Anladığım kadarıyla, anladığım kadarıyla, uygulama değişikliğine bağlı olarak işe yarayabilecek veya çalışmayabilecek bir bilgisayar korsanlığı mı?
Paweł Prażak

Bu koddaki bu ikinci sürüm, 403 Yasaklı bir URL için benim için çalışan tek sürümdür. Diğerleri bir istisna yapıyordu.
duality_

10

Tamlık için, httplib kullanarak kabul edilen yanıta eşdeğer bir Python3 yanıtına sahip olmak .

Temelde kütüphane çağrılmaz sadece aynı kod httplib artık ama http.client

from http.client import HTTPConnection

conn = HTTPConnection('www.google.com')
conn.request('HEAD', '/index.html')
res = conn.getresponse()

print(res.status, res.reason)

2
import httplib
import urlparse

def unshorten_url(url):
    parsed = urlparse.urlparse(url)
    h = httplib.HTTPConnection(parsed.netloc)
    h.request('HEAD', parsed.path)
    response = h.getresponse()
    if response.status/100 == 3 and response.getheader('Location'):
        return response.getheader('Location')
    else:
        return url

Önceki dolar işaretleri nelerdi import? İçin +1 urlparse- giriş tarafındaki URL'lerle uğraşırken httplibrahatlık sağlar urllib2.
Tomasz Gandor

1

Bir kenara, httplib kullanılırken (en azından 2.5.2'de), bir HEAD isteğinin yanıtını okumaya çalışmak (okuma hattında) engellenecek ve ardından başarısız olacaktır. Yanıtı okumayı engellemezseniz, bağlantıda başka bir istek gönderemezsiniz, yeni bir tane açmanız gerekecektir. Veya istekler arasında uzun bir gecikmeyi kabul edin.


1

Httplib'in urllib2'den biraz daha hızlı olduğunu buldum. Biri httplib, diğeri urllib2 kullanarak 10.000 URL'ye HEAD istekleri gönderen iki programı zamanladım. Httplib birkaç dakika daha hızlıydı. httplib'in toplam istatistikleri şunlardı: gerçek 6a21.334s kullanıcı 0m2.124s sys 0m16.372s

Ve urllib2 'ın toplam istatistik vardı: Gerçek 9m1.380s kullanıcı 0m16.666s sys 0m28.565s

Bu konuda başka bir girdisi olan var mı?


Giriş? Sorun GÇ'ye bağlıdır ve engelleme kitaplıkları kullanıyorsunuz. Daha iyi performans istiyorsanız, etkinlik grubuna geçin veya bükün. Bahsettiğiniz urllib2'nin sınırlamaları CPU'ya bağlıdır.
Devin Jeanpierre

3
urllib2 yeniden yönlendirmeleri izler, bu nedenle URL'lerinizden bazıları yeniden yönlendiriyorsa, farkın nedeni büyük olasılıkla bu olacaktır. Ve httplib daha düşük seviyelidir, örneğin urllib2 url'yi ayrıştırır.
Marian

1
urllib2, httplib üzerinde ince bir soyutlama katmanıdır, url'ler çok hızlı bir LAN'da değilse cpu'ya bağlı olsaydınız çok şaşırırdım. Bazı url'lerin yönlendirilmiş olması mümkün mü? urllib2 yeniden yönlendirmeleri takip ederken, httplib bunu yapmaz. Diğer olasılık, ağ koşullarının (bu deneyde açık kontrolünüz olmayan herhangi bir şey) 2 çalıştırma arasında dalgalanmasıdır. Bu olasılığı azaltmak için en az 3 aralıklı çalıştırma yapmalısınız
John La Rooy

0

Ve yine başka bir yaklaşım (Pawel cevabına benzer):

import urllib2
import types

request = urllib2.Request('http://localhost:8080')
request.get_method = types.MethodType(lambda self: 'HEAD', request, request.__class__)

Sadece örnek düzeyinde sınırsız yöntemlerden kaçınmak için.


-4

Muhtemelen daha kolay: urllib veya urllib2 kullanın.

>>> import urllib
>>> f = urllib.urlopen('http://google.com')
>>> f.info().gettype()
'text/html'

f.info () sözlüğe benzer bir nesnedir, dolayısıyla f.info () ['içerik türü'] vb. işlemleri yapabilirsiniz.

http://docs.python.org/library/urllib.html
http://docs.python.org/library/urllib2.html
http://docs.python.org/library/httplib.html

Dokümanlar, httplib'in normalde doğrudan kullanılmadığını not eder.


14
Bununla birlikte, urllib bir GET yapacak ve soru bir HEAD gerçekleştirmekle ilgili. Belki de poster pahalı bir belgeyi geri almak istemiyordur.
Philippe F
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.