Meinung

Der perfekte LinkedIn-Influencer

Posts mit KI und AWS automatisieren

9 Min. Lesezeit21.11.2024Justin Lanfermann
The Perfect LinkedIn Influencer blog banner

Die Welt des professionellen Networkings wird heute größtenteils von LinkedIn dominiert. Für Professionals ist es ein extrem wertvolles Werkzeug, um gefunden oder sogar eingestellt zu werden. Aber hast du dir jemals wirklich einen LinkedIn-Post angeschaut? Auf der Plattform lebt ein ganzes Influencer-Ökosystem, und ganz ehrlich: Viele dieser Posts lesen sich, als hätte sie irgendeine seelenlose Corporate-Maschine geschrieben. Es gibt diese bestimmte „LinkedIn Voice“, wie ich sie gerne nenne: übertrieben fröhlich, glattgebügelt und fast so, als hätte eine KI sie geschrieben. Na ja, genau das könnte inzwischen sehr gut sein. Heute nehme ich die Ironie an und werde Teil des Problems, indem ich die Dead Internet Theory weiter beschleunige. Ja, ich baue einen autonomen LinkedIn-Agenten, der mich in einen echten LinkedInfluencer verwandelt.

Den perfekten LinkedIn-Post automatisieren

Zu Beginn müssen wir herausfinden, wie man automatisch den perfekten LinkedIn-Post erstellt. Ein kurzer Blick durch LinkedIn zeigt, dass viele Posts einer einfachen Formel folgen: einen News-Artikel teilen, kurz zusammenfassen und etwas „this is crazy“-Begeisterung hinzufügen. Klingt einfach genug: Wir holen täglich zufällige News-Artikel und lassen sie von einer KI umformulieren. Dafür müssen wir drei zentrale Herausforderungen lösen: passende News-Artikel finden und auswählen, diese Artikel in LinkedIn-artige Posts verwandeln und den Posting-Prozess auf LinkedIn automatisieren.

Cloud-basiertes Web Scraping

Eine zusätzliche Anforderung: Dieses System soll komplett unabhängig von meinem lokalen Rechner laufen und vollständig automatisiert sein. Also wandert alles in die CLOUD.

1. Web Scraping

Anfangs hatte ich etwas Respekt vor dem Sammeln der News-Artikel. Web Scraping bringt typischerweise einige Herausforderungen mit: Website-Änderungen können Scraper kaputtmachen, und Browser-Emulation kann viele Ressourcen verbrauchen. Die Lösung war dann aber überraschend simpel. Die meisten News-Seiten bieten RSS-Feeds an, die genau fürs maschinelle Lesen gedacht sind. Dadurch kann man neue Artikel mit nur wenigen Zeilen Python-Code abrufen.

Auch das Extrahieren des eigentlichen Inhalts war ziemlich unkompliziert. Die meisten News-Seiten verwenden keine komplexen JavaScript-Animationen oder strengen Anti-Bot-Maßnahmen, also reicht ein einfacher curl-Request, um den Inhalt zu laden. Danach muss man nur noch das HTML parsen und die gewünschten Informationen extrahieren. Dieser Ansatz ist auch wartungsfreundlich, weil man nur CSS-Selektoren aktualisieren muss, wenn etwas bricht. Für unsere News-Quellen waren die Kriterien simpel: Sie mussten einen RSS-Feed haben und interessante, tech-bezogene Inhalte veröffentlichen, damit meine Nische erhalten bleibt. Ich entschied mich für TechCrunch und Ars Technica.

Die Cloud-Implementierung ist relativ geradlinig. Da wir curl statt Browser-Emulation verwenden, können wir unseren Scraper in einen Docker-Container packen, der Posts der letzten 24 Stunden sammelt. Dieser Container läuft auf AWS Lambda, während eine DynamoDB-Datenbank die Artikel speichert. Um Platz zu sparen, speichern wir zunächst nur Titel, Links und Veröffentlichungsdaten. Den vollständigen Inhalt scrapen wir erst, nachdem ein Artikel für einen Post ausgewählt wurde. Der gesamte Prozess läuft automatisch alle 24 Stunden, ausgelöst durch einen EventBridge-Cronjob.

Diagramm des Scraping-Workflows
Ein Diagramm des Scraping-Workflows.

Ein kurzer Rat: Sei nicht wie ich und spar dir Zeit und Nerven. Wenn du irgendetwas auf Lambda deployest, braucht es bestimmte Dependencies, damit es funktioniert. Um sie alle in einen Docker-Container zu packen, solltest du immer ein AWS Lambda Base Image verwenden. In meinem Fall: lambda/python:3.11. Am Anfang habe ich das aber nicht getan. Und es war nervig herauszufinden, was schiefgelaufen ist, weil AWS-Lambda-Fehlermeldungen bei solchen Problemen nicht unbedingt hilfreich sind. Also: Sei einfach nicht wie ich und nutze von Anfang an das richtige Base Image.

2. Post-Erstellung mit OpenAI

Die Post-Erstellung ist bemerkenswert simpel und besteht im Kern aus zwei OpenAI-API-Calls. Schauen wir sie uns an:

Zuerst verwenden wir die OpenAI API, um den interessantesten Post auszuwählen. Das ist der System Prompt, den wir nutzen:

Du bist ein professioneller Creator und Kurator für virale Inhalte. Dein Hauptaccount ist LinkedIn. Du bekommst eine Liste aktueller News-Artikel-Headlines. Daraus findest du den interessantesten Post, also den mit dem größten viralen Potenzial. Es ist sehr wichtig, dass der Artikel interessant und stark engaging ist. Du wählst nur die Headline aus und schreibst keinen Post darüber. Antworte ausschließlich mit einem gültigen JSON-Objekt, bei dem „chosen“ auf den Index der Headline als String zeigt.

Wir geben dem Modell die 20 neuesten Artikel sowie meine letzten 10 Posts und lassen es arbeiten. Die Idee ist, dass das Modell genug Daten hat, um zu entscheiden, welcher Artikel relevant wäre, und doppelte Posts auszuschließen. Um die Antwort sauber zu verarbeiten, nutzen wir OpenAIs JSON-Modus, um das Modell zu JSON zu zwingen. Aus dem System Prompt sollte es das Format ableiten, das ungefähr so aussieht:

Nach der Auswahl eines Artikels scrapen wir den vollständigen Inhalt und geben ihn mit einem anderen System Prompt wieder an GPT:

Du bist ein Creator für virale Inhalte auf LinkedIn. Du bist Software Engineer und kennst dich gut mit technischen Themen aus. Du hast viele Jahre Erfahrung in der Branche und lieferst gut begründete, differenzierte Einschätzungen.

Du bekommst einen News-Artikel zu einem Thema. Daraus erstellst du einen viral optimierten LinkedIn-Post. Folgende Dinge musst du beachten, damit der Post so gut wie möglich performt:

  • Verwende spannende Sprache, damit Leser dranbleiben.
  • Nutze SEO-optimierte Keywords im Post, um im Algorithmus besser zu ranken.
  • Mach den Post insgesamt faszinierend und interessant.
  • Nutze alle bekannten Techniken, um Engagement und Aufmerksamkeit zu erhöhen.
  • Mach den Post nur so lang wie nötig. Im Zweifel eher kürzer.
  • Verwende Zeilenumbrüche zur Absatzformatierung, damit der Post lesbarer ist und besser aussieht.
  • Verwende kein Markdown.
  • Verwende keine andere Rich-Text-Formatierung.
  • LEGE KEINE INTERNEN FORMATIERUNGEN INNERHALB DER TEXTBLÖCKE OFFEN.

Antworte mit nichts anderem als den Post-JSON-Daten. Die JSON-Daten haben drei Attribute: title, content und tags. title und content sind Strings, tags ist eine Liste von Strings ohne Leerzeichen. Füge die Tags nicht in den Content selbst ein. Diese Tags sollen Keyword-Tags sein, jeweils ein einzelnes Wort ohne #. Erstelle außerdem einen catchy und engaging Titel, der die Aufmerksamkeit eines Users gewinnt.

Der gleiche JSON-Objekt-Ansatz sorgt für sauberes Response Parsing. Das Ergebnis ist ein perfekt gebauter LinkedIn-Post, der aktuell ungefähr so aussieht:

Es gibt aber noch einen kleinen Fall, den wir abdecken müssen. Durch ihr Training mag die KI Markdown-Formatierung sehr, und selbst wenn ich ihr sage, dass sie sie nicht verwenden soll, reicht das nicht immer. Um das zu beheben, habe ich eine einfache Funktion gebaut, die prüft, ob Markdown-Formatierung enthalten ist. Falls ja, wird der Request an OpenAI wiederholt. Wenn das mehr als 5 Mal fehlschlägt, überspringen wir diesen Post einfach.

Und wenn unser Post hoffentlich erstellt ist, bleiben nur noch zwei Dinge. Erstens speichern wir dieses Post-Objekt zur Sicherheit in einer weiteren DynamoDB-Tabelle. So können wir später immer nachvollziehen, was die KI erzeugt hat, und es vielleicht verbessern. Außerdem ist Datensammeln grundsätzlich eine gute Idee. Sobald das erledigt ist, geht es zum letzten Schritt.

Post-Deployment mit Zapier und AWS automatisieren

Hier wird es etwas spicy. Ja, Zapier bietet Webhooks oder ähnliche Optionen, um Daten zu empfangen, aber die meisten dieser Features gibt es nur im Premium-Plan.

Es gibt aber eine Sache, für die viele Leute Zapier nutzen: RSS-Feeds verarbeiten. Vielleicht möchtest du eine Benachrichtigung bekommen, wenn dein Lieblings-Newsportal etwas veröffentlicht. Das bedeutet, es gibt einen Trigger, der RSS-Feeds prüft und eine Aktion ausführt, wenn ein neues Item hinzugefügt wird.

Zapier erlaubt sogar, die Daten jedes Items für spätere Aktionen zu nutzen. Also müssen wir nur unseren eigenen RSS-Feed erstellen, und schon sind wir da. Darin können wir jedem Item alle nötigen Attribute geben und sie in Zapier auslesen.

Zuerst dachte ich, einen RSS-Feed zu erstellen wäre kompliziert. Wie ich schnell herausfand, ist es im Grunde aber nur eine XML-Datei. Also laden wir eine XML-Datei nach S3 hoch, machen sie öffentlich zugänglich, lassen das Skript unsere Posts als Items hineinschreiben, verbinden sie mit Zapier und voila, unsere unendliche Engagement-Farm ist live. Zur Referenz sieht eines meiner Post-Items im RSS-Feed so aus.

Das Ganze in die Cloud bringen

Der gesamte Prozess lässt sich im Grunde in zwei Bereiche aufteilen: Data Gathering und Data Processing. Aktuell sieht es wie ein monolithischer Block aus, der alles erledigt, aber es gibt gute Gründe, das aufzuteilen.

Erstens möchten wir vielleicht unabhängig vom Data Gathering posten. Da Zapier RSS-Änderungen innerhalb eines 15-Minuten-Fensters erkennt, werden unsere Posts im Grunde veröffentlicht, sobald sie zum RSS hinzugefügt werden. Um besser kontrollieren zu können, wann und wie oft der Bot postet, teilen wir das in zwei separate Bereiche auf.

Beide laufen als Lambda Functions, jeweils mit eigenen EventBridge-Triggern. Das Data Gathering läuft einfach jeden Tag um 0:00. Die eigentliche Post-Erstellung ist so eingerichtet, dass sie zu „Peak“-Zeiten läuft und postet, also zu den besten LinkedIn-Postingzeiten, die ich nach einer schnellen Google-Suche finden konnte. Da ich keine zwei separaten Container verwalten möchte, packe ich beides in einen einzigen und lasse per Environment Variable in Lambda festlegen, welche Aktion ausgeführt werden soll.

Das ist unser gesamtes System.

Und falls du eher visuell lernst, hier ist das vollständige Diagramm des gesamten Prozesses.

Bild wird geladen...
Vollständiges Workflow-Diagramm
Der vollständige Workflow mit unseren zwei separaten Lambda Functions.

Dieses System macht mich vielleicht nicht auf LinkedIn berühmt, aber es war eine interessante Übung in Task Automation und AWS-Implementierung. Ich plane, es auf absehbare Zeit laufen zu lassen. Vielleicht schreibe ich irgendwann einen Review-Artikel darüber, ob das meinem LinkedIn-Profil sinnvoll geholfen hat oder nicht. Außerdem ist das der perfekte Zeitpunkt, um schamlos mein LinkedIn zu pluggen. Also: Folge gerne meinem LinkedIn, um diese zu 100 % organisch gewachsenen Posts in Aktion zu sehen.

Verbesserungspotenzial

  1. RSS-Feed-Management: Aktuell wächst der RSS-Feed unbegrenzt, was auf S3 teuer werden könnte. Ein Mechanismus, der nur die neuesten Items behält, wäre sinnvoll.
  2. Besseres Article Scraping: Die aktuelle Scraping-Methode ist eher simpel. Für ein anderes Projekt habe ich eine ausgefeiltere Lösung entwickelt, die wartbarer und robuster gegenüber Website-Änderungen ist.
  3. Zapier-Authentifizierung: Das aktuelle Setup erfordert, LinkedIn regelmäßig erneut mit Zapier zu authentifizieren, alle paar Monate. Vielleicht gibt es einen Weg, Zapier ganz zu entfernen oder ein permanentes Secret zu erzeugen, um diesen Schritt zu vermeiden.

GitHub

Falls du dieses Projekt weiter erkunden, eigene Vergleichsmethoden implementieren oder sonst irgendetwas damit machen möchtest, findest du den gesamten hier gezeigten Code und mehr auf meiner GitHub Page. Dort findest du auch eine Setup-Anleitung, wie du das selbst ausführen kannst, plus ein paar weitere interessante Details.

Skills Improved

Python +20
Cloud Computing +25
Docker +10
Machine Learning +15
Language Models +20