User-agent hlavička requestu na WMS server

Nedávno jsme s Martinem zjistili, že nám přestaly fungovat příklady v materiálech školení GeoPython pro začátečníky, konkrétně příklady věnované knihovně OWSLib, což je knihovna fungující jako klient k různým OGC OWS službám, jako je WMS, WMTS, WFS a pod.

OWSLib má svoje mouchy. Pokud ale chcete od někud stáhnout automatizovaně data prostřednictvím WFS, WCS, prohledávat katalogy pomocí CSW, spouštět procesy WPS, či stahovat obrázky z WMS nebo WMTS, je OWSLib celkem dobrou pomocnicí.

Server v našich ukázkách na jednoduchý WMS dotaz odpovídal nějak zvláštně – přitom stejným dotaz ve webovém prohlížeči fungoval, co s tím?

>>> from owslib.wms import WebMapService as WMS
>>> wms = WMS("http://geoportal.cuzk.cz/WMTS_ORTOFOTO/WMTService.aspx")


Traceback (most recent call last):
  File "", line 1, in 
  File "/home/jachym/src/OWSLib/owslib/wms.py", line 46, in WebMapService
    timeout=timeout, headers=headers)
  File "/home/jachym/src/OWSLib/owslib/map/wms111.py", line 80, in __init__
    self._capabilities = reader.read(self.url, timeout=self.timeout)
  File "/home/jachym/src/OWSLib/owslib/map/common.py", line 71, in read
    headers=self.headers)
  File "/home/jachym/src/OWSLib/owslib/util.py", line 183, in openURL
    **rkwargs)
  File "/home/jachym/.local/lib/python3.5/site-packages/requests/api.py", line 56, in request
    return session.request(method=method, url=url, **kwargs)
  File "/home/jachym/.local/lib/python3.5/site-packages/requests/sessions.py", line 475, in request
    resp = self.send(prep, **send_kwargs)
  File "/home/jachym/.local/lib/python3.5/site-packages/requests/sessions.py", line 617, in send
    history = [resp for resp in gen] if allow_redirects else []
  File "/home/jachym/.local/lib/python3.5/site-packages/requests/sessions.py", line 617, in 
    history = [resp for resp in gen] if allow_redirects else []
  File "/home/jachym/.local/lib/python3.5/site-packages/requests/sessions.py", line 110, in resolve_redirects
    raise TooManyRedirects('Exceeded %s redirects.' % self.max_redirects, response=resp)
requests.exceptions.TooManyRedirects: Exceeded 30 redirects.

Když dotaz funguje v prohlížeči a odpověď ve skriptu vypadá jinak – tedy server reaguje na typ klientské aplikace, způsobuje to pravděpodobně hlavička User-agent. Jde o identifikaci klienta, můj webový prohlížeč se třeba hlásí jako

...
user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36
...

Mimochodem, těchto hlaviček posílá prohlížeč na server strašně moc, mrkněte do záložky “síť” ve vývojářském prostředí.

Když se podívate do kódu OWSLib, tak uvidíte, že se knihovna hlásí pod hlavičkou

...
 'User-Agent'      : 'OWSLib (https://geopython.github.io/OWSLib)',
...

OWSLib je na štěstí celkem inteligentně psaná knihovna, hlavičky můžete vytvořit i vlastní. V našem případě tedy přepíšeme výchozí User-agent hlavičku:

wms = WMS("http://geoportal.cuzk.cz/WMS_ZM10_PUB/WMService.aspx", headers={"User-agent": "x"})

A stáhnout obrázek jde pak už bez problémů:

img = wms.getmap(
    layers=["GR_ZM10"],
    size=[800, 600],
    srs="EPSG:5514",
    bbox=[-950003, -1250003, -399990, -899996],
    format="image/png", headers={"User-agent": "x"})

with open('data/wms_download.png', 'w') as out:
    out.write(img.read())

Takže závěrem ještě jednou: Pokud Vám server v prohlížeči korektně odpovídá a ve skriptu končí chybou, zkuste mu podstrčit jinou User-agent hlavičku. Občas se tenhle trik může používat k blokování nelegálního stahování (rozuměj: Když je User-agent “Python”, tak to bude nejspíš skript hromadného stahování). Určitě nic nelegálně nestahujte, tento trik se může hodit.

Za GISMentors Jáchym Čepický