كيف يمكنك الحصول على رؤوس الافتراضي في urllib2 الطلب ؟

StackOverflow https://stackoverflow.com/questions/603856

  •  03-07-2019
  •  | 
  •  

سؤال

لدي الثعبان عميل ويب التي تستخدم urllib2.فمن السهل بما فيه الكفاية لإضافة رؤوس HTTP إلى الطلبات المنتهية ولايته.أنا فقط إنشاء قاموس رؤوس أريد أن أضيف ، ونقله إلى طلب مهيئ.

بيد أخرى "المعيار" رؤوس HTTP الحصول على إضافة إلى طلب فضلا عن تلك المخصصة أنا صراحة إضافة.عندما شم طلب استخدام يريشارك ، أرى رؤوس إلى جانب تلك أضيف نفسي.سؤالي هو كيف يمكنني الوصول إلى هذه الرؤوس ؟ أريد أن سجل كل طلب (بما في ذلك كامل مجموعة من رؤوس HTTP) و لا يمكن معرفة كيف.

أي نصائح ؟

باختصار:كيف يمكنني الحصول على كل الصادرة رؤوس من طلب HTTP إنشاؤه من قبل urllib2?

هل كانت مفيدة؟

المحلول

إذا كنت تريد أن ترى على طلب HTTP الحرفي التي يتم إرسالها خارج، وبالتالي نرى كل رأس الماضي تماما كما يمثل ذلك على السلك، ثم يمكن أن أقول لكم urllib2 لاستخدام النسخة الخاصة بك من HTTPHandler الذي يطبع خارج (أو يحفظ، أو أيا كان) طلب HTTP المنتهية ولايته.

import httplib, urllib2

class MyHTTPConnection(httplib.HTTPConnection):
    def send(self, s):
        print s  # or save them, or whatever!
        httplib.HTTPConnection.send(self, s)

class MyHTTPHandler(urllib2.HTTPHandler):
    def http_open(self, req):
        return self.do_open(MyHTTPConnection, req)

opener = urllib2.build_opener(MyHTTPHandler)
response = opener.open('http://www.google.com/')

ونتيجة تشغيل هذا الرمز هو:

GET / HTTP/1.1
Accept-Encoding: identity
Host: www.google.com
Connection: close
User-Agent: Python-urllib/2.6

نصائح أخرى

وتستخدم المكتبة urllib2 الأجسام OpenerDirector للتعامل مع الافتتاح الفعلي. لحسن الحظ، توفر المكتبة الثعبان التخلف لذلك لم يكن لديك ل. غير أنه، هذه الكائنات 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() أعطيك قائمة من المجموعات من ALL رؤوس، مع كل بنفسك وتلك التي أضافها OpenerDirector. I يتعين عليه أن يذكر هذا أولا لأنه صحيت الأكثر مباشرة عذرا.

وتحرير 2: بعد سؤالك عن مثال لتحديد معالج الخاص بك، وهنا عينة خطرت لي. قلق في أي monkeying مع سلسلة طلب هو أننا بحاجة للتأكد من أن معالج آمن لطلبات متعددة، وهذا هو السبب أنا غير مريح مجرد استبدال تعريف putheader على الطبقة HTTPConnection مباشرة.

للأسف، لأن الأجزاء الداخلية من HTTPConnection وAbstractHTTPHandler داخلية جدا، لدينا لإعادة إنتاج الكثير من رمز من مكتبة الثعبان لحقن السلوك عادتنا. على افتراض أنا لم اخطأ أدناه وهذا يعمل بشكل جيد كما فعلت في بلدي 5 دقائق من الاختبار، يرجى توخي الحذر لإعادة النظر في هذا التجاوز إذا قمت بتحديث نسخة بايثون الخاص بك إلى رقم المراجعة (أي: 2.5.x الى 2.5.y أو 2،5-2،6، الخ).

وأود أن أذكر أن وبالتالي أنا على بايثون 2.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')]

وماذا عن شيء مثل هذا:

import urllib2
import httplib

old_putheader = httplib.HTTPConnection.putheader
def putheader(self, header, value):
    print header, value
    old_putheader(self, header, value)
httplib.HTTPConnection.putheader = putheader

urllib2.urlopen('http://www.google.com')

وهناك حل على مستوى منخفض:

import httplib

class HTTPConnection2(httplib.HTTPConnection):
    def __init__(self, *args, **kwargs):
        httplib.HTTPConnection.__init__(self, *args, **kwargs)
        self._request_headers = []
        self._request_header = None

    def putheader(self, header, value):
        self._request_headers.append((header, value))
        httplib.HTTPConnection.putheader(self, header, value)

    def send(self, s):
        self._request_header = s
        httplib.HTTPConnection.send(self, s)

    def getresponse(self, *args, **kwargs):
        response = httplib.HTTPConnection.getresponse(self, *args, **kwargs)
        response.request_headers = self._request_headers
        response.request_header = self._request_header
        return response

مثال:

conn = HTTPConnection2("www.python.org")
conn.request("GET", "/index.html", headers={
    "User-agent": "test",
    "Referer": "/",
})
response = conn.getresponse()

وresponse.status، response.reason:

1: 200 OK

وresponse.request_headers:

[('Host', 'www.python.org'), ('Accept-Encoding', 'identity'), ('Referer', '/'), ('User-agent', 'test')]

وresponse.request_header:

GET /index.html HTTP/1.1
Host: www.python.org
Accept-Encoding: identity
Referer: /
User-agent: test

وهناك حل آخر، وتستخدم ساحرة فكرة من <لأ href = "https://stackoverflow.com/questions/603856/how-do-you-get-default-headers-in-a-urllib2-request/603966 # 603966 "> كيف تحصل على رؤوس الافتراضي في طلب urllib2 لكن لا ينسخ رمز من الأمراض المنقولة جنسيا-ليب:؟

class HTTPConnection2(httplib.HTTPConnection):
    """
    Like httplib.HTTPConnection but stores the request headers.
    Used in HTTPConnection3(), see below.
    """
    def __init__(self, *args, **kwargs):
        httplib.HTTPConnection.__init__(self, *args, **kwargs)
        self.request_headers = []
        self.request_header = ""

    def putheader(self, header, value):
        self.request_headers.append((header, value))
        httplib.HTTPConnection.putheader(self, header, value)

    def send(self, s):
        self.request_header = s
        httplib.HTTPConnection.send(self, s)


class HTTPConnection3(object):
    """
    Wrapper around HTTPConnection2
    Used in HTTPHandler2(), see below.
    """
    def __call__(self, *args, **kwargs):
        """
        instance made in urllib2.HTTPHandler.do_open()
        """
        self._conn = HTTPConnection2(*args, **kwargs)
        self.request_headers = self._conn.request_headers
        self.request_header = self._conn.request_header
        return self

    def __getattribute__(self, name):
        """
        Redirect attribute access to the local HTTPConnection() instance.
        """
        if name == "_conn":
            return object.__getattribute__(self, name)
        else:
            return getattr(self._conn, name)


class HTTPHandler2(urllib2.HTTPHandler):
    """
    A HTTPHandler which stores the request headers.
    Used HTTPConnection3, see above.

    >>> opener = urllib2.build_opener(HTTPHandler2)
    >>> opener.addheaders = [("User-agent", "Python test")]
    >>> response = opener.open('http://www.python.org/')

    Get the request headers as a list build with HTTPConnection.putheader():
    >>> response.request_headers
    [('Accept-Encoding', 'identity'), ('Host', 'www.python.org'), ('Connection', 'close'), ('User-Agent', 'Python test')]

    >>> response.request_header
    'GET / HTTP/1.1\\r\\nAccept-Encoding: identity\\r\\nHost: www.python.org\\r\\nConnection: close\\r\\nUser-Agent: Python test\\r\\n\\r\\n'
    """
    def http_open(self, req):
        conn_instance = HTTPConnection3()
        response = self.do_open(conn_instance, req)
        response.request_headers = conn_instance.request_headers
        response.request_header = conn_instance.request_header
        return response

وتحرير: تحديث المصدر

ونرى urllib2.py:do_request (خط 1044 (1067)) وurllib2.py:do_open (خط 1073) (خط 293) self.addheaders = [( "وكيل المستخدم"، client_version)] (فقط "وكيل المستخدم" وأضاف)

يبدو لي أنك تبحث عن رؤوس استجابة الكائن ، والتي تشمل Connection: close, ، وما إلى ذلك.هذه رؤوس يعيش في وجوه عاد قبل urlopen.الحصول عليهم من السهل بما فيه الكفاية:

from urllib2 import urlopen
req = urlopen("http://www.google.com")
print req.headers.headers

req.headers هو مثيل httplib.HTTPMessage

وينبغي أن ترسل الافتراضي رؤوس http (على النحو المحدد من قبل w3.org) جنبا إلى جنب مع تلك التي تحددها.يمكنك استخدام أداة مثل يريشارك إذا كنت تود أن ترى في مجملها.

تحرير:

إذا كنت ترغب في الدخول عليها ، يمكنك استخدام WinPcap التقاط الحزم المرسلة من قبل تطبيقات محددة (في الحالة الخاصة بك ، بيثون).كما يمكنك تحديد نوع الحزم و الكثير من التفاصيل الأخرى.

-جون

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top