Knihovna requests je určená pro HTTP požadavky (klienty). Přestože vytvářet HTTP požadavky jde i bez requests, pomocí standardní knihovny Pythonu, requests mají mnohem lidštější rozhraní a používají se mnohem jednodušeji.
Instaluje se 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 začátečnickou lekci, která vysvětluje o trošičku víc.
>>> 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', ...}
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': '*/*', 'User-Agent': 'python-requests/2.10.0', 'X-Test2': 'true', 'Host': 'httpbin.org', 'Accept-Encoding': 'gzip, deflate', 'X-Test': 'true', 'Cookie': 'mipyt=best'}}
Pro reálné použití si ukážeme, jak se dá pomocí requests získat seznam tweetů. Nebudeme samozřejmě nic parsovat z HTML stránek, ale použijeme API Twitteru.
>>> r = session.get('https://api.twitter.com/1.1/search/tweets.json')
>>> r.json()
{'errors': [{'code': 215, 'message': 'Bad Authentication data.'}]}
Jak můžete vidět v odpovědi, Twitter API neumožňuje data číst bez autentizace. Jak se autentizovat byste při troše hledání našli v dokumentaci, ale protože tu nevyučujeme úvod do OAuthu, ale Python, rozhodli jsme se vám to zjednodušit.
Nemáte-li na Twitter účet, vytvořte si ho. Můžete vytvořit nějaký dummy účet, který dál nebudete používat. Budete ale potřebovat ověřitelné telefonní číslo.
Po přihlášení na Twitter jděte na apps.twitter.com a vytvořte aplikaci
(URL si můžete vymyslet, třeba http://invalid).
Po vytvoření najdete na kartě Keys and Access Tokens API Key a API Secret.
Pozor, jedná se prakticky o hesla k vašemu Twitter účtu,
a proto by je nikdo kromě vás neměl vidět.
Ochrana přihlašovacích tokenů
Ještě jednou – API Key a API Secret se chovají jako hesla. Nikomu je nesmíte ukazovat! Stane-li se přesto, že se k nim dostane někdo nepovolaný, na kartě Keys and Access Tokens je můžete zrušit.
Prozatím klíče nastavte do proměnných, později je schováme například do konfiguračního souboru.
>>> api_key = 'D4HJp6PKmpon9eya1b2c3d4e5'
>>> api_secret = 'rhvasRMhvbuHJpu4MIuAb4WO50gnoQa1b2c3d4e5f6g7h8i9j0'
Pomocí těchto kódů je potřeba si od Twitter API vyžádat přístupový token.
Používá se k tomu běžné HTTP přihlášení (HTTP Basic authentication),
kde je api_key použit jako uživatelské jméno a api_secret jako heslo.
Pro běžné HTTP přihlášení se v knihovně requests používá
requests.auth.HTTPBasicAuth:
>>> r = session.post('https://api.twitter.com/oauth2/token',
auth=requests.auth.HTTPBasicAuth(api_key, api_secret),
data={'grant_type': 'client_credentials'})
>>>
>>> r.json()
{'token_type': 'bearer', 'access_token': 'AAAAAAAAAAAAAAAAAAAAAHhKXAAAAAAAaA1abB2bcC3cdD4deE5efF6fgG7ghH8hiI9ijJ0ja1b2c3d4e5f6g7h8i9j0a1b2c3d4e5f6g7h8i9j0'}
>>> bearer_token = r.json()['access_token']
Parametr 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.
requests.auth.HTTPBasicAuth zde 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 jen dvojice (jméno, heslo):
>>> r = session.post('https://api.twitter.com/oauth2/token',
auth=(api_key, api_secret),
data={'grant_type': 'client_credentials'})
Pro další komunikaci s Twitter API je nutné přidat hlavičku se získaným tokenem. Jelikož používáte session, není nutné to dělat u každého požadavku zvlášť, ale je možné nastavit autentizační funkci pro celou session.
>>> def bearer_auth(req):
... req.headers['Authorization'] = 'Bearer ' + bearer_token
... return req
...
>>> session.auth = bearer_auth
Pak už by mělo API fungovat. Použijeme API pro vyhledávání tweetů:
>>> r = session.get(
... 'https://api.twitter.com/1.1/search/tweets.json',
... params={'q': '#python'},
... )
>>> for tweet in r.json()['statuses']:
... print(tweet['text'])
...
Once a framework decides to abstract the HTML layer from you. Customizing your UI becomes sorcery. #django #Python
...
Zde je pro zjednodušení k dispozici celá funkce pro vytvoření autentizované session:
import requests
def twitter_session(api_key, api_secret):
session = requests.Session()
r = session.post('https://api.twitter.com/oauth2/token',
auth=(api_key, api_secret),
data={'grant_type': 'client_credentials'})
bearer_token = r.json()['access_token']
def bearer_auth(req):
req.headers['Authorization'] = 'Bearer ' + bearer_token
return req
session.auth = bearer_auth
return session
Podíváme se i na GitHub API, které má jednodušší 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í). Token je opět třeba patřičně chránit.
Pomocí tokenu pak můžete z GitHubu získávat informace. 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'] = 'token ' + token
... return req
...
>>> session.auth = token_auth
>>> r = session.get('https://api.github.com/user')
>>> r.json()
Všimněte si 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:
[twitter]
key = D4HJp6PKmpon9eya1b2c3d4e5
secret = rhvasRMhvbuHJpu4MIuAb4WO50gnoQa1b2c3d4e5f6g7h8i9j0
[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['twitter']['key']
D4HJp6PKmpon9eya1b2c3d4e5
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.
{
"data": {
"sessionMaterial": {
"id": "session-material:2017/mipyt-kam:requests-click:1",
"title": "Requests – Weboví klienti",
"html": "\n \n \n\n <h1>requests</h1>\n<p>Knihovna requests je určená pro HTTP požadavky (klienty).\nPřestože vytvářet HTTP požadavky jde i bez requests, pomocí standardní knihovny\nPythonu, requests mají mnohem lidštější rozhraní a používají se mnohem\njednodušeji.</p>\n<p>Instaluje se standardním způsobem:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">$ </span>python -m pip install requests\n</pre></div><p>Budeme předpokládat, že znáte alespoň základy HTTP protokolu,\na vrhneme se rovnou na příklad.</p>\n<div class=\"admonition note\"><p>Pokud základy neznáte, můžete se podívat na\n<a href=\"/2017/mipyt-kam/projects/github-api/\">začátečnickou lekci</a>,\nkterá vysvětluje o trošičku víc.</p>\n</div><div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"kn\">import</span> <span class=\"nn\">getpass</span>\n<span class=\"gp\">>>> </span><span class=\"kn\">import</span> <span class=\"nn\">requests</span>\n<span class=\"gp\">>>> </span><span class=\"n\">username</span> <span class=\"o\">=</span> <span class=\"nb\">input</span><span class=\"p\">(</span><span class=\"s1\">'Username: '</span><span class=\"p\">)</span>\n<span class=\"go\">Username: hroncok</span>\n<span class=\"gp\">>>> </span><span class=\"n\">password</span> <span class=\"o\">=</span> <span class=\"n\">getpass</span><span class=\"o\">.</span><span class=\"n\">getpass</span><span class=\"p\">()</span>\n<span class=\"go\">Password: </span>\n<span class=\"gp\">>>> </span><span class=\"n\">r</span> <span class=\"o\">=</span> <span class=\"n\">requests</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s1\">'https://api.github.com/user'</span><span class=\"p\">,</span> <span class=\"n\">auth</span><span class=\"o\">=</span><span class=\"p\">(</span><span class=\"n\">username</span><span class=\"p\">,</span> <span class=\"n\">password</span><span class=\"p\">))</span>\n<span class=\"gp\">>>> </span><span class=\"n\">r</span><span class=\"o\">.</span><span class=\"n\">status_code</span>\n<span class=\"go\">200</span>\n<span class=\"gp\">>>> </span><span class=\"n\">r</span><span class=\"o\">.</span><span class=\"n\">headers</span><span class=\"p\">[</span><span class=\"s1\">'content-type'</span><span class=\"p\">]</span>\n<span class=\"go\">'application/json; charset=utf8'</span>\n<span class=\"gp\">>>> </span><span class=\"n\">r</span><span class=\"o\">.</span><span class=\"n\">encoding</span>\n<span class=\"go\">'utf-8'</span>\n<span class=\"gp\">>>> </span><span class=\"n\">r</span><span class=\"o\">.</span><span class=\"n\">text</span>\n<span class=\"go\">'{"login":"hroncok"...'</span>\n<span class=\"gp\">>>> </span><span class=\"n\">r</span><span class=\"o\">.</span><span class=\"n\">json</span><span class=\"p\">()</span>\n<span class=\"go\">{'avatar_url': 'https://avatars.githubusercontent.com/u/2401856?v=3', ...}</span>\n</pre></div><p>Příklady použití pro další HTTP metody najdete v <a href=\"http://docs.python-requests.org/en/master/user/quickstart/\">dokumentaci</a>.</p>\n<h2>Použití session</h2>\n<p>Hlavně v budoucnu se nám bude hodit použití tzv.\n<a href=\"http://docs.python-requests.org/en/master/user/advanced/#session-objects\"><em>session</em></a>.</p>\n<p>Session má několik výhod.\nPrvní je, že využívá na pozadí jedno otevřené HTTP spojení a poskytuje tak\npři více sousledných požadavcích výrazné zrychlení.</p>\n<p>Dále pak session automaticky ukládá <em>cookies</em> a je možné u ní nastavit výchozí\nhlavičky.</p>\n<p>Zkuste si <em>cookies</em> vyzkoušet s <a href=\"http://httpbin.org\">httpbin.org</a> – službou\nk testování HTTP dotazů:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"n\">session</span> <span class=\"o\">=</span> <span class=\"n\">requests</span><span class=\"o\">.</span><span class=\"n\">Session</span><span class=\"p\">()</span>\n<span class=\"gp\">>>> </span><span class=\"n\">session</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s1\">'http://httpbin.org/cookies/set/mipyt/best'</span><span class=\"p\">)</span>\n<span class=\"go\"><Response [200]></span>\n<span class=\"gp\">>>> </span><span class=\"n\">r</span> <span class=\"o\">=</span> <span class=\"n\">session</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s1\">'http://httpbin.org/cookies'</span><span class=\"p\">)</span>\n<span class=\"gp\">>>> </span><span class=\"n\">r</span><span class=\"o\">.</span><span class=\"n\">json</span><span class=\"p\">()</span>\n<span class=\"go\">{'cookies': {'mipyt': 'best'}}</span>\n<span class=\"gp\">>>> </span><span class=\"n\">session</span><span class=\"o\">.</span><span class=\"n\">headers</span><span class=\"o\">.</span><span class=\"n\">update</span><span class=\"p\">({</span><span class=\"s1\">'x-test'</span><span class=\"p\">:</span> <span class=\"s1\">'true'</span><span class=\"p\">})</span>\n<span class=\"gp\">>>> </span><span class=\"n\">r</span> <span class=\"o\">=</span> <span class=\"n\">session</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s1\">'http://httpbin.org/headers'</span><span class=\"p\">,</span> <span class=\"n\">headers</span><span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s1\">'x-test2'</span><span class=\"p\">:</span> <span class=\"s1\">'true'</span><span class=\"p\">})</span>\n<span class=\"gp\">>>> </span><span class=\"n\">r</span><span class=\"o\">.</span><span class=\"n\">json</span><span class=\"p\">()</span>\n<span class=\"go\">{'headers': {'Accept': '*/*', 'User-Agent': 'python-requests/2.10.0', 'X-Test2': 'true', 'Host': 'httpbin.org', 'Accept-Encoding': 'gzip, deflate', 'X-Test': 'true', 'Cookie': 'mipyt=best'}}</span>\n</pre></div><h2>Twitter API</h2>\n<p>Pro reálné použití si ukážeme, jak se dá pomocí requests získat seznam tweetů.\nNebudeme samozřejmě nic parsovat z HTML stránek, ale použijeme <a href=\"https://dev.twitter.com/rest/public\">API Twitteru</a>.</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"n\">r</span> <span class=\"o\">=</span> <span class=\"n\">session</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s1\">'https://api.twitter.com/1.1/search/tweets.json'</span><span class=\"p\">)</span>\n<span class=\"gp\">>>> </span><span class=\"n\">r</span><span class=\"o\">.</span><span class=\"n\">json</span><span class=\"p\">()</span>\n<span class=\"go\">{'errors': [{'code': 215, 'message': 'Bad Authentication data.'}]}</span>\n</pre></div><p>Jak můžete vidět v odpovědi, Twitter API neumožňuje data číst bez autentizace.\nJak se autentizovat byste při troše hledání našli v dokumentaci, ale protože\ntu nevyučujeme úvod do OAuthu, ale Python, rozhodli jsme se vám to zjednodušit.</p>\n<p>Nemáte-li na Twitter účet, vytvořte si ho. Můžete vytvořit nějaký <em>dummy</em> účet,\nkterý dál nebudete používat. Budete ale potřebovat ověřitelné telefonní číslo.</p>\n<p>Po přihlášení na Twitter jděte na <a href=\"https://apps.twitter.com/\">apps.twitter.com</a> a vytvořte aplikaci\n(URL si můžete vymyslet, třeba <code>http://invalid</code>).\nPo vytvoření najdete na kartě <em>Keys and Access Tokens</em> <strong>API Key</strong> a <strong>API Secret</strong>.\nPozor, jedná se prakticky o hesla k vašemu Twitter účtu,\na proto by je nikdo kromě vás neměl vidět.</p>\n<div class=\"admonition warning\"><p class=\"admonition-title\">Ochrana přihlašovacích tokenů</p>\n<p>Ještě jednou – <em>API Key</em> a <em>API Secret</em> se chovají jako hesla.\nNikomu je nesmíte ukazovat!\nStane-li se přesto, že se k nim dostane někdo nepovolaný, na kartě\n<em>Keys and Access Tokens</em> je můžete zrušit.</p>\n</div><p>Prozatím klíče nastavte do proměnných, později je schováme například do\nkonfiguračního souboru.</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"n\">api_key</span> <span class=\"o\">=</span> <span class=\"s1\">'D4HJp6PKmpon9eya1b2c3d4e5'</span>\n<span class=\"gp\">>>> </span><span class=\"n\">api_secret</span> <span class=\"o\">=</span> <span class=\"s1\">'rhvasRMhvbuHJpu4MIuAb4WO50gnoQa1b2c3d4e5f6g7h8i9j0'</span>\n</pre></div><p>Pomocí těchto kódů je potřeba si od Twitter API vyžádat přístupový token.\nPoužívá se k tomu běžné HTTP přihlášení (<a href=\"https://cs.wikipedia.org/wiki/Basic_access_authentication\">HTTP Basic authentication</a>),\nkde je <code>api_key</code> použit jako uživatelské jméno a <code>api_secret</code> jako heslo.</p>\n<p>Pro běžné HTTP přihlášení se v knihovně requests používá\n<code>requests.auth.HTTPBasicAuth</code>:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"n\">r</span> <span class=\"o\">=</span> <span class=\"n\">session</span><span class=\"o\">.</span><span class=\"n\">post</span><span class=\"p\">(</span><span class=\"s1\">'https://api.twitter.com/oauth2/token'</span><span class=\"p\">,</span>\n<span class=\"go\"> auth=requests.auth.HTTPBasicAuth(api_key, api_secret),</span>\n<span class=\"go\"> data={'grant_type': 'client_credentials'})</span>\n<span class=\"gp\">>>> </span>\n<span class=\"gp\">>>> </span><span class=\"n\">r</span><span class=\"o\">.</span><span class=\"n\">json</span><span class=\"p\">()</span>\n<span class=\"go\">{'token_type': 'bearer', 'access_token': 'AAAAAAAAAAAAAAAAAAAAAHhKXAAAAAAAaA1abB2bcC3cdD4deE5efF6fgG7ghH8hiI9ijJ0ja1b2c3d4e5f6g7h8i9j0a1b2c3d4e5f6g7h8i9j0'}</span>\n<span class=\"gp\">>>> </span><span class=\"n\">bearer_token</span> <span class=\"o\">=</span> <span class=\"n\">r</span><span class=\"o\">.</span><span class=\"n\">json</span><span class=\"p\">()[</span><span class=\"s1\">'access_token'</span><span class=\"p\">]</span>\n</pre></div><p>Parametr <code>auth</code> v příkladu výše je autentizační funkce, která nějakým způsobem\nmodifikuje HTTP požadavek za účelem autentizace, většinou přidává specifické\nhlavičky.\n<code>requests.auth.HTTPBasicAuth</code> zde dle specifikace zakóduje jméno a heslo pomocí\nalgoritmu base64 a přidá hlavičku <code>Authorization</code>.</p>\n<p>Základní HTTP přihlášení je tak běžné, že pro něj Requests mají zkratku –\nmísto <code>HTTPBasicAuth</code> se dá použít jen dvojice (jméno, heslo):</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"n\">r</span> <span class=\"o\">=</span> <span class=\"n\">session</span><span class=\"o\">.</span><span class=\"n\">post</span><span class=\"p\">(</span><span class=\"s1\">'https://api.twitter.com/oauth2/token'</span><span class=\"p\">,</span>\n<span class=\"go\"> auth=(api_key, api_secret),</span>\n<span class=\"go\"> data={'grant_type': 'client_credentials'})</span>\n</pre></div><p>Pro další komunikaci s Twitter API je nutné přidat hlavičku se získaným tokenem.\nJelikož používáte session, není nutné to dělat u každého požadavku zvlášť,\nale je možné nastavit autentizační funkci pro celou session.</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"k\">def</span> <span class=\"nf\">bearer_auth</span><span class=\"p\">(</span><span class=\"n\">req</span><span class=\"p\">):</span>\n<span class=\"gp\">... </span> <span class=\"n\">req</span><span class=\"o\">.</span><span class=\"n\">headers</span><span class=\"p\">[</span><span class=\"s1\">'Authorization'</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"s1\">'Bearer '</span> <span class=\"o\">+</span> <span class=\"n\">bearer_token</span>\n<span class=\"gp\">... </span> <span class=\"k\">return</span> <span class=\"n\">req</span>\n<span class=\"gp\">... </span>\n<span class=\"gp\">>>> </span><span class=\"n\">session</span><span class=\"o\">.</span><span class=\"n\">auth</span> <span class=\"o\">=</span> <span class=\"n\">bearer_auth</span>\n</pre></div><p>Pak už by mělo API fungovat.\nPoužijeme <a href=\"https://developer.twitter.com/en/docs/tweets/search/api-reference/get-search-tweets.html\">API pro vyhledávání tweetů</a>:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"n\">r</span> <span class=\"o\">=</span> <span class=\"n\">session</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span>\n<span class=\"gp\">... </span> <span class=\"s1\">'https://api.twitter.com/1.1/search/tweets.json'</span><span class=\"p\">,</span>\n<span class=\"gp\">... </span> <span class=\"n\">params</span><span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s1\">'q'</span><span class=\"p\">:</span> <span class=\"s1\">'#python'</span><span class=\"p\">},</span>\n<span class=\"gp\">... </span><span class=\"p\">)</span>\n<span class=\"gp\">>>> </span><span class=\"k\">for</span> <span class=\"n\">tweet</span> <span class=\"ow\">in</span> <span class=\"n\">r</span><span class=\"o\">.</span><span class=\"n\">json</span><span class=\"p\">()[</span><span class=\"s1\">'statuses'</span><span class=\"p\">]:</span>\n<span class=\"gp\">... </span> <span class=\"k\">print</span><span class=\"p\">(</span><span class=\"n\">tweet</span><span class=\"p\">[</span><span class=\"s1\">'text'</span><span class=\"p\">])</span>\n<span class=\"gp\">... </span>\n<span class=\"go\">Once a framework decides to abstract the HTML layer from you. Customizing your UI becomes sorcery. #django #Python</span>\n<span class=\"gp\">...\n</span></pre></div><p>Zde je pro zjednodušení k dispozici celá funkce pro vytvoření autentizované\n<em>session</em>:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"kn\">import</span> <span class=\"nn\">requests</span>\n\n<span class=\"k\">def</span> <span class=\"nf\">twitter_session</span><span class=\"p\">(</span><span class=\"n\">api_key</span><span class=\"p\">,</span> <span class=\"n\">api_secret</span><span class=\"p\">):</span>\n <span class=\"n\">session</span> <span class=\"o\">=</span> <span class=\"n\">requests</span><span class=\"o\">.</span><span class=\"n\">Session</span><span class=\"p\">()</span>\n\n <span class=\"n\">r</span> <span class=\"o\">=</span> <span class=\"n\">session</span><span class=\"o\">.</span><span class=\"n\">post</span><span class=\"p\">(</span><span class=\"s1\">'https://api.twitter.com/oauth2/token'</span><span class=\"p\">,</span>\n <span class=\"n\">auth</span><span class=\"o\">=</span><span class=\"p\">(</span><span class=\"n\">api_key</span><span class=\"p\">,</span> <span class=\"n\">api_secret</span><span class=\"p\">),</span>\n <span class=\"n\">data</span><span class=\"o\">=</span><span class=\"p\">{</span><span class=\"s1\">'grant_type'</span><span class=\"p\">:</span> <span class=\"s1\">'client_credentials'</span><span class=\"p\">})</span>\n\n <span class=\"n\">bearer_token</span> <span class=\"o\">=</span> <span class=\"n\">r</span><span class=\"o\">.</span><span class=\"n\">json</span><span class=\"p\">()[</span><span class=\"s1\">'access_token'</span><span class=\"p\">]</span>\n\n <span class=\"k\">def</span> <span class=\"nf\">bearer_auth</span><span class=\"p\">(</span><span class=\"n\">req</span><span class=\"p\">):</span>\n <span class=\"n\">req</span><span class=\"o\">.</span><span class=\"n\">headers</span><span class=\"p\">[</span><span class=\"s1\">'Authorization'</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"s1\">'Bearer '</span> <span class=\"o\">+</span> <span class=\"n\">bearer_token</span>\n <span class=\"k\">return</span> <span class=\"n\">req</span>\n\n <span class=\"n\">session</span><span class=\"o\">.</span><span class=\"n\">auth</span> <span class=\"o\">=</span> <span class=\"n\">bearer_auth</span>\n <span class=\"k\">return</span> <span class=\"n\">session</span>\n</pre></div><h3>GitHub API</h3>\n<p>Podíváme se i na <a href=\"https://developer.github.com/v3\">GitHub API</a>, které má jednodušší autentizaci (od GitHubu přímo\nzískáte token). Stačí jít do <a href=\"https://github.com/settings/tokens\">nastavení</a> a vyrobit nový token\n(zatím není třeba zaškrtávat žádná oprávnění).\nToken je opět třeba patřičně chránit.</p>\n<p>Pomocí tokenu pak můžete z GitHubu získávat informace.\nTímto kódem lze například získat popis přihlášeného uživatele, tedy sebe sama.</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"n\">token</span> <span class=\"o\">=</span> <span class=\"s1\">'d7313dab254b7fd0d0f3ec3cbf754b3abce462d5'</span>\n<span class=\"gp\">>>> </span><span class=\"n\">session</span> <span class=\"o\">=</span> <span class=\"n\">requests</span><span class=\"o\">.</span><span class=\"n\">Session</span><span class=\"p\">()</span>\n<span class=\"gp\">>>> </span><span class=\"n\">session</span><span class=\"o\">.</span><span class=\"n\">headers</span> <span class=\"o\">=</span> <span class=\"p\">{</span><span class=\"s1\">'User-Agent'</span><span class=\"p\">:</span> <span class=\"s1\">'Python'</span><span class=\"p\">}</span>\n<span class=\"gp\">>>> </span><span class=\"k\">def</span> <span class=\"nf\">token_auth</span><span class=\"p\">(</span><span class=\"n\">req</span><span class=\"p\">):</span>\n<span class=\"gp\">... </span> <span class=\"n\">req</span><span class=\"o\">.</span><span class=\"n\">headers</span><span class=\"p\">[</span><span class=\"s1\">'Authorization'</span><span class=\"p\">]</span> <span class=\"o\">=</span> <span class=\"s1\">'token '</span> <span class=\"o\">+</span> <span class=\"n\">token</span>\n<span class=\"gp\">... </span> <span class=\"k\">return</span> <span class=\"n\">req</span>\n<span class=\"gp\">... </span>\n<span class=\"gp\">>>> </span><span class=\"n\">session</span><span class=\"o\">.</span><span class=\"n\">auth</span> <span class=\"o\">=</span> <span class=\"n\">token_auth</span>\n<span class=\"gp\">>>> </span><span class=\"n\">r</span> <span class=\"o\">=</span> <span class=\"n\">session</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s1\">'https://api.github.com/user'</span><span class=\"p\">)</span>\n<span class=\"gp\">>>> </span><span class=\"n\">r</span><span class=\"o\">.</span><span class=\"n\">json</span><span class=\"p\">()</span>\n</pre></div><div class=\"admonition note\"><p>Všimněte si hlavičky <code>User-Agent</code>. Ta je potřeba při komunikaci s GitHub API\nexplicitně nastavit. Nastavení na objektu session zajistí, že tato hlavička\nbude ve všech požadavcích.</p>\n</div><p>Pokud budete chtít něco provést, například dát hvězdičku repozitáři s těmito\nmateriály, musíte tokenu nastavit patřičné oprávnění\n(u hvězdičky je to <code>public_repo</code>).\nTo se dělá přes <a href=\"https://github.com/settings/tokens\">nastavení</a> na GitHubu.</p>\n<p>Hvězdičku pak přidáte takto:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"n\">r</span> <span class=\"o\">=</span> <span class=\"n\">session</span><span class=\"o\">.</span><span class=\"n\">put</span><span class=\"p\">(</span><span class=\"s1\">'https://api.github.com/user/starred/pyvec/naucse.python.cz'</span><span class=\"p\">)</span>\n<span class=\"gp\">>>> </span><span class=\"n\">r</span><span class=\"o\">.</span><span class=\"n\">text</span>\n<span class=\"go\">''</span>\n</pre></div><p>Jak vidíte, API nevrací žádný text (žádné tělo odpovědi).\nMůžete ale zkontrolovat návratový stav:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"n\">r</span><span class=\"o\">.</span><span class=\"n\">status_code</span>\n<span class=\"go\">204</span>\n</pre></div><p>Případně vyhodit výjimku, pokud je stavový kód divný (např <em>404 Nenalezeno</em>,\n<em>401 Chybí oprávnění</em> apod.):</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"n\">r</span><span class=\"o\">.</span><span class=\"n\">raise_for_status</span><span class=\"p\">()</span>\n</pre></div><p>Pokud hvězdičku chcete odebrat, použijte metodu DELETE.\nMy ale věříme, že ji odebrat nechcete :)</p>\n<p><a href=\"https://developer.github.com/v3/\">Dokumentace</a> ke GitHub API.</p>\n<h3>Chraňte své tokeny</h3>\n<p>Když ukládáte skript do gitu, mějte na paměti, že tokeny a klíče do něj nikdy\nnepatří. Můžete je uložit do konfiguračního souboru, který bude gitem ignorován,\nnapříklad takhle:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"k\">[twitter]</span>\n<span class=\"na\">key</span> <span class=\"o\">=</span> <span class=\"s\">D4HJp6PKmpon9eya1b2c3d4e5</span>\n<span class=\"na\">secret</span> <span class=\"o\">=</span> <span class=\"s\">rhvasRMhvbuHJpu4MIuAb4WO50gnoQa1b2c3d4e5f6g7h8i9j0</span>\n\n<span class=\"k\">[github]</span>\n<span class=\"na\">token</span> <span class=\"o\">=</span> <span class=\"s\">d7313dab254b7fd0d0f3ec3cbf754b3abce462d5</span>\n</pre></div><p>A následně konfiguraci načtete pomocí modulu\n<a href=\"https://docs.python.org/3/library/configparser.html\">configparser</a>:</p>\n<div class=\"highlight\"><pre><span></span><span class=\"gp\">>>> </span><span class=\"kn\">import</span> <span class=\"nn\">configparser</span>\n<span class=\"gp\">>>> </span><span class=\"n\">config</span> <span class=\"o\">=</span> <span class=\"n\">configparser</span><span class=\"o\">.</span><span class=\"n\">ConfigParser</span><span class=\"p\">()</span>\n<span class=\"gp\">>>> </span><span class=\"k\">with</span> <span class=\"nb\">open</span><span class=\"p\">(</span><span class=\"s1\">'auth.cfg'</span><span class=\"p\">)</span> <span class=\"k\">as</span> <span class=\"n\">f</span><span class=\"p\">:</span>\n<span class=\"gp\">... </span> <span class=\"n\">config</span><span class=\"o\">.</span><span class=\"n\">read_file</span><span class=\"p\">(</span><span class=\"n\">f</span><span class=\"p\">)</span>\n<span class=\"gp\">>>> </span><span class=\"n\">config</span><span class=\"p\">[</span><span class=\"s1\">'twitter'</span><span class=\"p\">][</span><span class=\"s1\">'key'</span><span class=\"p\">]</span>\n<span class=\"go\">D4HJp6PKmpon9eya1b2c3d4e5</span>\n</pre></div><p>Do souboru <code>.gitignore</code> pak musíte přidat název ignorovaného souboru, např.:</p>\n<div class=\"highlight\"><pre><code>auth.cfg\n\n</code></pre></div><p>Ověřte si, že git soubor <code>auth.cfg</code> opravdu ignoruje, t.j. soubor se neukáže\nve výstupu <code>git status</code>.</p>\n<p>Jelikož ostatní tento konfigurační soubor neuvidí,\nje vhodné jim vysvětlit, jak takový soubor (s jejich údaji) vytvořit.\nMůžete například vložit do gitu soubor <code>auth.cfg.sample</code>\ns vymyšlenými údaji, či příklad uvést v README.</p>\n\n\n "
}
}
}