Skip to content

Commit e432659

Browse files
committed
MI-PYT: Ditch Twitter API
Fixes: #453
1 parent 9b4622b commit e432659

File tree

3 files changed

+46
-140
lines changed

3 files changed

+46
-140
lines changed

lessons/intro/deployment/pythonanywhere.md

-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@ a editovat ve webové konzoli.
9797
> [note]
9898
> Doporučujeme pro tyto potřeby stejně raději nepoužívat API klíče
9999
> k vlastním účtům, raději si vyrobte nějaké účty pouze pro tento účel.
100-
> Twitter vyžaduje před vydáním API klíčů zadání a potvrzení telefonního čísla.
101100
> GitHub povoluje všem vytvořit si jeden účet pro automatické operace, ale
102101
> takový účet musí mít napsané v popisu, že je robot.
103102

lessons/intro/requests/index.md

+45-138
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ Password:
4040
{'avatar_url': 'https://avatars.githubusercontent.com/u/2401856?v=3', ...}
4141
```
4242

43+
> [note]
44+
> Tento příklad pracuje přímo se jménem a heslem.
45+
> To se většinou nedělá a webové API to často ani nepodporují.
46+
> Pokud na GitHub používáte dvoufaktorovou autentizaci, příklad nebude fungovat.
47+
4348
Příklady použití pro další HTTP metody najdete v [dokumentaci].
4449

4550
[dokumentaci]: http://docs.python-requests.org/en/master/user/quickstart/
@@ -73,140 +78,23 @@ k testování HTTP dotazů:
7378
{'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'}}
7479
```
7580

76-
## Twitter API
77-
78-
Pro reálné použití si ukážeme, jak se dá pomocí requests získat seznam tweetů.
79-
Nebudeme samozřejmě nic parsovat z HTML stránek, ale použijeme [API Twitteru].
80-
81-
```pycon
82-
>>> r = session.get('https://api.twitter.com/1.1/search/tweets.json')
83-
>>> r.json()
84-
{'errors': [{'code': 215, 'message': 'Bad Authentication data.'}]}
85-
```
86-
87-
Jak můžete vidět v odpovědi, Twitter API neumožňuje data číst bez autentizace.
88-
Jak se autentizovat byste při troše hledání našli v dokumentaci, ale protože
89-
tu nevyučujeme úvod do OAuthu, ale Python, rozhodli jsme se vám to zjednodušit.
81+
## GitHub API
9082

91-
Nemáte-li na Twitter účet, vytvořte si ho. Můžete vytvořit nějaký *dummy* účet,
92-
který dál nebudete používat. Budete ale potřebovat ověřitelné telefonní číslo.
93-
94-
Po přihlášení na Twitter jděte na [apps.twitter.com] a vytvořte aplikaci
95-
(URL si můžete vymyslet, třeba `http://invalid`).
96-
Po vytvoření najdete na kartě *Keys and Access Tokens* **API Key** a **API Secret**.
97-
Pozor, jedná se prakticky o hesla k vašemu Twitter účtu,
98-
a proto by je nikdo kromě vás neměl vidět.
83+
Podíváme se teď, podobně jako v úvodním příkladu, na [GitHub API],
84+
které má poměrně jednoduchou autentizaci (od GitHubu přímo
85+
získáte token). Stačí jít do [nastavení] a vyrobit nový token
86+
(zatím není třeba zaškrtávat žádná oprávnění).
9987

10088
> [warning] Ochrana přihlašovacích tokenů
101-
> Ještě jednou – *API Key* a *API Secret* se chovají jako hesla.
102-
> Nikomu je nesmíte ukazovat!
103-
> Stane-li se přesto, že se k nim dostane někdo nepovolaný, na kartě
104-
> *Keys and Access Tokens* je můžete zrušit.
89+
> Váš token je něco jako vaše heslo.
90+
> Nikomu je nesmíte ukazovat a nesmíte jej dát do Gitu.
91+
> Stane-li se přesto, že se k němu dostane někdo nepovolaný,
92+
> můžete jej v [nastavení] opět smazat.
10593
106-
Prozatím klíče nastavte do proměnných, později je schováme například do
94+
Pomocí tokenu můžete z GitHubu získávat informace.
95+
Prozatím token nastavte do proměnné, později jej schováme například do
10796
konfiguračního souboru.
10897

109-
```pycon
110-
>>> api_key = 'D4HJp6PKmpon9eya1b2c3d4e5'
111-
>>> api_secret = 'rhvasRMhvbuHJpu4MIuAb4WO50gnoQa1b2c3d4e5f6g7h8i9j0'
112-
```
113-
114-
Pomocí těchto kódů je potřeba si od Twitter API vyžádat přístupový token.
115-
Používá se k tomu běžné HTTP přihlášení ([HTTP Basic authentication]),
116-
kde je `api_key` použit jako uživatelské jméno a `api_secret` jako heslo.
117-
118-
Pro běžné HTTP přihlášení se v knihovně requests používá
119-
`requests.auth.HTTPBasicAuth`:
120-
121-
[HTTP Basic authentication]: https://cs.wikipedia.org/wiki/Basic_access_authentication
122-
123-
```pycon
124-
>>> r = session.post('https://api.twitter.com/oauth2/token',
125-
auth=requests.auth.HTTPBasicAuth(api_key, api_secret),
126-
data={'grant_type': 'client_credentials'})
127-
>>>
128-
>>> r.json()
129-
{'token_type': 'bearer', 'access_token': 'AAAAAAAAAAAAAAAAAAAAAHhKXAAAAAAAaA1abB2bcC3cdD4deE5efF6fgG7ghH8hiI9ijJ0ja1b2c3d4e5f6g7h8i9j0a1b2c3d4e5f6g7h8i9j0'}
130-
>>> bearer_token = r.json()['access_token']
131-
```
132-
133-
Parametr `auth` v příkladu výše je autentizační funkce, která nějakým způsobem
134-
modifikuje HTTP požadavek za účelem autentizace, většinou přidává specifické
135-
hlavičky.
136-
`requests.auth.HTTPBasicAuth` zde dle specifikace zakóduje jméno a heslo pomocí
137-
algoritmu base64 a přidá hlavičku `Authorization`.
138-
139-
Základní HTTP přihlášení je tak běžné, že pro něj Requests mají zkratku –
140-
místo `HTTPBasicAuth` se dá použít jen dvojice (jméno, heslo):
141-
142-
```pycon
143-
>>> r = session.post('https://api.twitter.com/oauth2/token',
144-
auth=(api_key, api_secret),
145-
data={'grant_type': 'client_credentials'})
146-
```
147-
148-
Pro další komunikaci s Twitter API je nutné přidat hlavičku se získaným tokenem.
149-
Jelikož používáte session, není nutné to dělat u každého požadavku zvlášť,
150-
ale je možné nastavit autentizační funkci pro celou session.
151-
152-
```pycon
153-
>>> def bearer_auth(req):
154-
... req.headers['Authorization'] = 'Bearer ' + bearer_token
155-
... return req
156-
...
157-
>>> session.auth = bearer_auth
158-
```
159-
160-
Pak už by mělo API fungovat.
161-
Použijeme [API pro vyhledávání tweetů][Search API]:
162-
163-
```pycon
164-
>>> r = session.get(
165-
... 'https://api.twitter.com/1.1/search/tweets.json',
166-
... params={'q': '#python'},
167-
... )
168-
>>> for tweet in r.json()['statuses']:
169-
... print(tweet['text'])
170-
...
171-
Once a framework decides to abstract the HTML layer from you. Customizing your UI becomes sorcery. #django #Python
172-
...
173-
```
174-
175-
Zde je pro zjednodušení k dispozici celá funkce pro vytvoření autentizované
176-
*session*:
177-
178-
```python
179-
import requests
180-
181-
def twitter_session(api_key, api_secret):
182-
session = requests.Session()
183-
184-
r = session.post('https://api.twitter.com/oauth2/token',
185-
auth=(api_key, api_secret),
186-
data={'grant_type': 'client_credentials'})
187-
188-
bearer_token = r.json()['access_token']
189-
190-
def bearer_auth(req):
191-
req.headers['Authorization'] = 'Bearer ' + bearer_token
192-
return req
193-
194-
session.auth = bearer_auth
195-
return session
196-
```
197-
198-
[API Twitteru]: https://dev.twitter.com/rest/public
199-
[apps.twitter.com]: https://apps.twitter.com/
200-
[Search API]: https://developer.twitter.com/en/docs/tweets/search/api-reference/get-search-tweets.html
201-
202-
### GitHub API
203-
204-
Podíváme se i na [GitHub API], které má jednodušší autentizaci (od GitHubu přímo
205-
získáte token). Stačí jít do [nastavení] a vyrobit nový token
206-
(zatím není třeba zaškrtávat žádná oprávnění).
207-
Token je opět třeba patřičně chránit.
208-
209-
Pomocí tokenu pak můžete z GitHubu získávat informace.
21098
Tímto kódem lze například získat popis přihlášeného uživatele, tedy sebe sama.
21199

212100
```pycon
@@ -222,9 +110,33 @@ Tímto kódem lze například získat popis přihlášeného uživatele, tedy se
222110
>>> r.json()
223111
```
224112

113+
Funkce `session.auth` v příkladu výše je autentizační funkce,
114+
která nějakým způsobem modifikuje HTTP požadavek za účelem autentizace,
115+
většinou přidává specifické hlavičky (jak je tomu i zde).
116+
Lze ji nastavit buďto na celé session nebo předat argumentem `auth` s každým
117+
požadavkem.
118+
119+
Existují předpřipravené funkce v modulu `requests.auth`, například
120+
`requests.auth.HTTPBasicAuth` provádí základní HTTP přihlášení.
121+
Dle specifikace zakóduje jméno a heslo pomocí
122+
algoritmu base64 a přidá hlavičku `Authorization`.
123+
124+
[Základní HTTP přihlášení](https://cs.wikipedia.org/wiki/Basic_access_authentication)
125+
je tak běžné, že pro něj Requests mají zkratku –
126+
místo `HTTPBasicAuth` se dá použít i dvojice (jméno, heslo):
127+
128+
```pycon
129+
>>> requests.get('https://httpbin.org/basic-auth/AzureDiamond/hunter2',
130+
auth=requests.auth.HTTPBasicAuth('AzureDiamond', 'hunter2'))
131+
>>>
132+
>>> requests.get('https://httpbin.org/basic-auth/AzureDiamond/hunter2',
133+
auth=('AzureDiamond', 'hunter2'))
134+
```
135+
225136
> [note]
226-
> Všimněte si hlavičky `User-Agent`. Ta je potřeba při komunikaci s GitHub API
227-
> explicitně nastavit. Nastavení na objektu session zajistí, že tato hlavička
137+
> Všimněte si také hlavičky `User-Agent`.
138+
> Ta je potřeba při komunikaci s GitHub API explicitně nastavit.
139+
> Nastavení na objektu session zajistí, že tato hlavička
228140
> bude ve všech požadavcích.
229141
230142
Pokud budete chtít něco provést, například dát hvězdičku repozitáři s těmito
@@ -264,18 +176,13 @@ My ale věříme, že ji odebrat nechcete :)
264176
[Dokumentace]: https://developer.github.com/v3/
265177
[GitHub API]: https://developer.github.com/v3
266178

267-
268-
### Chraňte své tokeny
179+
## Chraňte své tokeny
269180

270181
Když ukládáte skript do gitu, mějte na paměti, že tokeny a klíče do něj nikdy
271182
nepatří. Můžete je uložit do konfiguračního souboru, který bude gitem ignorován,
272183
například takhle:
273184

274185
```ini
275-
[twitter]
276-
key = D4HJp6PKmpon9eya1b2c3d4e5
277-
secret = rhvasRMhvbuHJpu4MIuAb4WO50gnoQa1b2c3d4e5f6g7h8i9j0
278-
279186
[github]
280187
token = d7313dab254b7fd0d0f3ec3cbf754b3abce462d5
281188
```
@@ -288,8 +195,8 @@ A následně konfiguraci načtete pomocí modulu
288195
>>> config = configparser.ConfigParser()
289196
>>> with open('auth.cfg') as f:
290197
... config.read_file(f)
291-
>>> config['twitter']['key']
292-
D4HJp6PKmpon9eya1b2c3d4e5
198+
>>> config['github']['token']
199+
'd7313dab254b7fd0d0f3ec3cbf754b3abce462d5'
293200
```
294201

295202
Do souboru `.gitignore` pak musíte přidat název ignorovaného souboru, např.:

lessons/intro/testing/index.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,7 @@ def client(betamax_session):
524524
```
525525
526526
Co když ale nevíme, jak bude vypadat citlivá část požadavku, protože se teprve
527-
někde spočítá a získá, jako v případě Twitter API?
527+
někde spočítá a získá, jako například v případě Twitter API?
528528
Na tuto otázku podrobněji odpovídá
529529
[dokumentace](https://betamax.readthedocs.io/en/latest/configuring.html#filtering-sensitive-data).
530530

0 commit comments

Comments
 (0)