Twittereinträge eines Benutzers auslesen mit der DSLib und wxWidgets in C++


Ein einfaches unvollständiges Tutorial


Von Thorsten Geppert am 18.11.2009, geändert 22.07.2015.

Ich möchte anmerken, dass es sich hier zwar um eine wxWidgets-Anwendung handelt, allerdings läuft diese in der Konsole. Folgende Voraussetzungen werden benötigt:

  • wxWidgets

  • DSLib

Die Beispielentwicklung erfolgt unter Linux, auf Mac OS X und FreeBSD sollte sie analog funktionieren. Beginnen möchte ich mit der Basis einer C++-Anwendung: der main-Funktion. Erstellen Sie eine Datei namens "Twitter.cpp" und bearbeiten Sie diese mit dem Editor Ihrer Wahl. Inkludieren Sie "<wx/wx.h>" sowie "<DSSocket.h>". Schreiben Sie weiterhin die main-Funktion:

#include <wx/wx.h>
#include <wx/sstream.h>
#include <wx/xml/xml.h>
#include <DSSocket.h>
#include <DSCasts.h>

int main(int argc, char *argv[]) {
    printf("Hello World\n");

    return 0;
}

Kompilieren Sie den Code mit folgender Zeile:

g++ Twitter.cpp -o Twitter -lds `wx-config --libs –cppflags`

Achten Sie darauf, dass es sich bei „`“ nicht um Apostrophzeichen, sondern um sogenannte Backticks handelt. Nach der Kompilierung können Sie das Programm mit:

./Twitter

ausführen. „Hello World“ sollte dann auf Ihrem Bildschirm erscheinen. Wenn das funktioniert hat, steht der weiteren Entwicklung nichts mehr im Weg. Wir wollen per Kommandozeile den Benutzernamen übergeben können, dessen letzte Twitternachrichten wir auflisten wollen. Ersetzen Sie also die Zeile mit „printf“ mit:

if(argc != 2) {
    fprintf(stderr, "Benutzung: %s Twittername\n", argv[0]);
    return 1;
}

Kompilieren Sie den Quelltext erneut und testen Sie ihn einmal mit und einmal ohne Parameter. Wenn Sie keine Parameter (oder mehr als einen Parameter) angeben, erfolgt eine Fehlermeldung auf der Fehlerkonsole.

Im nächsten Schritt müssen wir eine Verbindung zu „twitter.com“ auf Port „80“ aufbauen. Dazu eignet sich „DSSocket“ hervorragend. Die Klasse kapselt wichtige C-Socket-Befehle in einer einfach zu benutzenden Struktur. Erstellen Sie ein Objekt der Klasse und rufen Sie die Methoden „SetAddress“ und „SetTimeout“ mit den richtigen Parametern auf:

DynSoft::DSSocket connection;
connection.
SetAddress(_N("twitter.com"), 80);
connection.
SetTimeout(10, 0); // 10 Sekunden-Timeout

Beachten Sie, dass DSSocket im Namespace „DynSoft“ ist. Jetzt folgt die Konnektierung und das Abrufen der Daten, die wir benötigen. Dabei gehen wir folgendermaßen vor: Wir testen, ob die Verbindung zu „twitter.com“ auf Port „80“ zustande kommt, ansonsten geben wir eine Fehlermeldung aus. Danach senden wir dem Twitter-Server einen „GET“-Befehl, indem wir um die Sendung der Daten des übergebenen Nutzers als XML bitten. Wir holen uns dann die Daten und schließen die Verbindung. Wenn das Datenholen nicht funktioniert hat, geben wir eine Fehlermeldung aus, ansonsten die Daten (der Einfachheit nochmal als gesamter Quelltext):

#include <wx/wx.h>
#include <wx/sstream.h>
#include <wx/xml/xml.h>
#include <DSSocket.h>
#include <DSCasts.h>

int main(int argc, char *argv[]) {
     if(argc != 2) {
          fprintf(stderr, "Benutzung: %s Twittername\n", argv[0]);
          return 1;
     }

     DynSoft::DSSocket connection;
     connection.SetAddress(_N("twitter.com"), 80);
     connection.SetTimeout(10, 0); // 10 Sekunden-Timeout

     if(connection.Connect()) {
          connection.Send(
               _N("GET /statuses/user_timeline/") +
               DynSoft::DSCasts::ToString(argv[1]) +
               _N(".xml\n")
          );

          wxString content;
          const bool received = connection.Receive(&content);
          connection.Disconnect();

          if(!received) {
               fprintf(stderr, "Konnte die Daten nicht laden\n");
               return 2;
          }

          DS_PL(content);
     } else {
          fprintf(stderr, "Konnte keine Verbindung aufbauen\n");
          return 3;
     }

     return 0;
}

Kompilieren Sie den Quelltext und probieren Sie ihn aus:

./Twitter Morfio

Läuft alles gut, erhalten Sie einen XML-Quelltext mit den letzten Nachrichten des Benutzers. Gibt es den Benutzer nicht, wird ihnen das im XML-Quelltext angezeigt.

Im letzten Schritt müssen Sie nur noch das XML parsen. wxWidgets bietet Ihnen dafür einfache Methoden. Bitte entnehmen Sie der wxWidgets-Dokumentation, wie genau das funktioniert. Eine Implementierung könnte so aussehen (ersetzen Sie dazu „DS_PL(content);“ durch folgenden Quelltext:

wxStringInputStream sis(content);
wxXmlDocument
doc(sis);

if(doc.GetRoot()->GetName() != _N("statuses")) {
    fprintf(stderr, "Das Wurzelverzeichnis ist das falsche (statuses)\n");
    return 3;
}

wxXmlNode
*xml = NULL;
wxXmlNode
*status = NULL;
wxXmlNode
*statuses = doc.GetRoot()->GetChildren();
while(statuses) {
    if(statuses->GetName() == _N("status")) {
        status = statuses->GetChildren();
        while(status) {
            if(status->GetName() == _N("text")) {
                xml = status->GetChildren();
                // In 2.6.x gibt es kein GetNodeContent, also
                // muessen wir es selbst implementieren
                while(xml) {
                    if(xml->GetType() == wxXML_TEXT_NODE) {
                        DS_PL(xml->GetContent());
                        break;
                    }
                    xml = xml->GetNext();
                }
            }
            status = status->GetNext();
        }
    }
    statuses = statuses->GetNext();
}

DS_PL(xml->GetContent());“ holt genau die Daten, die als Nachricht bei Twitter stehen.

Im folgenden noch einmal alles in einem:

#include <wx/wx.h>
#include <wx/sstream.h>
#include <wx/xml/xml.h>
#include <DSSocket.h>
#include <DSCasts.h>

int main(int argc, char *argv[]) {
    if(argc != 2) {
        fprintf(stderr, "Benutzung: %s Twittername\n", argv[0]);
        return 1;
    }

    DynSoft::DSSocket connection;
    connection.SetAddress(_N("twitter.com"), 80);
    connection.SetTimeout(10, 0); // 10 Sekunden-Timeout

    if(connection.Connect()) {
        connection.Send(
            _N("GET /statuses/user_timeline/") +
            DynSoft::DSCasts::ToString(argv[1]) +
            _N(".xml\n")
        );

        wxString content;
        const bool received = connection.Receive(&content);
        connection.Disconnect();

        if(!received) {
            fprintf(stderr, "Konnte die Daten nicht laden\n");
            return 2;
        }

        wxStringInputStream sis(content);
        wxXmlDocument doc(sis);

        if(doc.GetRoot()->GetName() != _N("statuses")) {
            fprintf(stderr, "Das Wurzelverzeichnis ist das falsche (statuses)\n");
            return 3;
        }

        wxXmlNode *xml = NULL;
        wxXmlNode *status = NULL;
        wxXmlNode *statuses = doc.GetRoot()->GetChildren();
        while(statuses) {
            if(statuses->GetName() == _N("status")) {
                status = statuses->GetChildren();
                while(status) {
                    if(status->GetName() == _N("text")) {
                        xml = status->GetChildren();
                        // In 2.6.x gibt es kein GetNodeContent, also
                        // muessen wir es selbst implementieren
                        while(xml) {
                            if(xml->GetType() == wxXML_TEXT_NODE) {
                                DS_PL(xml->GetContent());
                                break;
                            }
                            xml = xml->GetNext();
                        }
                    }
                    status = status->GetNext();
                }
            }
            statuses = statuses->GetNext();
        }
    } else {
        fprintf(stderr, "Konnte keine Verbindung aufbauen\n");
        return 4;
    }

    return 0;
}

Das war es bereits. Sie sehen also, dass das Auslesen von Twitternachrichten eines Benutzer sehr einfach ist.

Download: Twitter.cpp (ca. 1,66kb)

[zurück]