SQLite, Delphi und Unicode

Gestern bereinigte ich einen Bug in den Systemen von „InstaLOC“. Hierbei ging es um eine Aufbereitung der Locationdatensätze (1.7Mio) in eine leichter lesbare Form. Aufgefallen war mir, dass bspw. chinesische Zeichen in Form von „???“ beim Auslesen und Übertragen dargestellt wurden. Dies ist das Unicode-Problem und meine Lösung war simpel: Wechsel der Spaltenvariable von „VARCHAR“ auf „STRING“.

[Delphi] Instagram – Likende auf Medien identifizieren und Datensätze speichern

[Datenquellen und Erklärungen]
„mylikers“ -> Anzahl der beobachteten Medien
„mytable“ -> Stringgridobjekt für die Ergebnisse
„oritable“ -> Stringgridobjekt für die Medienrohdaten
„oritable.cols[6].text“ -> Stringreihe für die Postcodes aus Instagram

procedure TForm1.getmylikers(mylikers: integer; mytable: TStringGrid; oritable: tstringgrid);
var lauf, lauf_gl: integer;
l_clear: integer;
JSONArray: tJSONArray;
JSONValue,jvalue: tJSONValue;
JSONPair: TJSONPair;
JSON, json_sub: TJSONObject;
size: integer;
j_array: tJSONArray;
s: string;
i,j: integer;
next_id: string;
chk_br: char;
HTTP: TIdHTTP;

begin
// => hole media_daten (unique-codes!)
debug.Text:=oritable.Cols[6].Text;
debug.Lines.Delete(0);
form1.Caption:=version+‘ ‚+inttostr(debug.Lines.Count-1)+‘ IDs eingelesen‘;
debug_03.Clear;

// init tabelle
with mytable do
begin
cells[0,0]:=’Nr.‘;
cells[1,0]:=’Username‘;
cells[2,0]:=’URL‘;
cells[3,0]:=’ID‘;
cells[4,0]:=’Post-ID‘;
cells[5,0]:=’Post-URL‘;
cells[6,0]:=’Tagcloud‘;
cells[7,0]:=’Postzeit‘;
rowcount:=1;
colcount:=8;
end;
for lauf_gl := 0 to mylikers do
begin
debug_01.Clear;
debug_01.ScrollBars:=ssboth;
randomize;
token.Text:=token.Items[random(token.Items.Count-1)];
debug_03.Lines.Add(‚https://api.instagram.com/v1/media/’+debug.Lines[lauf_gl]+’/likes?access_token=’+token.text);
try
HTTP := TIdHTTP.Create(nil);
form1.Caption:=version+‘ analysiere Likende, Bild: ‚+inttostr(lauf_gl)+‘ / ‚+inttostr(mylikers);
debug_01.Text:=HTTP.Get(‚https://api.instagram.com/v1/media/’+debug.Lines[lauf_gl]+’/likes?access_token=’+token.text);
JSONValue := TJSONObject.ParseJSONValue(debug_01.text);
JSON := TJSONObject.ParseJSONValue(debug_01.Lines.Text) as TJSONObject;
JSONArray := TJSONArray(JSON.Get(‚data‘).JsonValue);
http.free;
SetProcessWorkingSetSize(GetCurrentProcess, $FFFFFFFF, $FFFFFFFF);
for i := 0 to JSONArray.Size – 1 do
begin
with mytable do
begin
cells[0,rowcount]:=inttostr(rowcount);
cells[1,rowcount]:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get(‚username‘)).JsonValue.Value);
cells[2,rowcount]:=’https://instagram.com/’+(TJSONPair(TJSONObject(JSONArray.Get(i)).Get(‚username‘)).JsonValue.Value);
cells[3,rowcount]:=(TJSONPair(TJSONObject(JSONArray.Get(i)).Get(‚id‘)).JsonValue.Value);
cells[4,rowcount]:=debug.Lines[lauf_gl]; // post-id
cells[5,rowcount]:=oritable.Cells[1,lauf_gl+1];
cells[6,rowcount]:=oritable.Cells[2,lauf_gl+1];
cells[7,rowcount]:=oritable.Cells[5,lauf_gl+1];
if zdb.Checked=true then
begin
save_infname:=prjlikeacc.Text;
save_likers:=useridlikeacc.Text;
with sql_befehle.Lines do
begin
clear;
add(‚INSERT INTO `interakt` (`name`, `url`, `uid`, `postid`, `posturl`, `tagcloud`, `inflid`, `inflname`, `postzeit`,`zeit`) Values (“’+cells[1,rowcount]+“‘, “’+cells[2,rowcount]+“‘, “’+cells[3,rowcount]+“‘, “’+cells[4,rowcount]+“‘, “’+cells[5,rowcount]+“‘, “’+escape(cells[6,rowcount])+“‘, “’+save_likers+“‘, “’+save_infname+“‘, “’+cells[7,rowcount]+“‘, “’+datetimetostr(now)+“‘ );‘);
fdquery2.ExecSQL(sql_befehle.text);
form1.Caption:=version+‘ in DB eingetragen …‘;
SetProcessWorkingSetSize(GetCurrentProcess, $FFFFFFFF, $FFFFFFFF);
end;
end;
rowcount:=rowcount+1;
end;
end;
except
form1.Caption:=version+‘ Recherche und Analyse hat nicht funktioniert …‘;
end;
delay(50);
grdColWidth(mytable, 40);
end;
SaveToCSV(mytable,verz+’data\’+save_likers+‘.csv‘);
end;

Aufruf der Prozedur
getmylikers(strtoint(anzmedia.Text), table_likers, m_rohdaten);

Twitter mit Delphi ansprechen?

Durch Zufall entdeckte ich eine recht elegante Möglichkeit der Ansprache von Twitter:

Write a Twitter Client with Delphi XE7

Der Autor bezieht sich hier auf eine vorliegendes Demo-Projekt und im Artikel wird dargestellt, wie – im Speziellen – die Twitter-API über erstaunlich einfache Vorgehensweisen angesprochen werden kann. Interessant ist bei dem Projekt auch, dass das Delphi-Objekt ähnlich simple Verarbeitungsfunktionen für Foren und Facebook liefern kann.

Diese neuen Erkenntnisse erlaubten es mir nun, das angedachte Projekt „Twitterbot“ recht kurzfristig zu starten und in der Version 0.2b den Geschäftsfreund_innen und Klient_innen zu übergeben. Hier lege ich allerdings die Schwerpunkte auf:

– Datenerhebungen zu den Tags, Trends und Influenceraccounts
– Dateninterpretation zu der (halb)automatischen Pflege von Accounts

[Delphi] Zeichenkettenrückumwandlung der Htmlentities

Folgende Funktion erledigt das.

function tform1.Unescape(const StrEscaped:String):WideString;
function UnescapeUncodeChar(const s:String):WideChar;
var
r:Array [0..1] of Byte;
begin
HexToBin(PChar(LowerCase(s)),@r,SizeOf(r));
Result:=WideChar((r[0] shl 8) or r[1]);
end;
function UnescapeAnsiChar(const s:String):Char;
begin
HexToBin(PChar(LowerCase(s)),@Result,SizeOf(Result));
end;
var
i:Integer;
c:Integer;
begin
c:=1;
SetLength(Result,Length(StrEscaped));
i:=1;
while i<=Length(StrEscaped) do
begin
if StrEscaped[i]='%' then
begin
if (i<Length(StrEscaped)) and (StrEscaped[i+1]='u') then
begin
Result[c]:=UnescapeUncodeChar(Copy(StrEscaped,i+2,4));
Inc(i,6);
end
else
begin
Result[c]:=WideChar(UnescapeAnsiChar(Copy(StrEscaped,i+1,2)));
Inc(i,3);
end;
end
else
begin
Result[c]:=WideChar(StrEscaped[i]);
Inc(i);
end;
Inc(c);
end;
SetLength(Result,c-1);
end;

Der Aufruf erfolgt via
unescape(zeichenkette_htmlentities);

Weitere Quellen zu „Html-Endtities“.
http://unicode.e-workers.de/entities.php
https://mothereff.in/html-entities (Encoder, Decoder für den Quercheck)

[Delphi] Zeichenkettenumwandlung (Umlaute, Sonderzeichen) in Htmlentities

Folgende Funktion erledigt das.

function tform1.Escape(const StrToEscape:WideString):String;
var
i:Integer;
w:Word;
begin
Result:='';
for i:=1 to Length(StrToEscape) do
begin
w:=Word(StrToEscape[i]);
if w in [Ord('0')..Ord('9'),Ord('A')..Ord('Z'),Ord('a')..Ord('z')] then
Result:=Result+Char(w)
else if w<=255 then
Result:=Result+'%'+IntToHex(w,2)
else
Result:=Result+'%u'+IntToHex(w,4);
end;
end;

Der Aufruf erfolgt via
escape(zeichenkette_mit_umlaute_oder_sonderzeichen);

[Delphi] komplexe Tastendruckabfolgen simulieren o. automatisieren

Gewisse Änderungen an einem Social Medium zwangen mich zu einer Umarbeitung eines unserer Bots. Ein spezielles Problem war hier das Management komplexerer Login- und Logoutprozeduren, da besagtes Medium genau an dieser Stelle die Aktivierung der Keyboardtasten überwacht.
Nunja: die Lösung hierfür fand ich in der „Tech Ecke“ (Prozedur „EnterText“). Vor der Verwendung dieser Prozedur MUSS selbstverständlich das zu befüllende Formularfeld aktiviert werden.
Dies erledigt man mit „WebBrowser1.OleObject.document.forms.item(0).elements.item(‚[name]‘).focus;“.

[Delphi] Texte im Unicode speichern.

Bei einer speziellen Exportfunktion des Hashtagprojektes entdeckte ich, dass die „savetofile“-Prozedure leider keine Unicode-Zeichenketten (Pictogramme, etc.) in die gewünschte Text-Datei oder CSV übertragen kann. Die Problemlösung sieht so aus:

procedure tform1.savetounicode(mytext: tmemo; filename: string);
begin
Writer := TStreamWriter.Create(filename,
false, TEncoding.UTF8);
Writer.WriteLine(mytext.Text);
Writer.Write(mytext.Text);
Writer.Free();
end;

Aufruf der Prozedure:
savetounicode(memo,dateipfad+dateiname);

Inspiriert von:
Saving string or stringlist to unicode textfile

Delphi: Versenden von EMails via Indy (SSL, TSL)

Folgender Code hilft beim Versenden von EMails aus Delphi / Indy mit Anbindung und Unterstützung von SSL und TSL. Inspiriert wurde das Ganze von „Envio de e-mail com componentes Indy„.

procedure TForm1.Button3Click(Sender: TObject);
IdSSLIOHandlerSocket: TIdSSLIOHandlerSocketOpenSSL;
IdSMTP: TIdSMTP;
IdMessage: TIdMessage;
IdText: TIdText;
sAnexo: string;
begin
IdSSLIOHandlerSocket := TIdSSLIOHandlerSocketOpenSSL.Create(Self);
IdSMTP := TIdSMTP.Create(Self);
IdMessage := TIdMessage.Create(Self);
try
IdSSLIOHandlerSocket.SSLOptions.Method := sslvSSLv23;
IdSSLIOHandlerSocket.SSLOptions.Mode := sslmClient;
IdSMTP.IOHandler := IdSSLIOHandlerSocket;
IdSMTP.UseTLS := utUseImplicitTLS;
IdSMTP.AuthType := satDefault;
IdSMTP.Port := xxx;
IdSMTP.Host := '';
IdSMTP.Username := '';
IdSMTP.Password := '';
IdMessage.From.Address := '';
IdMessage.From.Name := '';
IdMessage.ReplyTo.EMailAddresses := IdMessage.From.Address;
IdMessage.Recipients.Add.Text := edit5.text;
IdMessage.Subject := '';
IdMessage.Encoding := meMIME;
IdText := TIdText.Create(IdMessage.MessageParts);
IdText.Body.Add('The body of the e-mail goes here');
IdText.ContentType := 'text/plain; charset=iso-8859-1';
try
IdSMTP.Connect;
IdSMTP.Authenticate;
except
on E:Exception do
begin
MessageDlg('Cannot authenticate: ' +
E.Message, mtWarning, [mbOK], 0);
Exit;
end;
end;
try
IdSMTP.Send(IdMessage);
MessageDlg('Message sent successfully!', mtInformation, [mbOK], 0);
except
On E:Exception do
begin
MessageDlg('Error while sending a message: ' +
E.Message, mtWarning, [mbOK], 0);
end;
end;
finally
FreeAndNil(IdMessage);
FreeAndNil(IdSSLIOHandlerSocket);
FreeAndNil(IdSMTP);
end;
end;

Delphi: Abrufen von EMails via Indy inkl. SSL

Der folgende Code ist hilft hier vor allem bei TLS und SSL geschützten Accounts. Es eine erste Version und soweit sind keine Fehler aufgefallen.

procedure TForm1.Button9Click(Sender: TObject);
var
i, j,MsgAnz: Integer;
IdSSLIOHandlerSocket: TIdSSLIOHandlerSocketOpenSSL;
bodytext: string;
begin
IdSSLIOHandlerSocket := TIdSSLIOHandlerSocketOpenSSL.Create(Self);
idpop31.IOHandler := IdSSLIOHandlerSocket;
idpop31.UseTLS := utUseImplicitTLS;
IdPOP31.Host := '';
IdPOP31.Port := xxx;
IdPOP31.UseTLS := utUseImplicitTLS;
IdPOP31.Username := '';
IdPOP31.Password := '';
IdPOP31.Connect;
if IdMessage1.ContentType='text/plain' then
memo1.text:=IdMessage1.Body.Text;
MsgAnz := IdPOP31.CheckMessages;
mailzeug.Lines.Add('Anzahl E-Mails:' + IntToStr(MsgAnz));
for i:= 1 to MsgAnz do
begin
idpop31.Retrieve(i, IdMessage1);
mailzeug.Lines.Add('E-Mail Nr:' + IntToStr(i)+ sLineBreak +
' Von:' + IdMessage1.From.Text + sLineBreak +
' Betreff:' + IdMessage1.Subject);
bodytext:=idmessage1.Body.Text;
mailzeug.Lines.Add(bodytext);
IdMessage1.Clear;
idpop31.Delete(i);
end;
IdPOP31.Disconnect;
FreeAndNil(IdSSLIOHandlerSocket);
end;