News: Zusammenlegung der Instagramprojekte

Per sofort wird der Support für das Projekt „Hashtag-DB“ / „Reichweitenanalysen v. Hashtags“ eingestellt und mit dem Themenkomplex „InstaLOC“ zusammen geführt.
Der Zugang zu den Datenbanken, generiert zwischen 2015/16 und 2018, ist für Externe ab dem heutigen Datum geschlossen.

Ausnahmen sind Geschäftspartner_innen und Kund_innen.

Link zum Archiv: https://www.pontipix.de/werkzeuge-tools/hashtag-projekt/

Themenweltendatenbank „Tourismus & Urlaub“: aktueller Bestand

Die Datenbank (SQLite-Datei) hat nun folgende Kennzahlen:

Speichervolumen: ~13GB
Beiträge (Unique): 18.411.849
Tagwolken (Unique): 17.490.694
(codierte) Nutzer_innen: 6.180.654
Locations (Unique): 1.037.477
Zeitstempel (Unique): 9.165.025

Mit Stand 27.10.2018 wurden 120.000 von 176721 Abfragen über die API innerhalb von ca 2 Wochen mit einem täglichen Scrapingzeitraum i.H.v. 11Stunden durchgeführt.

Ich rechne mit einem Abschluss der Themenwelten-Erfassungsfunktionen zum kommenden Mittwoch (31.10.2018) und im nächsten Turnus widme ich mit den Themen „Kunst“, „Kultur“, „Mode“, „Lifestyle“. Hier rechne ich mit ~300.000 Abfragen.

InstaLOC, Datenauszüge / Freigabe (Stand: 22.10.2018)

Folgende (Roh)datenauszüge beschreiben den Umfang der gesammelten Informationen.

(1) Die Locations
export_locs_22102018.rar

(2) Die Zeitstempel
times.rar

(3) Die Tagwolken
export_tags_22102018.rar

Bitte beachten.
Die Locationsdatei umfasst 3 Pakete: Auflistung, Zuordnung zu den gesammelten Likes und Zuordnung zu den gesammelten Comments.
Die Zeitstempeldatei umfasst ein Paket.
Die Tagwolkendatei umfasst 3 Pakete: Auflistung, Zuordnung zu den aktiven User_innen und Zuordnung zu den gesammelten Likes.

Die entpackten CSV-Daten schwanken zwischen wenigen 100MB bis zu 5GB und man muss über entsprechende Parser / Ressourcen verfügen, um die Daten interpretieren zu können. Hier gilt: Support wird ausschließlich den Kund_innen und den (Geschäfts)freund_innen geleistet.

InstaLOC, Datenbestand – Überblick

Nach Zusammenführung der fehlerbereinigten Datensätze (Duplikate etc.) in eine Master-DB mit den Inhalten:

-> Städte aus dem RolandBerger-Projekt
-> div. deutsche Groß- und Kleinstädte
-> politische Analyse
-> Themenwelt „Home & Living“
-> 1/3 – Datenbank aus Themenwelt „Tourismus“

kommen wir nun auf den folgenden Bestand:

24.321.643 Beiträge
19.123.483 Tagwolken
8.031.350 (codierte) Nutzer_innen
1.084.069 Locations
14.540.475 Zeitstempel

Die Datenbankdatei ist umfasst ca. 13GB und wird je Durchlauf um 3-5GB wachsen. Der aktualisierte Datenbestand wird zeitnah an die W&L GbR Partner_innen verteilt.

InstaLOC, Zwischenfreigabe der Themendatenbank „Tourismus“

Die aktuelle Datenbank umfasst die Ergebnisse aus 23575 Abfragen und speichert folgende Daten:

4.546.235 Beiträge
4.376.548 Tagwolken
2.031.490 codierte User
380.723 Locations
2.674.339 Zeitstempel

Datenauszüge (unverschlüsselt)

(1) Auflistung Tagwolken und deren Locations
Datei: exp_urlaub_tag_loc.zip
Dateivolumen: ZIP->339MB, Entpackt->1.6GB

(2) Auflistung der Locations und Aufsummierung der Likes JE Location
Datei: exp_urlaub_like_locs.zip
Dateivolumen: ZIP->13MB, Entpackt->42MB

(3) Auflistung Tagwolken (ungefiltert!) und deren Likes
Datei: exp_urlaub_tag_likes.zip
Dateivolumen: ZIP->168MB, Entpackt->600MB

(4) Auflistung der Locations + Postingzeitstempel + Likes
Datei: exp_urlaub_loc_time_likes.zip
Dateivolumen: ZIP->52MB, Entpackt->265MB

(5) Auflistung der Locations + Aufsummierung der Postings
Datei: exp_urlaub_postings_locs.zip
Dateivolumen: ZIP->12MB, Entpackt->42MB

(6) Auflistung der Tagwolken + Aufsummierung der User, welche die Wolken verwendeten
Datei: exp_urlaub_tags_user.zip
Dateivolumen: ZIP->333MB, Entpackt->1.5GB

(7) Auflistung der Locations + Aufsummierung der User, welche an den Locations aktiv waren
Datei: exp_urlaub_loc_user.zip
Dateivolumen: ZIP->13MB, Entpackt->41MB

Die aufgelisteten Datenauszüge geben einen ersten und sehr guten Überblick.
Im Bezug zu den erfassten Datensätzen sind weitere Nachforschungen die Beantwortung hochfaszinierender Fragen, wie:

(a) Wieviele User schreiben in welchem Zeitfenster über den Urlaub an welchen Orten?
(b) Welche Orte werden an Hotspots von welchen Usergruppen besucht und was wird da geschrieben?
(c) Welche User / Usergruppen neigen zur Trendbildung an welchen Orten und / oder zu welchen Tags (Themen, Themenwelten)?
(d) Welche Orte werden zu welchen Zeitfenstern|Jahreszeiten|Monaten besonders stark frequentiert und was wird da geschrieben?

möglich.

Die Anwendungsszenarien sind vielfältig. Ich denke an die folgenden Punkte:

-> Influenceraccountanalysen
-> Schnittstellen zu Socialmediastrategien inkl. Hashtag- und Postzeitplanungen
-> Schnittstellen zu div. Textanalysetools mit Anbindung an WDF*IDF / KWD-Analysen
-> gezielte Steuerung von ortsbezogenen Werbeanzeigen|Flyeraktionen|Plakataktionen|sonst.Promomaßnahmen
-> Gegenprobe auf die üblichen Auswertungstools aus der Socialmedia
-> gezielte Steuerung von ortsbezogenen Werbeanzeigen in den Suchmaschinen, den Socialmedia

Interesse am Austausch? Fragen? Anfragen?
Konkretes Projektangebot?
Ich freue mich auf Rückmeldung unter der eMail: office(at)pontipix.de

Notiz: Instagramaccount aufräumen und effektiv managen.

Vor einigen Tagen beschloss ich eine Neuausrichtung meines Accounts und stand vor folgenden Problemen:

(1) Wie kann man extrem schnell und mit möglichst wenig Aufwand uralte Beiträge entfernen?
(2) Wie räumt man schnell und effektiv die Aboliste auf?

Ninjagram und ähnliche Systeme wurden gesichtet und getestet. Hier stellte ich einen hohen Zeitaufwand fest und landete bei der Android-App „Cleaner for Instagram„. Das Werkzeug erlaubt das Entfernen von mehreren 1000 Beiträgen per Stapelverarbeitung, filtert Abos nach Aktivitäten (Follow / NON-Follow / Interaktionsfreudigkeiten etc.) und kostet – je nach Funktionsumfang – zwischen 3,09 € bis 4,89 €.

Projekt „InstaLOC“ – Update der Scrapertechnologie + Bugfixing

Während der letzten Datendurchläufe stellte ich immer wieder fest, dass der Scraper den Arbeitsspeicher zu stark beanspruchte. Konkret bedeutet das, dass ca. 250 Abfragen an die API einen Scrapingabbruch und einen RAM-Verbrauch i.H.v. 1,8GB (!) provozierte.

Dieses Problem wurde nun final über die Quellcodeanpassung
jsonvalue.Free;
JSON.Free;

gelöst.

Der Speicherverbrauch wurde von 1.8GB auf ca. 100MB / je 250 Abfragen reduziert.

Die fehlerbereinigte Prozedur ist:
procedure TForm1.getmedia_db(mytable: TStringGrid; tagsearch: string; rounds: integer);
var
JSONArray: tJSONArray;
JSONValue,jvalue: tJSONValue;
JSONPair: TJSONPair;
JSON, json_sub: TJSONObject;
size: integer;
j_array: tJSONArray;
s: string;
i,j: integer;
next_id: string;
zaehl: integer;
url,tag,likes,comments,post_id,username,location,filter,pruefzeit: widestring;
erstellzeit: string;
gedoens: TIdHTTP;
zw_db: tmemo;
begin
gedoens := TIdHTTP.Create;
zw_db :=tmemo.Create(self);
sql_befehle.Clear;
try
zw_db.text:=gedoens.Get('https://api.instagram.com/v1/tags/'+escape(tagsearch)+'/media/recent?access_token='+token.text);
JSONValue := TJSONObject.ParseJSONValue(zw_db.text);
JSON := TJSONObject.ParseJSONValue(zw_db.Lines.Text) as TJSONObject;
JSONArray := TJSONArray(JSON.Get('data').JsonValue);
try next_id:= JSONValue.GetValue('pagination.next_url');
except
//-> hier user, locations etc. einbauen!!!
next_id:='N/A';
end;

for i := 0 to JSONArray.Size - 1 do
begin
url:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get('link')).JsonValue.Value);
s:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get('tags')).ToString);
s:= StringReplace(s, '"tags":[', '', [rfReplaceAll,rfIgnoreCase]);
s:= StringReplace(s, ']', '', [rfReplaceAll,rfIgnoreCase]);
tag:=escape(s);
s:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get('likes')).ToString);
s:= StringReplace(s, '"likes":{"count":', '', [rfReplaceAll,rfIgnoreCase]);
s:= StringReplace(s, '}', '', [rfReplaceAll,rfIgnoreCase]);
likes:=s;
s:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get('comments')).ToString);
s:= StringReplace(s, '"comments":{"count":', '', [rfReplaceAll,rfIgnoreCase]);
s:= StringReplace(s, '}', '', [rfReplaceAll,rfIgnoreCase]);
comments:=s;
erstellzeit:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get('created_time')).JsonValue.Value);
erstellzeit:=datetimetostr(UnixToDateTime(strtoint(erstellzeit)));
post_id:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get('id')).JsonValue.Value);
s:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get('user')).ToString);
s:= StringReplace(s, '"user":{"username":', '', [rfReplaceAll,rfIgnoreCase]);
s:= StringReplace(s, '}', '', [rfReplaceAll,rfIgnoreCase]);
s:= StringReplace(s, '"', '', [rfReplaceAll,rfIgnoreCase]);
username:=s;
s:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get('location')).ToString);
s:= StringReplace(s, '"location":', '', [rfReplaceAll,rfIgnoreCase]);
location:=s;
filter:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get('filter')).JsonValue.Value);
pruefzeit:=datetimetostr(now);
with sql_befehle.Lines do
begin
add('INSERT INTO `locations` (`url`, `tag`, `likes`, `comments`, `erstellzeit`, `post_id`, `username`, `location`, `filter`, `pruefzeit`) Values ('''+url+''', '''+tag+''', '''+likes+''', '''+comments+''', '''+erstellzeit+''', '''+post_id+''', '''+username+''', '''+location+''', '''+filter+''', '''+pruefzeit+''');');
end;
end;
fdquery3.ExecSQL(sql_befehle.text);
sql_befehle.Clear;
// sql_befehle.Free;
except
tr_break:='1';
end;

// -> Speicherfreigabe
jsonvalue.Free;
JSON.Free;
if next_id<>'N/A' then
begin
repeat
// -> tiefenpruefung
if next_id='N/A' then
break;
delay(strtoint(frequenz1.Text));
try
zw_db.text:=gedoens.Get(next_id);
JSONValue := TJSONObject.ParseJSONValue(zw_db.text);
JSON := TJSONObject.ParseJSONValue(zw_db.Lines.Text) as TJSONObject;
JSONArray := TJSONArray(JSON.Get('data').JsonValue);
try next_id:= JSONValue.GetValue('pagination.next_url');
except
next_id:='N/A';
break;
end;
for i := 0 to JSONArray.Size - 1 do
begin
url:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get('link')).JsonValue.Value);
s:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get('tags')).ToString);
s:= StringReplace(s, '"tags":[', '', [rfReplaceAll,rfIgnoreCase]);
s:= StringReplace(s, ']', '', [rfReplaceAll,rfIgnoreCase]);
tag:=escape(s);
s:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get('likes')).ToString);
s:= StringReplace(s, '"likes":{"count":', '', [rfReplaceAll,rfIgnoreCase]);
s:= StringReplace(s, '}', '', [rfReplaceAll,rfIgnoreCase]);
likes:=s;
s:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get('comments')).ToString);
s:= StringReplace(s, '"comments":{"count":', '', [rfReplaceAll,rfIgnoreCase]);
s:= StringReplace(s, '}', '', [rfReplaceAll,rfIgnoreCase]);
comments:=s;
erstellzeit:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get('created_time')).JsonValue.Value);
erstellzeit:=datetimetostr(UnixToDateTime(strtoint(erstellzeit)));
post_id:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get('id')).JsonValue.Value);
s:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get('user')).ToString);
s:= StringReplace(s, '"user":{"username":', '', [rfReplaceAll,rfIgnoreCase]);
s:= StringReplace(s, '}', '', [rfReplaceAll,rfIgnoreCase]);
s:= StringReplace(s, '"', '', [rfReplaceAll,rfIgnoreCase]);
username:=s;
s:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get('location')).ToString);
s:= StringReplace(s, '"location":', '', [rfReplaceAll,rfIgnoreCase]);
location:=s;
filter:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get('filter')).JsonValue.Value);
pruefzeit:=datetimetostr(now);
with sql_befehle.Lines do
begin
add('INSERT INTO `locations` (`url`, `tag`, `likes`, `comments`, `erstellzeit`, `post_id`, `username`, `location`, `filter`, `pruefzeit`) Values ('''+url+''', '''+tag+''', '''+likes+''', '''+comments+''', '''+erstellzeit+''', '''+post_id+''', '''+username+''', '''+location+''', '''+filter+''', '''+pruefzeit+''');');
end;
end;
fdquery3.ExecSQL(sql_befehle.text);
sql_befehle.Clear;
except
tr_break:='1';
break;
end;
// -> Speicherfreigabe
jsonvalue.Free;
JSON.Free;
// -> tiefenpruefung, ende
zaehl:=zaehl+1;
until zaehl=rounds;
end;
form1.Caption:=version+' alle Posts herunter geladen';
gedoens.free;
zw_db.Free;
fdquery.Free;
end;

Projekt InstaLOC, Aktuelle Statistiken

Der aktuelle Datenbestand umfasst:

587.903 Locations inkl. Geocodes, IDs und Namen
12.669.502 Unique Tagclouds
5.633.457 Beiträge ohne Locationzuordnung
8.516.617 Beiträge mit Locationzuordnung
4.863.200 codierte User
10.700.170 Unique Zeitstempel (Beiträge)

Die Masterdatenbank umfasst alle erfassten Datensätze und die Scrapingtechnologie schafft das genannte Volumen innerhalb von 3-4 Werktagen.

Datenbanken, Bigdata und die Aufbereitung der Abfragen

Nach Durchsicht der aktuellen Datenbasis aus den Projekten „HashtagDB“ und „InstaLOC“ musste ich etwas nachdenken und mir eine Lösung zur Aufbereitung der extremen Datenfülle überlegen. Das Problem ist, dass zwar via SQLite-Studio und der integrierten SQL-basierten Abfragemöglichkeiten gute Abfrage- und Auswertungsmöglichkeiten vorliegen, jedoch lassen sich keinerlei Gewichtungsprozeduren hier realisieren. Ein angedachter Lösungsweg war die Anbindung von Excel via der bereitgestellten API. Trotz (technischer) Realisierbarkeit tauchten auf verschiedenen Rechnern immer wieder Ressourcenprobleme auf. Ich entschied mich heute (final) für eine 3-Stufenlösung:

(1) Vorgewichtung
Die Vorgewichtung erfolgt via SQLite-Studio in Form der – hier dokumentierten – Abfragen. Wir, oder ein geschulter Externer, setzen entsprechende Metaebenenanfragen an die Datenbanken ab und extrahieren die Ergebnisse im Standard-CSV-Format.
Metaebenenanfragen können sein:
(a) Gib mir alle Tagwolken aus dem Zeifenster 08-2018 aus, die mind. zum Inhalt „urlaub“ haben und in dem Raum Leipzig gepostet wurden.
(b) Zeige mir die beliebtesten Postings aus dem Raum Berlin mit Inhalt „Schmuck“.

(2) Nachgewichtung
Die Nachgewichtung erfolgt hier mit Hilfe einer kleinen Software. Diese importiert die Ergebnisse aus der „Vorgewichtung“ und liefert über geeignete Berechnungsfunktionen Interpretationshinweise zu:
(a) Welche Beziehungen existieren zwischen den Hashtags?
(b) Welche Beziehungen existieren zwischen den Tags, den Locations und den aktiven Accounts?
(c) Wer gewichtet Trends in welchem Zeitfenster, an welcher Location?

(3) Interpretation und Reporting
Die Nachgewichtungssoftware exportiert die generierten Gewichtungsergebnisse in ein geeignetes Standarformat, welches von Openoffice und Excel akzeptiert wird. Die grafische Auswertung und die Aufbereitung für nachgelagerte Beratungsgespräche und Interpretationen im Team / bei den Kund_innen findet genau in diesem Umfeld statt.

Privat vertrete ich den Anspruch an die absolute Transparenz bzgl. der Rohdaten / der Datensätze. Ich habe aber auch, nach verdammt vielen Diskussionen, verstanden, dass 4-20GB große Datensätze von Geschäftsfreund_innen und Kund_innen nicht behandelbar sind. Daher der skizzierte Kompromis der Aufbereitung via Excel, Powerpoint & Co. und Quercheck auf die gefilterten Daten aus der „Nachgewichtung“.

Anfragen, Hinweise oder Nachfragen gerne via Kommentar, eMail oder Telefon.

Hinweis: SQLite-Dateien in Excel öffnen und da weiter verarbeiten (InstaLOC und HashtagDB)

Irgendwer aus dem „Netzwerk“ gab mir bei einem Telefonat einen interessanten Hinweis zu den Potentialen von Excel. Wir sprachen da u.a. darüber, dass die freigegebenen SQLite-Datenbanken aus den Projekten „Hashtag-Reichweiten“ und „InstaLoc“ zu viele Auswertungs- und Analyseprobleme provozieren können.

Eine Option beschreibt
https://yourbusiness.azcentral.com/connecting-excel-sqlite-12971.html

und man benötigt für die dargestellte Funktion das Plugin http://www.ch-werner.de/sqliteodbc/.

Möchte man hierüber unsere Dateien anbinden, muss an der entsprechenden Einlesestelle (siehe verlinkter Blogbeitrag!) die Option „SQLite-3“ ausgewählt werden. Die nachgeschaltete EXCEL-Oberfläche ist relativ selbsterklärend. Mit den konkreten Auswertungsfunktionen habe ich mich nicht beschäftigt und ich kann an der Stelle auch keinerlei Support zu den Queries geben.