urllib2ライブラリは、OpenerDirectorオブジェクトを使用して実際のオープニングを処理します。幸い、Pythonライブラリにはデフォルトが用意されているので、そうする必要はありません。ただし、余分なヘッダーを追加しているのは、これらのOpenerDirectorオブジェクトです。
リクエストが送信された後の内容を確認するには(たとえば、ログに記録できるように):
req = urllib2.Request(url='http://google.com')
response = urllib2.urlopen(req)
print req.unredirected_hdrs
(produces {'Host': 'google.com', 'User-agent': 'Python-urllib/2.5'} etc)
unredirected_hdrsは、OpenerDirectorsが余分なヘッダーをダンプする場所です。単に見るreq.headers
だけで、あなた自身のヘッダーだけが表示されます-ライブラリはそれらをあなたのために無邪気に残します。
リクエストを送信する前にヘッダーを確認する必要がある場合は、送信をインターセプトするためにOpenerDirectorをサブクラス化する必要があります。
お役に立てば幸いです。
編集:リクエストが送信されるとreq.header_items()
、すべてのヘッダーのタプルのリストが表示され、自分のものとOpenerDirectorによって追加されたものの両方が表示されることを忘れました。これが最も簡単なので、最初に言及する必要がありました:-)申し訳ありません。
編集2:独自のハンドラーを定義するための例についての質問の後、これが私が思いついたサンプルです。リクエストチェーンを使用する場合の懸念は、ハンドラーが複数のリクエストに対して安全であることを確認する必要があることです。そのため、HTTPConnectionクラスのputheaderの定義を直接置き換えるだけでは不快です。
残念ながら、HTTPConnectionとAbstractHTTPHandlerの内部は非常に内部的であるため、カスタム動作を注入するには、Pythonライブラリからコードの多くを再現する必要があります。私が以下を間違えておらず、これが5分間のテストと同じように機能すると仮定すると、Pythonバージョンをリビジョン番号(つまり、2.5.xから2.5.yまたは2.5から2.6など)。
したがって、私はPython2.5.1を使用していることに言及する必要があります。2.6、特に3.0を使用している場合は、それに応じて調整する必要があります。
これがうまくいかない場合はお知らせください。私はこの質問でwaaaayyyyをとても楽しんでいます:
import urllib2
import httplib
import socket
class CustomHTTPConnection(httplib.HTTPConnection):
def __init__(self, *args, **kwargs):
httplib.HTTPConnection.__init__(self, *args, **kwargs)
self.stored_headers = []
def putheader(self, header, value):
self.stored_headers.append((header, value))
httplib.HTTPConnection.putheader(self, header, value)
class HTTPCaptureHeaderHandler(urllib2.AbstractHTTPHandler):
def http_open(self, req):
return self.do_open(CustomHTTPConnection, req)
http_request = urllib2.AbstractHTTPHandler.do_request_
def do_open(self, http_class, req):
# All code here lifted directly from the python library
host = req.get_host()
if not host:
raise URLError('no host given')
h = http_class(host) # will parse host:port
h.set_debuglevel(self._debuglevel)
headers = dict(req.headers)
headers.update(req.unredirected_hdrs)
headers["Connection"] = "close"
headers = dict(
(name.title(), val) for name, val in headers.items())
try:
h.request(req.get_method(), req.get_selector(), req.data, headers)
r = h.getresponse()
except socket.error, err: # XXX what error?
raise urllib2.URLError(err)
r.recv = r.read
fp = socket._fileobject(r, close=True)
resp = urllib2.addinfourl(fp, r.msg, req.get_full_url())
resp.code = r.status
resp.msg = r.reason
# This is the line we're adding
req.all_sent_headers = h.stored_headers
return resp
my_handler = HTTPCaptureHeaderHandler()
opener = urllib2.OpenerDirector()
opener.add_handler(my_handler)
req = urllib2.Request(url='http://www.google.com')
resp = opener.open(req)
print req.all_sent_headers
shows: [('Accept-Encoding', 'identity'), ('Host', 'www.google.com'), ('Connection', 'close'), ('User-Agent', 'Python-urllib/2.5')]