Post von Python auf Facebook Timeline

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.

Verifizierte Umgebung

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

Quellcode

https://github.com/nmatsui/post_facebook_using_python

Erstellen einer Facebook-App

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".

fb_python_01.png

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".

fb_python_02.png

3 Wählen Sie eine Kategorie aus (diesmal ** Dienstprogramm **) und klicken Sie auf "App-ID erstellen".

fb_python_03.png

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".

fb_python_04.png

5 Abschluss der Erstellung der Facebook-Anwendung

fb_python_05.png

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

fb_python_06.png

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

fb_python_07.png

Konfigurationsdatei erstellen

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"
  }
}

Umweltvorbereitung

Jetzt, da wir eine Facebook-App haben, müssen wir eine Python-Umgebung vorbereiten.

Bibliotheksinstallation

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

Erstellen eines Verzeichnisses für CGI

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

Erstellen eines CGI-Programms

Dieses Mal werden wir die folgenden zwei CGIs erstellen

Berechtigungen für den Zugriff auf Token

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 zur Generierung der OAuth-Authentifizierungs-URL

** 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.

Anzeigevorlage für die OAuth-Authentifizierungs-URL

** 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.

Zugriff auf Token Acquisition CGI

** 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.

Zugriff auf die Token-Anzeigevorlage

** 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>

CGI-Programmbetrieb und Zugriffstokenerfassung

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 den CGI HTTP Server

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

Zugriffsindex

Greifen Sie über den Browser des PCs, auf dem CGIHTTPServer gestartet wird, auf die folgende URL zu.

http://localhost:8000/cgi-bin/index

fb_python_08.png

Authentifiziert mit OAuth

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.

fb_python_09.png

2 Überprüfen Sie den Buchungsbereich Geben Sie den Veröffentlichungsbereich an, den die Facebook-App in Ihrem Namen veröffentlicht.

fb_python_10.png

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.

fb_python_11.png

Zugriffstoken abrufen und anzeigen

CGI erhält das Zugriffstoken, speichert es in "token.json" und zeigt es auf dem Bildschirm an.

fb_python_12.png

token.json


{
  "token": {
    "page_access": "Erhaltenes Seitenzugriffstoken", 
    "user_access": "Erhaltenes User Acdess Token"
  }
}

Auf Facebook posten

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.

Python-Skript

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)

Poste auf deiner Timeline

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.

facebook_python_12.png

Posten auf der Timeline auf der Facebook-Seite

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.

fb_python_13.png

Schließlich

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

Post von Python auf Facebook Timeline
Post von Python nach Slack
[Lambda] [Python] Von Lambda auf Twitter posten!
Poste ein Bild von Python auf Tumblr
Änderungen von Python 3.0 zu Python 3.5
Änderungen von Python 2 zu Python 3.0
poste an vim → Python → Slack
Flirte von PHP nach Python
Post to Slack mit Python 3
Anaconda aktualisiert von 4.2.0 auf 4.3.0 (python3.5 aktualisiert auf python3.6)
Mit Python auf Twitter posten
Wechseln Sie von Python2.7 zu Python3.6 (centos7)
Stellen Sie von Python aus eine Verbindung zu SQLite her
Post an Slack in Python
POST-Nachrichten von Python an Slack über eingehenden Webhook
Versuchen Sie, Facebook mit Python zu betreiben
Stellen Sie von Python aus eine Verbindung zur utf8mb4-Datenbank her
Python (vom ersten Mal bis zur Ausführung)
So greifen Sie über Python auf Wikipedia zu
Python, um von einer anderen Sprache zu wechseln
Mit Python 3 einfach auf Twitter posten
[Nanonets] Wie poste ich Memo [Python]
Hat sich nicht von Python 2 auf 3 geändert
Aktualisieren Sie Mac Python von 2 auf 3
Senden Sie eine Nachricht von IBM Cloud Functions an Slack in Python
[Python] Fluidsimulation: Von linear zu nichtlinear
Von Python bis zur Verwendung von MeCab (und CaboCha)
So aktualisieren Sie Google Sheets von Python
Privates Python-Handbuch (von Zeit zu Zeit aktualisiert)
Ich möchte ein Glas aus Python verwenden
Konvertieren Sie von Katakana zu Vokal Kana [Python]
Push-Benachrichtigung vom Python-Server an Android
Herstellen einer Verbindung von Python zu MySQL unter CentOS 6.4
Portieren und Ändern des Doublet-Solvers von Python2 auf Python3.
Zugriff auf RDS von Lambda (Python)
Python> Ausgaben von 1 bis 100, 501 bis 600> Für CSV
In Python von Markdown in HTML konvertieren
[Amazon Linux] Wechsel von der Python 2-Serie zur Python 3-Serie
API-Erklärung zum Berühren von Mastodon aus Python
Stellen Sie von Python aus eine Verbindung zur Websocket-API von coincheck her
Auf Python 2.7.9 aktualisiert
Summe von 1 bis 10
SQL zu SQL
MeCab von Python
"Backport" zu Python 2
Senden Sie eine Nachricht von Slack an einen Python-Server
Bearbeiten Sie Excel in Python, um eine Pivot-Tabelle zu erstellen
So öffnen Sie einen Webbrowser über Python
Studie aus Python Hour7: Verwendung von Klassen
[Python] Konvertieren von DICOM in PNG oder CSV
Excel-Datei aus Python importieren (in DB registriert)
Ich möchte mit Python eine E-Mail von Google Mail senden.
[Python] Ich möchte 7DaysToDie von Discord aus verwalten! 1/3
Von der Datei zur Diagrammzeichnung in Python. Grundstufe Grundstufe
[Erster Beitrag] Frage ・ Wie man Python ausfegt
[Python] Lesen von Daten aus CIFAR-10 und CIFAR-100
[Python] Erstellen Sie eine Tabelle von Pandas DataFrame zu Postgres
[Bash] Holen Sie sich die Kraft von Python aus Bash mithilfe der folgenden Dokumentation
So generieren Sie ein Python-Objekt aus JSON