Zanurkuj w Pythonie/Ustawianie User-Agent

Ustawianie User-Agent

edytuj

Pierwszym krokiem, aby udoskonalić swój klient serwisu HTTP jest właściwe zidentyfikowanie siebie za pomocą nagłówka User-Agent. Aby to zrobić, potrzebujemy wyjść poza prosty urllib i zanurkować w urllib2.

Przykład. Wprowadzenie do urllib2
>>> import httplib
>>> httplib.HTTPConnection.debuglevel = 1                             #(1)
>>> import urllib2
>>> request = urllib2.Request('http://diveintomark.org/xml/atom.xml') #(2)
>>> opener = urllib2.build_opener()                                   #(3)
>>> feeddata = opener.open(request).read()                            #(4)
connect: (diveintomark.org, 80)
 send: '
 GET /xml/atom.xml HTTP/1.0
 Host: diveintomark.org
 User-agent: Python-urllib/2.1
 '
 reply: 'HTTP/1.1 200 OK\r\n'
 header: Date: Wed, 14 Apr 2004 23:23:12 GMT
 header: Server: Apache/2.0.49 (Debian GNU/Linux)
 header: Content-Type: application/atom+xml
 header: Last-Modified: Wed, 14 Apr 2004 22:14:38 GMT
 header: ETag: "e8284-68e0-4de30f80"
 header: Accept-Ranges: bytes
 header: Content-Length: 26848
 header: Connection: close
--->Autor tego podręcznika najwyraźniej używał Pythona w wersji 2.3. 
Aktualna stabilna wersja 2.5.2 nieco się różni i tak włączone debugowanie nie zadziała, z tego powodu że biblioteka 'urllib2'
importuje do własnej przestrzeni nazw bibliotekę 'httplib', w której 'debuglevel' jest domyślnie wyłączony, by go włączyć należy
przy inicjalizacji 'build_opener' dodać jako argument 'HTTPHandler' z włączonym debugowaniem:
  1. Jeśli w dalszym ciągu masz otwarty IDE na przykładzie z poprzedniego podrozdziału, możesz ten punkt pominąć. Polecenie to włącza debugowanie HTTP, dzięki której możemy zobaczyć, co rzeczywiście wysyłamy i co zostaje przysłane do nas.
  2. Pobieranie zasobów HTTP za pomocą urllib2 składa się z trzech krótkich etapów. Pierwszy krok to utworzenie obiektu żądania (instancji klasy Request). Klasa Request przyjmuje jako parametr URL zasobów, z których będziemy ewentualnie pobierać dane. Dodajmy, że za pomocą tego kroku jeszcze nic nie pobieramy.
  3. Drugim krokiem jest zbudowanie otwieracza (ang. opener) URL-a. Może on przyjąć dowolną liczbę funkcji obsługi, które kontrolują, w jaki sposób obsługiwać odpowiedzi. Ale możemy także zbudować otwieracz bez podawania żadnych funkcji obsługi, a co robimy w tym fragmencie. Później, kiedy będziemy omawiać przekierowania, zobaczymy w jaki sposób zdefiniować własne funkcje obsługi.
  4. Ostatnim krokiem jest kazanie otwieraczowi, aby korzystając z utworzonego obiektu żądania otworzył URL. Widzimy, że wszystkie otrzymane informacje debugujące zostały wypisane. W tym kroku tak pobieramy zasoby, a zwrócone dane przechowujemy w feeddata.

Poprawny przykład programu do aktualnej wersji (2.5.2):

>>> import urllib2
>>> req=urllib2.Request('http://www.wp.pl')
>>> handler=urllib2.HTTPHandler()                          #(1)
>>> handler
<urllib2.HTTPHandler instance at 0x00CACC38>
>>> handler.set_http_debuglevel(1)                         #(2)
>>> opener=urllib2.build_opener(handler)                   #(3)
>>> opener.open(req)                                       #(4)
connect: (www.wp.pl, 80)
send: 'GET / HTTP/1.1\r\nAccept-Encoding: identity\r\nHost: www.wp.pl\r\nConnection: close\r\nUser-Agent: 
Python-urllib/2.5\r
\n\r\n'
reply: 'HTTP/1.1 200 OK\r\n'
header: Server: aris
header: Expires: Mon, 26 Jul 1997 05:00:00 GMT
header: Last-Modified: Fri, 05 Sep 2008 11:19:05 GMT
header: Pragma: no-cache
header: Cache-Control: no-cache
header: Content-type: text/html; charset=ISO-8859-2
header: Set-Cookie: reksticket=1220613545; expires=Sunday, 07-Sep-08 11:19:05 GMT; path=/; domain=.www.wp.pl
header: Set-Cookie: rekticket=1220613545; expires=Sunday, 07-Sep-08 11:19:05 GMT; path=/; domain=.wp.pl
header: Set-Cookie: statid=217.153.86.226.13470:1220613545:3180022324:v1; path=/; expires=Mon, 05-Sep-11 11:19:06 GMT
header: Set-Cookie: statid=217.153.86.226.13470:1220613545:3180022324:v1; domain=.wp.pl; path=/; expires=Mon,
05-Sep-11 11:19:06 GMT
header: Content-Length: 129517
header: Connection: close
<addinfourl at 18905488 whose fp = <socket._fileobject object at 0x00CA4C30>
>>> opener.handle_open['http']                             #(5)
[<urllib2.HTTPHandler instance at 0x00CACC38>]
  1. Stworzenie instancji 'HTTPHanler' z biblioteki 'urllib2'
  2. Ustawienie flagi 'debuglevel'
  3. Przekazanie instancji do 'build_opener' jako argumentu przy inicjalizacji. Domyślny 'HTTPHandler' zostaje nadpisany.
  4. Od tej chwili instancja 'opener' używa naszego zdefiniowanego handlera HTTP.
  5. 'opener.handle_open' zwraca słownik handlerów dla wszystkich protokołów. Dodanie klucza '['http']' zwraca jako wartość liste dla HTTP. Jak widzimy jest tylko jeden zdefiniowany przez nas
Przykład. Dodawanie nagłówków do żądania
>>> request                                                #(1)
<urllib2.Request instance at 0x00250AA8>
>>> request.get_full_url()
http://diveintomark.org/xml/atom.xml
>>> request.add_header('User-Agent',
...     'OpenAnything/1.0 +http://diveintopython.org/')    #(2)
>>> feeddata = opener.open(request).read()                 #(3)
connect: (diveintomark.org, 80)
send: '
GET /xml/atom.xml HTTP/1.0
Host: diveintomark.org
User-agent: OpenAnything/1.0 +http://diveintopython.org/   #(4)
'
reply: 'HTTP/1.1 200 OK\r\n'
header: Date: Wed, 14 Apr 2004 23:45:17 GMT
header: Server: Apache/2.0.49 (Debian GNU/Linux)
header: Content-Type: application/atom+xml
header: Last-Modified: Wed, 14 Apr 2004 22:14:38 GMT
header: ETag: "e8284-68e0-4de30f80"
header: Accept-Ranges: bytes
header: Content-Length: 26848
header: Connection: close
  1. Kontynuujemy z poprzedniego przykładu. Mamy już utworzony obiekt Request z URL-em, do którego chcemy się dostać.
  2. Za pomocą metody add_header obiektu klasy Request, możemy dodać do żądania dowolny nagłówek HTTP. Pierwszy argument jest nagłówkiem, a drugi jest wartością dostarczoną do tego nagłówka. Konwencja dyktuje, aby User-Agent powinien być w takim formacie: nazwa aplikacji, następnie slash, a potem numer wersji. Pozostała część może mieć dowolną formę, jednak znaleźć mnóstwo wariacji wykorzystania tego nagłówka, ale gdzieś powinno się umieścić URL aplikacji. User-Agent jest zazwyczaj logowany przez serwer wraz z innymi szczegółami na temat twojego żądania. Włączając URL twojej aplikacji, pozwalasz administratorom danego serwera skontaktować się z tobą, jeśli jest coś źle.
  3. Obiekt opener utworzony wcześniej może być także ponownie wykorzystany. Ponownie wysyłamy te same dane, ale tym razem ze zmienionym nagłówkiem User-Agent.
  4. Tutaj wysyłamy ustawiony przez nas nagłówek User-Agent, w miejsce domyślnego, wysyłanego przez Pythona. Jeśli będziesz uważnie patrzył, zobaczysz, że zdefiniowaliśmy nagłówek User-Agent, ale tak naprawdę wysłaliśmy nagłówek User-agent. Widzisz różnicę? urllib2 zmienia litery w ten sposób, że tylko pierwsza litera jest wielka. W rzeczywistości nie ma to żadnego znaczenia. Specyfikacja HTTP mówi, że wielkość liter nazwy pola nagłówka nie jest ważna.

Autor podręcznika stosował ustawianie nagłówków tylko do pojedynczych urli. Można też to zrobić dla wszystkich adresów otwieranych za pomocą instancji stworzonej poleceniem instancja=urllib2.build_opener. Jest to ważne jeśli za jej pomocą otwieramy wiele adresów, niektóre serwery po prostu mogą nie przyjmować zapytań z domyślną wartością nagłówka '[('User-agent', 'Python-urllib/2.5')]'.

>>> opener=urllib2.build_opener()
>>> opener.addheaders=[('user-agent','Mozillla/5.0'),('accept-encoding','gzip')]

Po wywołaniu tego polecenia wszystkie polecenia GET protokołu HTTP będą miały te dwa nagłówki.