Knihoven pro HTTP klienty (tedy “programy, které stahují webové stránky“)
je celá řada.
Jedna z nich, urllib.request
, je dokonce součástí standardní knihovny Pythonu.
Pokud tedy budete chtít HTTP používat a seznam závislostí
svého projektu nemůžete rozšířit o další knihovnu, jde to.
Mnohem snáze se vám ale bude pracovat s knihovnou Requests, která má mnohem “lidštější” rozhraní a používá se mnohem jednodušeji. Rozdíl je největší u pokročilejších vlastností jako cookies, autentizace nebo sdílení spojení (Keep-alive), které s Requests zvládnete i bez detailních znalostí protokolu HTTP.
Dokonce i v dokumentaci modulu urllib
se píše:
The Requests package is recommended for a higher-level HTTP
client interface.
Zaměříme se tedy na Requests hned od začátku.
Knihovna Requests se instaluje standardním způsobem:
$ python -m pip install requests
Budeme předpokládat, že znáte alespoň základy HTTP protokolu, a vrhneme se rovnou na příklad.
Pokud základy neznáte, můžete se podívat na shrnutí pro začátečníky, které vysvětluje vše potřebné.
>>> import getpass
>>> import requests
>>> username = input('Username: ')
Username: hroncok
>>> password = getpass.getpass()
Password:
>>> r = requests.get('https://api.github.com/user', auth=(username, password))
>>> r.status_code
200
>>> r.headers['content-type']
'application/json; charset=utf8'
>>> r.encoding
'utf-8'
>>> r.text
'{"login":"hroncok"...'
>>> r.json()
{'avatar_url': 'https://avatars.githubusercontent.com/u/2401856?v=3', ...}
Tento příklad pracuje přímo se jménem a heslem. To se většinou nedělá a webové API to často ani nepodporují. Pokud na GitHub používáte dvoufaktorovou autentizaci, příklad nebude fungovat.
Příklady použití pro další HTTP metody najdete v dokumentaci.
Hlavně v budoucnu se nám bude hodit použití tzv. session.
Session má několik výhod. První je, že využívá na pozadí jedno otevřené HTTP spojení a poskytuje tak při více sousledných požadavcích výrazné zrychlení.
Dále pak session automaticky ukládá cookies a je možné u ní nastavit výchozí hlavičky.
Zkuste si cookies vyzkoušet s httpbin.org – službou k testování HTTP dotazů:
>>> session = requests.Session()
>>> session.get('http://httpbin.org/cookies/set/mipyt/best')
<Response [200]>
>>> r = session.get('http://httpbin.org/cookies')
>>> r.json()
{'cookies': {'mipyt': 'best'}}
>>> session.headers.update({'x-test': 'true'})
>>> r = session.get('http://httpbin.org/headers', headers={'x-test2': 'true'})
>>> r.json()
{'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Connection': 'close', 'Cookie': 'mipyt=best', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.19.1', 'X-Test': 'true', 'X-Test2': 'true'}}
Podíváme se teď, podobně jako v úvodním příkladu, na GitHub API, které má poměrně jednoduchou autentizaci (od GitHubu přímo získáte token). Stačí jít do nastavení a vyrobit nový token (zatím není třeba zaškrtávat žádná oprávnění).
Ochrana přihlašovacích tokenů
Váš token je něco jako vaše heslo. Nikomu je nesmíte ukazovat a nesmíte jej dát do Gitu. Stane-li se přesto, že se k němu dostane někdo nepovolaný, můžete jej v nastavení opět smazat.
Pomocí tokenu můžete z GitHubu získávat informace. Prozatím token nastavte do proměnné, později jej schováme například do konfiguračního souboru.
Tímto kódem lze například získat popis přihlášeného uživatele, tedy sebe sama.
>>> token = 'd7313dab254b7fd0d0f3ec3cbf754b3abce462d5'
>>> session = requests.Session()
>>> session.headers = {'User-Agent': 'Python'}
>>> def token_auth(req):
... req.headers['Authorization'] = f'token {token}'
... return req
...
>>> session.auth = token_auth
>>> r = session.get('https://api.github.com/user')
>>> r.json()
Funkce session.auth
v příkladu výše je autentizační funkce,
která nějakým způsobem modifikuje HTTP požadavek za účelem autentizace,
většinou přidává specifické hlavičky (jak je tomu i zde).
Lze ji nastavit buďto na celé session nebo předat argumentem auth
s každým
požadavkem.
Existují předpřipravené funkce v modulu requests.auth
, například
requests.auth.HTTPBasicAuth
provádí základní HTTP přihlášení.
Dle specifikace zakóduje jméno a heslo pomocí
algoritmu base64 a přidá hlavičku Authorization
.
Základní HTTP přihlášení
je tak běžné, že pro něj Requests mají zkratku –
místo HTTPBasicAuth
se dá použít i dvojice (jméno, heslo):
>>> requests.get('https://httpbin.org/basic-auth/AzureDiamond/hunter2',
auth=requests.auth.HTTPBasicAuth('AzureDiamond', 'hunter2'))
>>>
>>> requests.get('https://httpbin.org/basic-auth/AzureDiamond/hunter2',
auth=('AzureDiamond', 'hunter2'))
Všimněte si také hlavičky User-Agent
.
Ta je potřeba při komunikaci s GitHub API explicitně nastavit.
Nastavení na objektu session zajistí, že tato hlavička
bude ve všech požadavcích.
Pokud budete chtít něco provést, například dát hvězdičku repozitáři s těmito
materiály, musíte tokenu nastavit patřičné oprávnění
(u hvězdičky je to public_repo
).
To se dělá přes nastavení na GitHubu.
Hvězdičku pak přidáte takto:
>>> r = session.put('https://api.github.com/user/starred/pyvec/naucse.python.cz')
>>> r.text
''
Jak vidíte, API nevrací žádný text (žádné tělo odpovědi). Můžete ale zkontrolovat návratový stav:
>>> r.status_code
204
Případně vyhodit výjimku, pokud je stavový kód divný (např 404 Nenalezeno, 401 Chybí oprávnění apod.):
>>> r.raise_for_status()
Pokud hvězdičku chcete odebrat, použijte metodu DELETE. My ale věříme, že ji odebrat nechcete :)
Dokumentace ke GitHub API.
Když ukládáte skript do gitu, mějte na paměti, že tokeny a klíče do něj nikdy nepatří. Můžete je uložit do konfiguračního souboru, který bude gitem ignorován, například takhle:
[github]
token = d7313dab254b7fd0d0f3ec3cbf754b3abce462d5
A následně konfiguraci načtete pomocí modulu configparser:
>>> import configparser
>>> config = configparser.ConfigParser()
>>> with open('auth.cfg') as f:
... config.read_file(f)
>>> config['github']['token']
'd7313dab254b7fd0d0f3ec3cbf754b3abce462d5'
Do souboru .gitignore
pak musíte přidat název ignorovaného souboru, např.:
auth.cfg
Ověřte si, že git soubor auth.cfg
opravdu ignoruje, t.j. soubor se neukáže
ve výstupu git status
.
Jelikož ostatní tento konfigurační soubor neuvidí,
je vhodné jim vysvětlit, jak takový soubor (s jejich údaji) vytvořit.
Můžete například vložit do gitu soubor auth.cfg.sample
s vymyšlenými údaji, či příklad uvést v README.
ConfigParser změní velikost písmen klíčů z konfiguračního souboru na malá.
Pokud potřebujete, aby byly klíče přesně tak, jak jsou v souboru, musíte
před načtením nastavit config.optionxform = str
.