Python 2でHEAD HTTPリクエストを送信するにはどうすればよいですか?


114

ここで私がやろうとしているのは、指定されたURLのヘッダーを取得して、MIMEタイプを判別できるようにすることです。がhttp://somedomain/foo/HTMLドキュメントまたはJPEG画像などを返すかどうかを確認できるようにしたいと思います。したがって、コンテンツをダウンロードせずにMIMEタイプを読み取ることができるように、HEADリクエストを送信する方法を理解する必要があります。これを行う簡単な方法を知っている人はいますか?

回答:


104

編集する:この回答は機能しますが、現在は、以下の他の回答で述べられているように、リクエストライブラリを使用する必要があります。


使用する httplibをます

>>> 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)特定のヘッダーを取得するもあります。


2
この応答は回答済みとしてマークされていますが、リクエスト libを確認する必要があります。少し下にあるダリウスの反応を見てください。
Bahadir Cambel 2011

これは本当にすばらしいですが、要求のホストとパスに個別の値を指定する必要があります。urlparse手元にあると便利です。これは、ランクの低い応答で示されます。
Tomasz Gandor 2013年

7
Python 3に関する注意。httplibはに名前が変更されましたhttp.client
Santosh Kumar

2
残念ながら、requestsデフォルトではPythonに同梱されていません。
ルーク

@rookもあなたのプログラムではありません:)
Eevee

109

urllib2を使用して、HEADリクエストを実行できます。これは、URLをホスト名とパスに分割する代わりにurllib2がURLを解析するため、httplibを使用するよりも少し優れています。

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

ヘッダーは以前と同様にresponse.info()を介して利用できます。興味深いことに、リダイレクトされたURLを見つけることができます。

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

1
response.info().__ str __()は、取得した結果で何かを実行したい場合に備えて、ヘッダーの文字列形式を返します。
シェーン

6
python 2.7.1(ubuntu natty)でこれを試すことを除いて、リダイレクトがある場合、宛先ではなくHEADではなくGETを実行します...
eichin

1
これが、httplib.HTTPConnectionリダイレクトを自動的に処理しないの利点です。
Ehtesh Choudhury、2011

しかしdosheaの答えで。タイムアウトを設定するには?不正なURL、つまり、存続しなくなったURLを処理する方法。
fanchyna 2013

65

義務的Requestsな方法:

import requests

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

36

Requestsライブラリにも言及する必要があると思います。


5
この答えはもっと注目に値します。問題を簡単にするかなり良いライブラリのように見えます。
Nick Retallack、2011年

3
同意することは非常に簡単でした:{code}インポートリクエストr = requests.head( ' github.com'){code}
Luis R.

@LuisR .:リダイレクトがある場合は、GET / POST / PUT / DELETEにも従います。
jfs

@Nick Retallack:リダイレクトを無効にする簡単な方法はありません。allow_redirectsPOST / PUT / DELETEリダイレクトのみを無効にできます。例:ヘッドリクエストリダイレクトなし
jfs

@JFSebastianあなたの例へのリンクは壊れているようです。次のリダイレクトの問題について詳しく教えてください。
Piotr Dobrogost 2012

17

ただ:

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

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

編集:httplib2:Dがあることに気づきました

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'
...

リンクテキスト


get_methodをにバインドするのではなく、バインドされていない関数として残しているという点で少し厄介ですrequest。(Viz、動作しますが、スタイルが悪く、使用selfしたい場合-難しいです。)
Chris Morgan

4
このソリューションの長所と短所についてもう少し詳しく説明してもらえますか?ご覧のとおり、私はPythonの専門家ではありません。そのため、状況が悪化する可能性があることを知っておくと役に立ちます;)懸念は、実装の変更に応じて機能するかどうかにかかわらず、ハッキングであるということです。
パヴェルPrażak

このコードのこの2番目のバージョンは、403 ForbiddenのURLで私のために機能した唯一のものです。他の人は例外を投げていました。
duality_ 2013

10

完全を期すために、httplibを使用して受け入れられた回答と同等のPython3回答を得るます。

これは、ライブラリがhttplibではなく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

以前のドル記号は何importですか?+1は、入力側でURLを処理するときに、urlparseと一緒にhttplibの快適さurllib2を提供します。
Tomasz Gandor 2013年

1

余談ですが、httplib(少なくとも2.5.2)を使用している場合、HEADリクエストの応答を読み取ろうとすると(readlineで)ブロックされ、その後失敗します。応答でreadを発行しない場合、接続で別の要求を送信することができないため、新しい要求を開く必要があります。または、リクエスト間の長い遅延を受け入れます。


1

httplibはurllib2よりもわずかに速いことがわかりました。2つのプログラムの時間を計った-1つはhttplibを使用し、もう1つはurllib2を使用して、10,000のURLにHEADリクエストを送信した。httplibは数分高速でした。 httplibの合計統計は次のとおりです。実際の6m21.334sユーザー0m2.124s sys 0m16.372s

そしてurllib2の合計統計は次のとおりです:実際の9m1.380sユーザー0m16.666s sys 0m28.565s

他に誰かがこれについて意見を持っていますか?


入力?問題はIOバウンドであり、ブロッキングライブラリを使用しています。より良いパフォーマンスが必要な場合は、イベントレットまたはツイストに切り替えます。あなたが言及するurllib2の制限はCPUに依存しています。
Devin Jeanpierre

3
urllib2はリダイレクトを追跡するため、一部のURLがリダイレクトする場合、それがおそらく違いの理由になります。そして、httplibはより低レベルであり、たとえばurllib2はURLを解析します。
マリアン

1
urllib2は、httplibの上にある抽象化の薄いレイヤーにすぎません。URLが非常に高速なLAN上にない限り、CPUにバインドされているとしたら、私は非常に驚きます。一部のURLがリダイレクトであった可能性はありますか?urllib2はリダイレクトに従いますが、httplibはそうしません。もう1つの可能性は、2つの実行間でネットワーク条件(この実験で明示的に制御できないもの)が変動したことです。あなたはこのlikelyhood減らすために、それぞれの少なくとも3つのインターリーブの実行を行う必要があります
ジョン・ラRooy

0

さらに別のアプローチ(Pawelの回答と同様):

import urllib2
import types

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

インスタンスレベルで無制限のメソッドを使用しないようにするためです。


-4

おそらくもっと簡単です:urllibまたはurllib2を使用してください。

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

f.info()は辞書のようなオブジェクトなので、f.info()['content-type']などを実行できます。

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

ドキュメントでは、httplibは通常直接使用されないことに注意してください。


14
ただし、urllibはGETを実行し、問題はHEADの実行についてです。たぶん、ポスターは高価なドキュメントを取得したくないでしょう。
フィリップF
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.