Poste von Python zu dir selbst oder zur Timeline auf deiner Facebook-Seite.
Leider verfügt Facebook nicht über einen eingehenden Webhook-Mechanismus, sodass Sie eine Facebook-App zum Posten erstellen müssen.
Außerdem sind Zugriffstoken erforderlich, um Facebook zu betreiben. Es ist jedoch schwierig, Zugriffstoken von CLI zu erhalten, da Facebook eine OAuth-Authentifizierung erfordert (obwohl dies nicht unmöglich ist, wenn Sie die Antwort mit einem kopflosen Browser analysieren).
Dieses Mal starte ich den CGI-Server mit Python auf localhost und verarbeite den OAuth-Rückruf mit CGI, um das Zugriffstoken zu erhalten.
Ich wollte in der Facebook-Gruppe posten können, habe diesmal aber leider aufgegeben, da der Facebook-Betreiber die Facebook-Anwendung anscheinend genehmigen muss.
version | |
---|---|
OS | Ubuntu 15.04 (3.19.0-26-generic) |
Python | 2.7.10 |
pip | 7.1.2 |
requests | 2.8.1 |
jinja2 | 2.8 |
facebook-sdk | 0.4.0 |
facebook graph API | 2.5 |
https://github.com/nmatsui/post_facebook_using_python
Erstellen Sie zunächst eine Facebook-App.
1 Zeigen Sie im Facebook-Entwicklerportal https://developers.facebook.com/ "Neue App hinzufügen" an und wählen Sie "Website".
2 Geben Sie den Namen der Facebook-App ein, die Sie erstellen möchten (diesmal ** python_publisher **), und klicken Sie auf "Neue Facebook-App-ID erstellen".
3 Wählen Sie eine Kategorie aus (diesmal ** Dienstprogramm **) und klicken Sie auf "App-ID erstellen".
4 Geben Sie die URL für den Authentifizierungsrückruf mit OAuth ein (diesmal ** http: // localhost: 8000 / cgi-bin / get_token **) und klicken Sie auf "Weiter".
5 Abschluss der Erstellung der Facebook-Anwendung
6 Zeigen Sie die Top Page des Entwicklerportals erneut an und wählen Sie die aus "Meine Apps" erstellte App aus.
Wenn Sie die von Ihnen erstellte App nicht sehen, laden Sie das Entwicklerportal neu
7 Überprüfen Sie die App-ID und das App-Geheimnis
Möglicherweise werden Sie beim Überprüfen des App-Geheimnisses zur Eingabe eines Kennworts aufgefordert
Erstellen Sie eine Einstellungsdatei, die die Informationen der erstellten Facebook-Anwendung und die Informationen der zu veröffentlichenden Facebook-Seite beschreibt. Zur Vereinfachung des CGI-Programms wird der Name der Einstellungsdatei als ** conf.json ** festgelegt.
conf.json
{
"app": {
"app_id": "Facebook App App ID",
"app_secret": "Facebook App App Geheimnis",
"redirect_uri": "Rückruf-URL in der Facebook-App festgelegt"
},
"page": {
"name": "Der Name der Facebook-Seite, die gepostet werden soll"
}
}
Jetzt, da wir eine Facebook-App haben, müssen wir eine Python-Umgebung vorbereiten.
Erstellen Sie die Datei require.txt am selben Speicherort wie conf.json und installieren Sie die folgenden drei Bibliotheken mit pip.
requirements.txt
requests
jinja2
facebook-sdk
Mit pip installieren
$ pip install -r requirements.txt
Platzieren Sie das CGI-Programm in dem Verzeichnis, in dem conf.json abgelegt ist. ** Erstellen Sie das Verzeichnis cgi-bin ** und das Verzeichnis ** templates **, in dem sich die jinja2-Vorlage befindet.
Verzeichnis erstellen
$ mkdir cgi-bin
$ mkdir templates
Dieses Mal werden wir die folgenden zwei CGIs erstellen
Geben Sie diesmal die folgenden drei Berechtigungsbereiche an. Weitere Informationen zu den Berechtigungen, die angegeben werden können, finden Sie unter Berechtigungsreferenz - Facebook-Anmeldung.
Standardmäßig erhält das Zugriffstoken die Berechtigung ** public_profile ** (Berechtigung zum Abrufen eines öffentlichen Profils), sodass das diesmal erworbene Zugriffstoken innerhalb dieser vier Berechtigungsbereiche ausgeführt werden kann.
index Generieren Sie eine OAuth-Authentifizierungs-URL für die Facebook-App und zeigen Sie den Link in Ihrem Browser an.
** cgi-bin / index ** liest conf.json und generiert eine OAuth-Authentifizierungs-URL im folgenden Format.
https://www.facebook.com/dialog/oauth?redirect_uri= <Rückruf-URL für Facebook-App & client_id = <App-ID der Facebook-App> & scope = <Berechtigung zur Erteilung der Genehmigung>
cgi-bin/index
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import json
import urllib
from jinja2 import Environment, FileSystemLoader
CONF_FILE = 'conf.json'
BASE_URL = 'https://www.facebook.com/dialog/oauth'
SCOPE = 'manage_pages,publish_actions,publish_pages'
TPL_DIR = './templates'
TEMPLATE = 'index.tpl.html'
def create_url():
with open(CONF_FILE, 'r') as f:
conf = json.load(f)
redirect_uri = urllib.quote_plus(conf['app']['redirect_uri'])
url = BASE_URL + '?'
url += 'redirect_uri=' + redirect_uri + '&'
url += 'client_id=' + conf['app']['app_id'] + '&'
url += 'scope=' + SCOPE
return url
def main():
params = {}
try:
url = create_url()
params['isOK'] = True
params['url'] = url
except Exception as e:
params['isOK'] = False
params['error_type'] = type(e).__name__
params['error_title'] = str(e)
env = Environment(loader=FileSystemLoader(TPL_DIR, encoding='utf-8'))
tpl = env.get_template(TEMPLATE)
html = tpl.render(params)
print('Content-type: text/html')
print('\n')
print(html.encode('utf-8'))
main()
Da die Rückruf-URL nicht wie sie ist als URL-Parameter übergeben werden kann, wird sie mit "urllib.quote_plus ()" maskiert.
** templates / index.tpl.html ** zeigt die generierte URL als Link an.
html+jinja:templates/index.tpl.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>index</title>
</head>
<body>
{% if isOK %}
<a href="{{ url }}">get token</a>
{% else %}
<b>Ich habe den folgenden Fehler erhalten</b><br/>
[{{ error_type }}] {{ error_title }}
{% endif %}
</body>
</html>
get_token Von der OAuth-Authentifizierungsfunktion von Facebook zurückgerufen und der Authentifizierungscode abgerufen. Beziehen Sie das folgende Zugriffstoken mithilfe des Authentifizierungscodes von der Facebook-API und speichern Sie es als JSON-Datei.
** cgi-bin / get_token ** ruft das Seitenzugriffstoken der Facebook-Seite ab, das als Benutzerzugriffstoken unter Verwendung des zurückgerufenen Autorisierungscodes angegeben wurde. Das erworbene Zugriffstoken wird in token.json gespeichert.
cgi-bin/get_token
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import cgi
import json
import re
import requests
from jinja2 import Environment, FileSystemLoader
CONF_FILE = 'conf.json'
TOKEN_FILE = 'token.json'
TOKEN_URL = 'https://graph.facebook.com/oauth/access_token'
ACCOUNT_URL = 'https://graph.facebook.com/me/accounts'
USER_ACCESS_TOKEN_PATTERN = r'access_token=([^&=]+)(&expires=\d+)?'
TPL_DIR = './templates'
TEMPLATE = 'get_token.tpl.html'
class TokenRetriever(object):
def __init__(self, code):
self.code = code
with open(CONF_FILE, 'r') as f:
self.conf = json.load(f)
def get_token(self):
user_access_token = self.__get_user_access_token()
page_access_token = self.__get_page_access_token(user_access_token)
token = {}
token['user_access'] = user_access_token
token['page_access'] = page_access_token
token_json = json.dumps({'token': token}, indent=2, sort_keys=True)
return token_json
def __get_user_access_token(self):
payload = {}
payload['client_id'] = self.conf['app']['app_id']
payload['client_secret'] = self.conf['app']['app_secret']
payload['redirect_uri'] = self.conf['app']['redirect_uri']
payload['code'] = self.code
response = requests.get(TOKEN_URL, params=payload)
m = re.match(USER_ACCESS_TOKEN_PATTERN, response.text)
if m:
return self.__exchange_token(m.group(1))
else:
raise LookupError('access_token does not exist')
def __get_page_access_token(self, user_access_token):
payload = {}
payload['access_token'] = user_access_token
response = requests.get(ACCOUNT_URL, params=payload)
pages = filter(lambda p: p['name'] == self.conf['page']['name'],
json.loads(response.text)['data'])
page_access_token = pages[0]['access_token']
return self.__exchange_token(page_access_token)
def __exchange_token(self, token):
payload = {}
payload['client_id'] = self.conf['app']['app_id']
payload['client_secret'] = self.conf['app']['app_secret']
payload['grant_type'] = 'fb_exchange_token'
payload['fb_exchange_token'] = token
response = requests.get(TOKEN_URL, params=payload)
m = re.match(USER_ACCESS_TOKEN_PATTERN, response.text)
if m:
return m.group(1)
else:
raise LookupError('access_token does not exist')
def main():
params = {}
try:
form = cgi.FieldStorage()
if not form.has_key('code'):
raise LookupError('QueryString "code" does not exist')
token_retriever = TokenRetriever(form['code'].value)
token_json = token_retriever.get_token()
with open(TOKEN_FILE, 'w') as f:
f.write(token_json)
params['isOK'] = True
params['token_file'] = TOKEN_FILE
params['token_json'] = token_json
except Exception as e:
params['isOK'] = False
params['error_type'] = type(e).__name__
params['error_title'] = str(e)
env = Environment(loader=FileSystemLoader(TPL_DIR, encoding='utf-8'))
tpl = env.get_template(TEMPLATE)
html = tpl.render(params)
print('Content-type: text/html; charset=utf-8')
print('\n')
print(html.encode('utf-8'))
main()
Die "Anfragen" -Bibliothek wird verwendet, um die REST-API von Facebook zu verwenden. Das Facebook-Benutzerzugriffstoken läuft normalerweise 1 bis 2 Stunden nach dem Erwerb ab. Das war ein mühsamer Test, daher habe ich die REST-API der Access Token Extension verwendet, um sie gegen Token auszutauschen, die 60 Tage gültig sind.
** templates / get_token.tpl.html ** zeigt das erworbene Zugriffstoken an.
html+jinja:templates/get_token.tpl.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>get_token</title>
</head>
<body>
{% if isOK %}
<b>User Access Token</b>Wann<b>Page Access Token</b>Ich habe.</br>
Token haben das folgende JSON-Format{{ token_file }}Ich habe es geschrieben.
<pre>{{ token_json }}</pre>
{% else %}
<b>Der folgende Fehler ist aufgetreten:</b><br/>
[{{ error_type }}] {{ error_title }}
{% endif %}
</body>
</html>
Lassen Sie uns nun CGI ausführen und ein Zugriffstoken erhalten. Da dies eine Überprüfung ist, wird httpd wie nginx und apache nicht verwendet, und stattdessen wird der CGIHTTPServer von python2.7 verwendet.
Starten Sie CGI HTTP Server mit dem folgenden Befehl aus dem Verzeichnis, das das Verzeichnis conf.json, cgi-bin und templates enthält.
Starten Sie den CGI HTTP Server
$ python -m CGIHTTPServer
Greifen Sie über den Browser des PCs, auf dem CGIHTTPServer gestartet wird, auf die folgende URL zu.
http://localhost:8000/cgi-bin/index
Wenn Sie auf "get_token" klicken, wird die Facebook-App authentifiziert und Sie werden aufgefordert, die Berechtigungen zu genehmigen.
1 Überprüfen der dem Benutzer erteilten Berechtigung Überprüfen Sie die zu genehmigende Berechtigung. Da diese Facebook-App nicht genehmigt wurde, wird eine Warnung angezeigt, die besagt, dass einige der Berechtigungen, z. B. das Schreiben an die Gruppe, ungültig wurden.
2 Überprüfen Sie den Buchungsbereich Geben Sie den Veröffentlichungsbereich an, den die Facebook-App in Ihrem Namen veröffentlicht.
3 Berechtigungsprüfung für Facebook-Seite Überprüfen Sie die Verwaltungs- und Veröffentlichungsberechtigung der Facebook-Seite. Es gibt keine Warnung zum Posten auf der Facebook-Seite, auch nicht für nicht genehmigte Apps.
CGI erhält das Zugriffstoken, speichert es in "token.json" und zeigt es auf dem Bildschirm an.
token.json
{
"token": {
"page_access": "Erhaltenes Seitenzugriffstoken",
"user_access": "Erhaltenes User Acdess Token"
}
}
Nachdem ich das Zugriffstoken habe, werde ich es von Python auf Facebook veröffentlichen. Sie können die REST-API von Facebook direkt bedienen, diesmal verwenden wir jedoch Facebook SDK für Python.
Holen Sie sich und den Endpunkt der Facebook-Seite mit dem SDK und greifen Sie auf das Token zu und schreiben Sie eine Nachricht. Beachten Sie, dass sich die Schreibmethode zwischen Ihrer Zeitleiste und der Zeitleiste der Facebook-Seite unterscheidet.
post.py
#!/usr/bin/env python
# -*- encode: utf-8 -*-
import sys
import json
import facebook
class Timeline:
def __init__(self, token_file):
with open(token_file, 'r') as f:
token = json.load(f)['token']
self.user_endpoint = facebook.GraphAPI(token['user_access'])
self.page_endpoint = facebook.GraphAPI(token['page_access'])
def post_me(self, msg):
self.user_endpoint.put_object('me', 'feed', message=msg)
print('posted to my timeline: %s' % msg)
def post_page(self, msg):
self.page_endpoint.put_wall_post(message=msg)
print('posted to page timeline: %s' % msg)
if __name__ == '__main__':
if len(sys.argv) != 4:
print('usage: %s token_file [me|page] message' % sys.argv[0])
exit(1)
try:
timeline = Timeline(sys.argv[1])
if sys.argv[2] == 'me':
timeline.post_me(sys.argv[3])
elif sys.argv[2] == 'page':
timeline.post_page(sys.argv[3])
else:
print '%s is invalid' % sys.argv[2]
except (IOError, facebook.GraphAPIError) as e:
print e
exit(9)
Versuchen Sie, auf Ihrer Timeline zu posten.
Poste auf deiner Timeline
$ ./post.py token.json me "Testbeitrag. Dies ist ein Test eines Beitrags aus einem Python-Skript."
posted to my timeline:Testbeitrag. Dies ist ein Test eines Beitrags aus einem Python-Skript.
Ich werde es auf der Timeline der Facebook-Seite veröffentlichen, die für dieses Experiment erstellt wurde.
$ ./post.py token.json page "Testbeitrag. Dies ist ein Test eines Beitrags aus einem Python-Skript."
posted to page timeline:Testbeitrag. Dies ist ein Test eines Beitrags aus einem Python-Skript.
Ich wollte nur von Python auf Facebook posten, aber es war ein sehr langer Weg, aber ich konnte sicher auf meiner Timeline und der Timeline der Facebook-Seite posten. Wird Facebook auch einen eingehenden Webhook vorbereiten?
Recommended Posts