Meine kleine Datensicherungssoftware für Twitter, Twacbak muss dringend aktualisiert werden: die Benutzerauthentifizierung mittels Name und Kennwort (“Basic Authentication”) wird zum 30.06.2010 abgeschaltet. Statt dessen soll das OAuth-Protokoll verwendet werden, bei dem Name und Kennwort nur durch Twitter selbst verwaltet werden und Benutzer einzelnen Anwendungen das Recht geben, auf ihre Daten bei Twitter zuzugreifen. An sich eine gute Idee, da keine Kennworte mehr bei externen Anwendungen gespeichert werden.

Twacbak nutzt noch das bisherige Verfahren, bei dem über HTTP Basic Authentication Name und Kennwort mittels Base64 verscheiert übertragen werden. Dabei beruhigt höchstens die mögliche Übertragung per SSL. Das Modul zur direkten Kommunikation habe ich nicht selbst entwickelt. Statt dessen passte ich die Python Twitter Tools (PTT) an meine Bedüfnisse an.

Der 30.06.2010 näherte sich, besonders letzte Woche. Der Author der PTT scheint gerade OAuth zu implementieren, aber ob er bis zum 30.06.2010 fertig wird, bleibt offen. Und dann bräuchte ich ja noch Zeit, die Änderungen in Twacbak zu integrieren. Eine einfache Risikoabschätzung zeigt: besser etwas anderes.

OAuth ist kein triviales Protokoll. Es gibt für die unterschiedlichsten Szenarien Möglichkeiten der Anbindung. In den meisten Beispielen wird davon ausgegangen, dass die Anwendung, die auf Twitter zugreifen möchte, selbst eine für jeden zugänglich Webanwendung ist. Twacbak ist aktuell eine reine Konsolenanwendung. Und selbst wenn Twacbak einmal eine Webanwendung wird, würde es bei mir nur im lokalen Netz laufen.

Das ist die Situation: Twacbak muss bis Ende Juni 2010 an OAuth angepasst werden, OAuth ist ein komplexes Protokoll, mein bisheriges Modul zur Kommunikation mit Twitter unterstützt kein OAuth.

Mitte November 2009 stolperte ich über Tweepy. Damals war es nicht besonders ausgereift, kein Vergleich zu PTT. Zum Glück hatte ich es in meinem Brain einsortiert und schaute es mir letzte Woche noch einmal im Detail an. Etwas anders aufgebaut als PTT unterstützt es nun recht ausgereift OAuth.

Bleibt das Problem, wie man sich in einer Konsolenanwendung bei Twitter über OAuth authentifiziert. Die Beispiele im Web gaben nicht viel her. Ein wenig herumexperimentieren, Python’s REPL half immens, kam heraus, dass es recht einfach ist:

auth = tweepy.auth.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth_url = auth.get_authorization_url()
webbrowser.open(auth_url)
pin = getline('Enter PIN: ').strip()
if pin:
    access_token = auth.get_access_token(pin)
    # sichere access_token.key und access_token.secret für zukünftige
    # Zugriffe, z.B. in einer Datenbank

Die Werte für CONSUMER_KEY und CONSUMER_SECRET erhält man nach der Registrierung einer Anwendung bei Twitter. Mittels get_authorization_url() erhält man von Twitter eine URL, unter der ein Benutzer die Anwendung authorisieren kann. Nach der Authorisierung erhält der Benutzer auf der Webseite eine PIN, die er dann in der Konsolenanwendung angeben muss. Diese dient dazu, dass die Anwendung über Twitter ein sog. Access Token erhält. Damit authentifiziert sich die Anwendung später gegenüber Twitter. Das Access Token ist benutzer- und anwendungsspezifisch und damit wesentlich sicherer als ein Kennwort.

Der spätere Zugriff ist dann wieder einfach:

auth = tweepy.auth.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
# lese key und secret aus Datenbank
auth.set_access_token(key, secret)
api = tweepy.API(auth, parser=tweepy.parsers.JSONParser())

Über das Objekt api können dann die Methoden der Twitter-API authentifiziert aufgerufen werden. Fertig.

Fertig? Nein. Tweepy hat eine leicht andere Philosophie als PTT. Aber zum Glück ist Python nicht statisch typisiert. Sonst hätte ein Großteil von Twacbak angepasst werden müssen (Ja, ich weiß: geringere Kopplung …). Dank Duck Typing, eines der besonders angenehmen Merkmale von Python, und der guten Konfigurierbarkeit Tweepy’s musste ich nur einige wenige Stellen anpassen. Nach kurzer Zeit war ich dann wirklich fertig mit der Umstellung.

Twacbak arbeitet nun mindestens so gut wie vorher. Subjektiv scheint es sogar schneller mit Twitter zu kommunizieren. Aber das kann auch daran liegen, dass Twitter die Kommunikation mittels OAuth bevorzugt abwickeln könnte.

Jetzt kann ich wieder in Ruhe darüber nachdenken, wie sich Twacbak weiter entwickeln soll. Vermutlich in Richtung Webanwendung ;-)

, , , ,

Lange habe ich mich schon um die Anforderungen zu Twacbak herumgedrückt. Im
Kopf waren Sie schon, aber nicht zu Papier. Und, als weitere Ausrede, musste
ich erst einmal ausprobieren, was die Twitter-API so alles hergibt. Damit bin ich nun soweit fertig, einen ersten Prototyp habe ich auch schon.

Also, was sind (meine) Anforderungen?

Funktionalität

  • Sichern aller grundlegenden Daten eines Twitter-Accounts, wie:
    • Benutzerdaten (Name, Location, eigene URL, Bio, … so wie sie im Profile / Setting angegeben werden),
    • alle eigene Tweets,
    • Favorites,
    • gesendete Nachrichten,
    • empfangene Nachrichten,
    • Liste der Friends, d.h. der Accounts, denen man folgt,
    • Liste der Follower, d.h. die Account, die einem folgen.
  • Sichern von nützlichen Zusatzinformationen:
    • Wann ist mir wer gefolgt, wann hat er mich aus seiner Liste gelöscht?
    • Wann bin ich jemanden gefolgt, wann habe ich das Verfolgen aufgegeben?
    • Was haben meine Friends so getwittert?
    • Wenn jemanden eine Antwort getwittert hat, auf welchen Tweet welchen Benutzers bezog sich diese Antwort?
  • Die gesammelten Daten sollen auf den Bildschirm / in eine Datei ausgegeben werden können.
  • Darüber hinaus sollen folgende Berichte (Bildschirm / Datei) ausgegeben werden:
    • Liste der Accounts, die kürzlich das Verfolgen eingestellt haben
    • Detailinformationen zu Accounts, z.B. wann bin ich gefolgt, wann wurde meinem Account gefolgt, wann wurde das Verfolgen eingestellt und wieder aufgenommen, …
    • Durchsuchen der Tweets nach bestimmten Begriffen.
  • Sobald von Friends Tweets mit einem definierten Hashtag erscheinen, sollen diese Retweetet werden.
  • Eigene Tweets sollen auf einem anderen Account gespiegelt werden.
  • Gespeicherte Informationen zu Accounts sollen regelmäßig aktualisiert werden, z.B. einmal pro Woche.

Technisches

  • Die Daten sollen so abgespeichert, dass diese auch separat auswertbar sind.
  • Twacbak soll regelmäßig ohne Benutzerinteraktion die Daten von Twitter einsammeln können.
  • Es soll eine Lösung für einen Account erstellt werden.  Twacbak soll nicht für beliebig viele Accounts Daten sammeln.
  • Es sollen beliebige Microbloggingdienste unterstützt werden, welche die Twitter-API bereitstellen. Neben Twitter ist dies z.B. identi.ca.
  • Twacbak soll im Normalfall einmal pro Stunde ablaufen und dabei max. 50 Aufrufe der API tätigen.
  • Die Software soll so weit es geht platformunabhängig sein. Auf jeden Fall soll die Software unter Windows und unter Linux ablaufen.

Das wären die ersten Anforderungen. Wir alle wissen ja: der Appetit kommt beim Essen. Und wenn jemand Anregungen hat, ich nehme diese gerne entgegen ;-)

, ,

Jedes Kind muss einen Namen haben. Und für eine Heimat wäre es wohl auch dankbar. Zuerst der Name. Nicht zu lang, bin ja tippfaul. Eindeutig und aussagekräftig sollte er sein. Bisher hatte ich von “meinem Twitterbackupanalyseprogramm” gesprochen. @jbanach kam mit dem Vorschlag “Twaccback” (Twitter Account Backup). Ich habe noch zwei C’s aufgehoben. Eines für das Glücksrad, das andere für die Sesamstraße.

Als Heimat kommen auch diese Seiten in Betracht. Dann könnte ich aber entweder “nur” das gesamte Paket zum Download anbieten oder ich müsste hier Software installieren. Aber es gibt ja Dienste, welche die Softwareentwicklung unterstützen. De facto gibt es die Wahl zwischen SourceForge.net oder Google Code. Ich habe mich für SourceForge.net entschieden, weil es da einige Dienste gibt, die ich immer schon mal ausprobieren wollte: Mercurial als verteiltes Versionskontrollsystem (kann Google Code auch) und Trac (kann Google Code m.E. nicht). Beide wären auch Kandidaten für meine Veranstaltung “Projektstudie Softwareentwicklung” ;-).

Somit ist die Heimat von Twacbak gefunden.

Bleibt noch die Frage der Lizenz. Open Source sollte sie sein, von abgeschlossenen Systemen halte ich nicht zu viel. Die GPL ist mir zu viral (und einschränkend), MIT & Co. zu offen. Als Lizenz habe ich (vorläufig) die Apache License, Version 2.0 definiert.

Ja, ich weiß. Langsam sollte ich die Anforderungen definieren. *g

, ,

Seit einigen Tagen bin ich unter einem neuen Account zu erreichen: @implizit. Mein bisheriger Account @dkreuz ist seit einiger Zeit unbrauchbar geworden, vermutlich durch eine Aufräumaktion seitens Twitter (“Siehst du, Mutti, aufräumen ist gar nicht gut!”). Details zum Thema auch hier.

Warum @implizit? Ganz einfach einmal auf der Kommandozeile der Wahl folgendes eingeben:

python -c "import this"

Und dann einfach etwas selbstironisch sein …

,

Ich habe heute ein wenig mit verschieden Python-Bibliotheken zum Zugriff auf der Tw***er herum gespielt. Ich wollte mir klar werden, was diese Bibliotheken können und was nicht. Eine erste Recherche (Suche nach “python twitter”) lieferte mir schon vor einiger Zeit de facto zwei erst zu nehmende Kandidaten. Beide kapseln die Tw***er-API, jedoch mit einer jeweils anderern Philosophie.

Mein erster Kandidat ist python-twitter. Damit hatte ich vor einiger Zeit meine damals 1818 Tweets gesichert. python-twitter stellt als Start die Klasse Api zur Verfügung, mit deren Methoden so gut wie alle Aufrufe durchgeführt werden. Diese Aufrufe liefern meistens Listen von Datenobjekten, wie z.B. Status, DirectMessage oder User. Mit denen kann man dann weiterarbeiten. Als Beispiel der Code, um die Texte der eigenen Timeline, mitsamt der eigenen Freunde darzustellen:

import twitter
api = twitter.Api(username='username', password='password')
timeline = api.GetFriendsTimeline()
for status in timeline:
    print status.text

Um meine Tweets zu sichern hatte ich folgenden Code ausgeführt:

import twitter
import pickle
api = twitter.Api()
timeline = api.GetUserTimeline('dkreuz', count=1818)
datei = open('sicherung.pickle', 'w')
pickle.dump(datei, timeline)
datei.close()

Alles schön handlich und gut gekapselt. Aber mit zwei Nachteilen, doch dazu später. Und wie ich später las: es klappte zufällig. Egal.

Der andere Kandidat sind die Python Twitter Tools. Hier werden nur die Aufrufe sehr grob gekapselt, die Ergebnisse sind meistens Listen von Dictionaries (a.k.a. HashMaps, für die Java-affinen Leser ;-) ). Die Implementierung orientiert sich an der des Python-Moduls xmlrpclib. Dies funktioniert, das die Tw***er-API sehr einheitlich aufgebaut ist. Die Python Twitter Tools sind so generisch, dass die meisten zu erwartenden Änderungen der Tw***er-API nicht zu Änderungen der Bibliothek führen, evtl. aber zum aufrufenden Programmcode. Methodenaufrufe werden über einen netten Python-Trick abgefangen und direkt auf die Tw***er-API abgebildet. Auch hier das Beispiel zur Darstellung der Texte der eigenen Timeline:

import twitter
api = twitter.Twitter('username', 'password')
timeline = api.statuses.friends_timeline()
for status in timeline:
    print status['text']

(Achtung: auch Python Twitter Tools stellt ein Modul mit dem Namen twitter bereit, genau wie python-twitter. Es sind aber unterschiedliche Module!)

Analog der xmlrpclib wird der Aufruf statuses.friends_timeline auf die Tw***er-API statuses/friends_timeline abgebildet. Die Python Twitter Tools definieren, im Gegensatz zu python-twitter, keine eigenen, an der Tw***er-API orientierten Methoden.

Tja, welche Bibliothek ist nun die geeignete?

Die Bibliothek python-twitter hatte ich wegen der netten Abstraktionen ausgewählt, um meine Tweets zu sichern. Das ging ganz gut. Bis ich mir die Tw***er-API im Detail angesehen habe. Zum Beispiel erlaubt es die Methode statuses/user_timeline eine minimale und eine maximale Tweet-ID anzugeben. Die Methode GetUserTimeline() von python-twitter erlaubt dagegen nur eine minimale Tweet-ID. Entweder wurde die Angabe einer maximalen Tweet-ID vom Autoren von python-twitter für nicht notwendig befunden oder diese Möglichkeit wurde erst vor kurzem von Tw***er eingeführt, aber noch nicht in python-twitter nachvollzogen. Entsprechendes gibt es von der Klasse User zu berichten: Tw***er liefert das Datum, wann der Benutzer sich bei Tw***er angemeldet hat, aber nicht python-twitter.

Der andere Punkt, der gegen python-twitter spricht, ist seine Bindung an den Dienst Tw***er. Im Quellcode ist fest und schwer änderbar für jede Methode die URL “http://twitter.com/” hineincodiert. Zum Beispiel bei GetFriendsTimeline die Zeichenkette “http://twitter.com/statuses/friends_timeline.json “. Das ist solange nicht problematisch, so lange man nur den Dienst Tw***er nutzen möchte. Ich selbst nutze parallel den Dienst identi.ca. Schließlich weiß man ja nie, was irgendwann mal mit Tw***er wird. Identi.ca basiert auf einem quelloffenen PHP-System. Und: Identi.ca bietet eine Tw***er-kompatible API an. Software, wie z.B. Gravity nutzen dies, um mehrere Accounts sowohl bei Tw***er als auch bei Identi.ca zu verwalten.

Der einzige Unterschied zwischen API-Zugriffen auf Tw***er und Identi.ca sind unterschiedliche Präfixe der URL für den HTTP-Aufruf. Für Tw***er ist es der Präfix “http://twitter.com”, für identi.ca ist es “http://identi.ca/api “. Der mobile Client Twibble erlaubt sogar die Einstellung eines eigenen Präfix, z.B. wenn man eine identi.ca-Implementierung selbst betreibt.

Und hierbei scheitert python-twitter. Eines meiner Anwendungsszenarien ist das selbstbestimmte Spiegeln von Tweets zwischen Tw***er und Identi.ca (dort heißen Tweets “Dents”, aber das ist eine andere Geschichte).

Der andere Vorteil der Python Twitter Tools ist, dass ich per Programm an alles herankomme, was mir die API bietet. Und nicht auf das beschränkt bin, was mir die Bibliothek genehmigt.

Einen Nachteil haben allerdings beide: Kommunikation ist nur über HTTP möglich, nicht über HTTPS. Aber das kann man ja ändern ;-)

Es geht weiter mit den Python Twitter Tools.

,