urllib2
urlopen
呼び出しが行われたときにページ全体を取得しますか?
ページを取得せずにHTTP応答ヘッダーを読みたいだけです。 urllib2
はHTTP接続を開き、その後実際のHTMLページを取得します...またはurlopen
呼び出しでページのバッファリングを開始しますか?
import urllib2
myurl = 'http://www.kidsidebyside.org/2009/05/come-and-draw-the-circle-of-unity-with-us/'
page = urllib2.urlopen(myurl) // open connection, get headers
html = page.readlines() // stream page
response.info()
メソッドを使用してヘッダーを取得します。
rllib2 docs から:
urllib2.urlopen(url [、data] [、timeout])
...
この関数は、2つの追加メソッドを持つファイルのようなオブジェクトを返します。
- geturl()—取得されたリソースのURLを返します。一般的に、リダイレクトが追跡されたかどうかを判断するために使用されます
- info()—ヘッダーなどのページのメタ情報をhttplib.HTTPMessageインスタンスの形式で返します(HTTPヘッダーのクイックリファレンスを参照)
したがって、あなたの例では、探しているものについてresponse.info().headers
の結果をステップスルーしてみてください。
Httplib.HTTPMessageを使用する場合の主な注意事項は python issue 477 に記載されています。
通常のGETリクエストの代わりにHEADリクエストを送信します。同様の 質問 からコピーされた)以下はまさにそれを行います。
>>> 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')]
実際、urllib2はHTTP HEADリクエストを行うことができます。
上記の@retoがリンクしている question は、HEADリクエストを行うためにurllib2を取得する方法を示しています。
これが私の見解です。
import urllib2
# Derive from Request class and override get_method to allow a HEAD request.
class HeadRequest(urllib2.Request):
def get_method(self):
return "HEAD"
myurl = 'http://bit.ly/doFeT'
request = HeadRequest(myurl)
try:
response = urllib2.urlopen(request)
response_headers = response.info()
# This will just display all the dictionary key-value pairs. Replace this
# line with something useful.
response_headers.dict
except urllib2.HTTPError, e:
# Prints the HTTP Status code of the response but only if there was a
# problem.
print ("Error code: %s" % e.code)
Wiresharkネットワークプロトコルアナライザーのようなものでこれをチェックすると、GETではなくHEADリクエストを実際に送信していることがわかります。
これは、Wiresharkによってキャプチャされた、上記のコードからのHTTPリクエストとレスポンスです。
HEAD/doFeT HTTP/1.1
Accept-Encoding:identity
ホスト:bit.ly
接続:閉じる
ユーザーエージェント:Python-urllib/2.7HTTP/1.1 301移動
サーバー:nginx
日付:2012年2月19日日曜日13:20:56 GMT
Content-Type:text/html; charset = utf-8
キャッシュ制御:プライベート。 max-age = 90
場所: http://www.kidsidebyside.org/?p=445
MIMEバージョン:1.0
コンテンツの長さ:127
接続:閉じる
Set-Cookie:_bit = 4f40f738-00153-02ed0-421cf10a; domain = .bit.ly; expires = Fri Aug 17 13:20:56 2012; path = /; HttpOnly
ただし、他の質問のコメントの1つで述べたように、問題のURLにリダイレクトが含まれている場合、urllib2はHEADではなく宛先にGET要求を実行します。 HEADリクエストのみを行いたい場合、これは大きな欠点になる可能性があります。
上記のリクエストにはリダイレクトが含まれます。 Wiresharkがキャプチャした宛先へのリクエストは次のとおりです。
GET/2009/05/come-and-draw-the-circle-of-unity-with-us/HTTP/1.1
Accept-Encoding:identity
ホスト:www.kidsidebyside.org
接続:閉じる
ユーザーエージェント:Python-urllib/2.7
Urllib2を使用する代わりに、Joe Gregorioの httplib2 ライブラリを使用することもできます。
import httplib2
url = "http://bit.ly/doFeT"
http_interface = httplib2.Http()
try:
response, content = http_interface.request(url, method="HEAD")
print ("Response status: %d - %s" % (response.status, response.reason))
# This will just display all the dictionary key-value pairs. Replace this
# line with something useful.
response.__dict__
except httplib2.ServerNotFoundError, e:
print (e.message)
これには、HEAD初期HTTP要求と宛先URLへのリダイレクトされた要求の両方に要求を使用するという利点があります。
最初のリクエストは次のとおりです。
HEAD/doFeT HTTP/1.1
ホスト:bit.ly
accept-encoding:gzip、deflate
user-agent:Python-httplib2/0.7.2(gzip)
宛先への2番目のリクエストは次のとおりです。
HEAD/2009/05/come-and-draw-the-circle-of-unity-with-us/HTTP/1.1
ホスト:www.kidsidebyside.org
accept-encoding:gzip、deflate
user-agent:Python-httplib2/0.7.2(gzip)
urllib2.urlopenは、HTTP POSTではなくHTTP GET(またはデータ引数を指定した場合はHEAD)を実行します(後者を実行した場合、readlinesまたは他のアクセスを実行できませんでした)もちろん、ページ本文に)。
ワンライナー:
$ python -c "import urllib2; print urllib2.build_opener(urllib2.HTTPHandler(debuglevel=1)).open(urllib2.Request('http://google.com'))"