urllib2, falsche Schreibweise von User-Agent?

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
vimico
User
Beiträge: 9
Registriert: Montag 27. März 2006, 22:27

Montag 27. März 2006, 22:42

Ich versuche seit einiger Zeit den "User-Agent" bei einem WWW-Zugriff zu setzen. Dies war aber nur teilweise erfolgreich.

Zwer setzen die Befehle add_header oder ein header-EIntrag im Konstruktor einen User-Agent-Header, ein TCPDUMP zeigt jedoch, dass der Header "User-agent" und nicht "User-Agent" ausgegeben wird.

Den meisten Sites ist dies egal, einige sind aber pingelig.

Irgendeine Idee, wo man dass ändern kann?
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dienstag 28. März 2006, 06:25

Du hast recht ich hab es gerade auch mal damit getestet:

Code: Alles auswählen

import urllib2

opener = urllib2.build_opener()
opener.addheaders = [('User-Agent', 'Mozilla/5.0')]
opener.addheaders = [('TEST-HEADER', 'Mozilla/5.0')]
handle = opener.open("http://www.google.de")
'User-Agent' wird zu 'User-agent'
und
'TEST-HEADER' wird zu 'Test-header'

Und das liegt an:

Code: Alles auswählen

    def add_header(self, key, val):
        # useful for something like authentication
        self.headers[key.capitalize()] = val
In http://svn.python.org/view/python/trunk ... iew=markup

Ich geh mal davon aus, das das dem Standart entpricht. Wobei Firefox allerdings die andere Schreibweise nimmt...


EDIT: Ich sehe gerade, das bei AbstractHTTPHandler.do_request_() das gemacht wird:

Code: Alles auswählen

        for name, value in self.parent.addheaders:
            name = name.capitalize()
EDIT2: Also Lösung würde ich sagen, die betreffenden Methoden einfach überschreiben, aber so auf die schnelle Funktioniert das nicht:

Code: Alles auswählen

import urllib2

class Request(urllib2.Request):
    def add_header(self, key, val):
        print "key:", key
        self.headers[key] = val

urllib2.Request = Request

class AbstractHTTPHandler(urllib2.AbstractHTTPHandler):
    def do_request_(self, request):
        host = request.get_host()
        if not host:
            raise URLError('no host given')

        if request.has_data():  # POST
            data = request.get_data()
            if not request.has_header('Content-type'):
                request.add_unredirected_header(
                    'Content-type',
                    'application/x-www-form-urlencoded')
            if not request.has_header('Content-length'):
                request.add_unredirected_header(
                    'Content-length', '%d' % len(data))

        scheme, sel = splittype(request.get_selector())
        sel_host, sel_path = splithost(sel)
        if not request.has_header('Host'):
            request.add_unredirected_header('Host', sel_host or host)
        for name, value in self.parent.addheaders:
            #~ name = name.capitalize()
            print "Name:", name
            if not request.has_header(name):
                request.add_unredirected_header(name, value)

        return request

urllib2.AbstractHTTPHandler = AbstractHTTPHandler

opener = urllib2.build_opener()
opener.addheaders = [('User-Agent', 'Mozilla/5.0')]
opener.addheaders = [('TEST-HEADER', 'Mozilla/5.0')]
handle = opener.open("http://www.google.de")
Ansonsten, könntest du socket nehmen, aber das ist aufwendiger: http://www.python-forum.de/viewtopic.php?t=3615

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
vimico
User
Beiträge: 9
Registriert: Montag 27. März 2006, 22:27

Dienstag 28. März 2006, 12:40

Lauf RFC 2616 ist "User-Agent" die richtige Schreibweise:

http://www.w3.org/Protocols/rfc2616/rfc ... l#sec14.43

Da sollte man vielleicht mal einen Bug-Report schreiben...

EDIT: Ich habe gerade den einfachen Weg genommen und urllib2.py geändert... seitdem klappts auch mit Yahoo...

Vielen Dank für den Hinweis.
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dienstag 28. März 2006, 13:13

vimico hat geschrieben:Da sollte man vielleicht mal einen Bug-Report schreiben...
Hast du anscheinen gemacht:
https://sourceforge.net/tracker/?group_ ... id=1459963
:lol:

Es gibt allerdings schon Bug-Reports darüber:
https://sourceforge.net/tracker/?group_ ... aid=994101

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
vimico
User
Beiträge: 9
Registriert: Montag 27. März 2006, 22:27

Donnerstag 30. März 2006, 11:04

jens hat geschrieben:
vimico hat geschrieben:Da sollte man vielleicht mal einen Bug-Report schreiben...
Hast du anscheinen gemacht:
https://sourceforge.net/tracker/?group_ ... id=1459963
:lol:
Ja, ich konnte mich einfach nicht zurückhalten :)
jens hat geschrieben: Es gibt allerdings schon Bug-Reports darüber:
https://sourceforge.net/tracker/?group_ ... aid=994101
Ich muss zugeben, den hatte ich übersehen. Zwei Jahre bin ich dann doch nicht zurückgegangen... zumal der Bug ja immer noch drin war.

Kurze Zusammenfassung

Der offizielle Bug-Fix: In urllib2 capitalize() gegen title() austauschen (3 Fundstellen).

title() macht tatsächlich aus "TEST-HEADER" "Test-Header".

Grund dafür, dass eine solche Funktion überhaupt verwendet wird ist, dass die Entwickler vermeiden wollten, dass ein Header mehrfach übertragen wird, nur weil die Groß/Keinschreibung unterschiedlich ist (also z.B. einmal als "TEST-HEADER" und dann nochmal als "Test-Header"). Die bis dato verwendete Funktion capitalize() ist jedoch ungeeignet, da sie bei vielen Headern die offizielle Schreibweise verfälscht, was zu Problemen führen kann.
Antworten