Erfahren Sie, wie Sie einen produktionsreifen Flask-Webhook-Server erstellen, der LinkedIn-Profile asynchron abruft. Crawlbase Die API speichert Daten in MySQL. Dieses Tutorial behandelt die Einrichtung der Umgebung, das Datenbankdesign, die Implementierung des Callback-Servers und die Echtzeitüberwachung.

Was Sie bauen werden

Ein skalierbares LinkedIn-Scraping-System mit folgenden Funktionen:

  • Flask-Webhook-Server um gesammelte Daten zu erhalten
  • MySQL-Datenbank für strukturierte Datenspeicherung
  • Asynchrone Verarbeitung für das Schaben großer Mengen
  • Echtzeit-Überwachung Dashboard

Anwendungsfälle

  • Talent AcquisitionAutomatisierte Kandidatensuche und Profilanalyse
  • Markteinblicke: Branchentrends und Wettbewerbsanalysen verfolgen
  • Lead-Generierung: Aufbau zielgerichteter B2B-Interessentendatenbanken
  • HR AnalyticsAnalyse von Arbeitsmarktmustern und Karriereverläufen
  • KI-Trainingsdaten: Datensätze für Modelle des maschinellen Lernens generieren

Diese Anleitung zeigt ausschließlich das Auslesen öffentlich zugänglicher LinkedIn-Daten. Beachten Sie stets die Nutzungsbedingungen von LinkedIn und die geltenden Datenschutzgesetze. Crawlbase verbietet die Entnahme privater Daten.

Teil I: Vorbereiten der Umgebung

A. Erstellen Crawlbase Konto und Aktivieren des LinkedIn-Crawlings

  1. Beginnen Sie mit dem Besuch der Crawlbase Website und Für einen Account anmelden.
  2. Gehen Sie zum LinkedIn-Vereinbarungsseite um die Bedingungen zu lesen und zu akzeptieren.
  3. Fügen Sie Ihre Rechnungsdetails hinzu, indem Sie auf die Rechnungsinformationseinstellungen.

B. Einrichten einer MySQL-Datenbank

Wir werden MySQL verwenden, da es ein beliebtes relationales Datenbankmanagementsystem ist, das für verschiedene Anwendungen weit verbreitet ist. In diesem Beispiel werde ich MySQL Version 8 verwenden. Wenn Sie diese noch nicht auf Ihrem Computer installiert haben, gehen Sie bitte zu offizielles Installationshandbuch von MySQL.

Öffnen Sie nach der Installation den MySQL-Befehlszeilenclient. Sie werden aufgefordert, das Kennwort für den MySQL-Root-Benutzer einzugeben. Nach Eingabe des Kennworts befinden Sie sich in der MySQL-Befehlszeilenschnittstelle. Anschließend können Sie die folgenden Befehlszeilen ausführen.

  1. Erstellen Sie einen neuen Benutzer
1
CREATE USER „LinkedInCrawler“@„lokaler Host“ IDENTIFIZIERT BY „linked1nS3cret“;

Der Code erstellt einen neuen MySQL-Benutzer namens linkedincrawler mit dem Passwort linked1nS3cret, beschränkt auf die Verbindung von derselben Maschine (localhost).

  1. Erstellen Sie eine Datenbank
1
CREATE DATENBANK linkedin_crawler_db;

Diese Datenbank ist ein leerer Container, der Tabellen, Daten und andere Objekte speichern kann.

  1. Erteilen der Berechtigung
1
GRANT ALLER PRIVILEGIEN ON linkedin_crawler_db.* TO „LinkedInCrawler“@„lokaler Host“;

Dadurch erhält unser Benutzer sämtliche Privilegien und Berechtigungen für die neu erstellte Datenbank.

  1. Aktuelle Datenbank festlegen
1
VERWENDEN Sie linkedin_crawler_db;

Dadurch wird unsere Datenbank ausgewählt und alle unsere Anweisungen an sie weitergeleitet.

  1. Lassen Sie uns nun drei Tabellen innerhalb der aktuell ausgewählten Datenbank erstellen: crawl_requests, linkedin_profiles und linkedin_profile_experiences.

Die crawl_requests wird die Haupttabelle sein, die als Mechanismus zur Verfolgung des gesamten asynchronen Crawling-Prozesses dient.

Diese Tabelle hat drei Spalten: url, status, crawlbase_rid.

Die status Spalte kann einen dieser drei Werte haben - waiting, receiving und processed. Der Zweck dieser Status wird später näher erläutert.

1
2
3
4
5
6
TABELLE ERSTELLEN IF NICHT VORHANDEN `crawl_requests` (
`Id` INT AUTO_INCREMENT PRIMARY KEY,
`url` TEXT NICHT NULL,
`Status` VARCHAR(30) NICHT NULL,
`crawlbase_rid` VARCHAR(255) NICHT NULL
);

Dann erstellen wir Datenbankindizes für die Leistung unserer Abfrage.

1
2
3
CREATE INDEX `idx_crawl_requests_status` ON `crawl_requests` (`Status`);
CREATE INDEX `idx_crawl_requests_crawlbase_rid` ON `crawl_requests` (`crawlbase_rid`);
CREATE INDEX `idx_crawl_requests_status_crawlbase_rid` ON `crawl_requests` (`Status`, `crawlbase_rid`);

In den letzten beiden Tabellen können Sie die strukturierten Informationen zu den gecrawlten LinkedIn-Profilen und den zugehörigen Details speichern.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
TABELLE ERSTELLEN IF NICHT VORHANDEN `linkedin_profiles` (
`Id` INT AUTO_INCREMENT PRIMARY KEY,
`crawl_request_id` INT NICHT NULL,
`Titel` VARCHAR(255),
`Überschrift` VARCHAR(255),
`Zusammenfassung` TEXT,

AUSLÄNDISCHER SCHLÜSSEL (`crawl_request_id`) REFERENZEN `crawl_requests`(`id`)
);

TABELLE ERSTELLEN IF NICHT VORHANDEN `linkedin_profile_experiences` (
`Id` INT AUTO_INCREMENT PRIMARY KEY,
`LinkedIn_Profil_ID` INT NICHT NULL,
`Titel` VARCHAR(255),
`Firmenname` VARCHAR(255),
`Beschreibung` TEXT,
`ist_aktuell` BIT NICHT NULL DEFAULT 0,

AUSLÄNDISCHER SCHLÜSSEL (`LinkedIn-Profil-ID`) REFERENZEN `linkedin_profiles`(`id`)
);

Um die Tabellen anzuzeigen, die Sie in Ihrer MySQL-Datenbank erstellt haben, verwenden Sie SQL-Abfragen in der MySQL-Befehlszeilenschnittstelle oder einem MySQL-Clienttool.

MySQL-Befehlszeilenschnittstelle

C. Datei- und Verzeichnisstruktur

Beim Einrichten einer Umgebung in Python ist es wichtig, Ihre Dateien zu organisieren. Stellen Sie sicher, dass alle Dateien im selben Projektverzeichnis gespeichert werden, wie unten gezeigt:

Datei- und Verzeichnisstruktur

D. Erstellen einer virtuellen Umgebung in Python

Eine virtuelle Umgebung ist ein isolierter Bereich, in dem Sie Python-Pakete installieren können, ohne die systemweite Python-Installation zu beeinträchtigen. Sie ist nützlich, um Abhängigkeiten für verschiedene Projekte zu verwalten.

In diesem Projekt verwenden wir Python 3. Stellen Sie sicher, dass Sie die richtige Version herunterladen und installieren.

Öffne Git-Bash oder Terminal, um den folgenden Befehl auszuführen.

1
PROJEKTORDNER$ python3 -m venv .venv

Nachdem Sie die virtuelle Umgebung erstellt haben, müssen Sie sie aktivieren.

1
PROJEKTORDNER$ . .venv/bin/activate

Erstellen Sie eine Textdatei in Ihrem Projektordner und speichern Sie sie unter PROJECT_FOLDER/requirements.txt. Diese Datei sollte die folgenden Python-Pakete enthalten, von denen unser Projekt abhängt.

1
2
3
4
5
Flasche
MySQL-Connector-Python
pyyaml
Zugriffe
SQLAlchemy

Installieren Sie die Abhängigkeiten mit dem pip Befehl.

1
PROJEKTORDNER$ pip install -r requirements.txt

Erstellen Sie im selben Verzeichnis eine Datei mit dem Namen PROJECT_FOLDER/settings.yml Dieser dient als Platzhalter für Ihre Crawlbase (TCP)-Token und Crawler Namen.

1
2
Zeichen: < >
Crawler: meinCrawlername

E. So erhalten Sie eine Liste mit LinkedIn-Profilen

Um eine Liste mit LinkedIn-Profil-URLs zu erhalten, müssen Sie diese URLs normalerweise aus verschiedenen Quellen sammeln, z. B. aus Suchergebnissen, Verbindungen oder öffentlichen Profilen. Hier sind einige Möglichkeiten, wie Sie LinkedIn-Profil-URLs erhalten können:

  1. Manuelles Sammeln:
  • Sie können LinkedIn-Profile manuell besuchen und die URLs aus der Adressleiste Ihres Webbrowsers kopieren. Diese Methode eignet sich für eine kleine Anzahl von Profilen.
  1. LinkedIn-Suchergebnisse:
  • Verwenden Sie die Suchfunktion von LinkedIn, um Profile anhand bestimmter Kriterien zu finden (z. B. Berufsbezeichnung, Standort, Branche).
  • Kopieren Sie die URLs der in den Suchergebnissen aufgelisteten Profile.
  1. Profile der Verbindungen:
  • Wenn Sie mit jemandem auf LinkedIn verbunden sind, können Sie dessen Verbindungsliste aufrufen und von dort die Profil-URLs extrahieren.
  1. API von Drittanbietern:
  • Sie können einen separaten Scraper erstellen, indem Sie Crawlbase um die Erfassung von LinkedIn-URLs zu automatisieren. Wir werden dies möglicherweise in einem zukünftigen Artikel behandeln, also bleiben Sie dran.

Für diesen Artikel haben wir eine Liste der zu scrapenden LinkedIn-URLs bereitgestellt. Standardmäßig haben wir die Textdatei mit dem Top 5 der meistgefolgten Persönlichkeiten auf LinkedIn.

Diese Datei befindet sich in PROJECT_FOLDER/urls.txt.

Hinweis: dass jede Zeile einer gültigen URL entspricht. Wenn Sie über leicht verfügbare URLs verfügen, können Sie diese Textdatei bearbeiten und sie der Liste hinzufügen.

Teil II: Schreiben von Skripten für das Projekt

A. Erstellen Sie eine ORM-Definition mit SQLAlchemy zur Interaktion mit Ihrer Datenbank

Jetzt müssen wir ein Skript für die Arbeit mit LinkedIn-bezogenen Daten in einer MySQL-Datenbank erstellen. Dieses Skript importiert zunächst die erforderlichen Module aus SQLAlchemy und das Typisierungsmodul für Typhinweise.

Zu Demonstrationszwecken speichern wir dieses Skript in PROJECT_FOLDER/lib/database.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
von Eingabe         importieren Liste
von sqlalchemie importieren Unbekannter Schlüssel
von sqlalchemie importieren Engine erstellen
von sqlalchemy.orm importieren DeklarativeBasis
von sqlalchemy.orm importieren Session
von sqlalchemy.orm importieren Mapped
von sqlalchemy.orm importieren zugeordnete_Spalte
von sqlalchemy.orm importieren Beziehung

Klasse Basis(DeklarativeBasis):
passieren

Klasse CrawlRequest(Basis):
__Tabellenname__ = 'Crawl_Anfragen'

id: Zugeordnet[int] = zugeordnete Spalte (Primärschlüssel =richtig)
URL: Zugeordnet[str]
Status: Zugeordnet[str]
crawlbase_rid: Zugeordnet[str]
linkedin_profile: Zugeordnet[„LinkedInProfil“] = Beziehung(back_populates='Crawl_Anfrage')

Klasse LinkedinProfil(Basis):
__Tabellenname__ = „linkedin_profiles“

id: Zugeordnet[int] = zugeordnete Spalte (Primärschlüssel =richtig)
Titel: Kartiert[str]
Überschrift: Kartiert[str]
Zusammenfassung: Mapped[str]
crawl_request_id: Zugeordnet[int] = zugeordnete_Spalte(Fremdschlüssel('crawl_requests.id'))
crawl_request: Zugeordnet['CrawlRequest'] = Beziehung(back_populates=„LinkedIn-Profil“)
Erfahrungen: Kartiert[Liste[„LinkedinProfileExperience“]] = Beziehung(back_populates=„LinkedIn-Profil“)

Klasse LinkedinProfilErfahrung(Basis):
__Tabellenname__ = „LinkedIn_Profil_Erfahrungen“

id: Zugeordnet[int] = zugeordnete Spalte (Primärschlüssel =richtig)
Titel: Kartiert[str]
Firmenname: Zugeordnet[str]
Beschreibung: Zugeordnet[str]
is_current: Zugeordnet[bool]
linkedin_profile_id: Zugeordnet[int] = zugeordnete_Spalte(Fremdschlüssel(„linkedin_profiles.id“))
linkedin_profile: Zugeordnet[„LinkedInProfil“] = Beziehung(back_populates='Erfahrungen')

def Datenbanksitzung erstellen
Verbindungszeichenfolge = „mysql+mysqlconnector://linkedincrawler:linked1nS3cret@localhost:3306/linkedin_crawler_db“
Engine = Engine erstellen (Verbindungszeichenfolge, Echo =richtig)
Rückkehr Sitzung(smodul)

Dieser Code bietet eine Funktion zum Erstellen einer Sitzung für die Datenbankinteraktion. Beachten Sie, dass das von uns bereitgestellte Skript voraussetzt, dass Sie die erforderlichen Bibliotheken installiert haben und ein MySQL-Server mit den angegebenen Verbindungsdetails ausgeführt wird.

B. Skript zum Senden von Anfragen an die Crawlbase Crawler

Die Crawlbase Crawler arbeitet asynchron innerhalb eines Push-Pull-Systems, das Callback-URLs verwendet. Wenn Sie Anfragen an die Crawlerweist ein eindeutige RID auf jede Anfrage. Die Crawler führt intern das Crawlen durch, bis ein erfolgreiche Antwort wird erhalten. Anschließend wird diese Antwort an Ihren angegebenen Webhook zurückgesendet, sodass Sie die Daten verarbeiten und anschließend in Ihrer Datenbank speichern können.

Weitere Einzelheiten finden Sie im vollständige Dokumentation Crawlbase Crawler.

Das Skript beginnt mit dem Importieren der erforderlichen Module, darunter „requests“ zum Stellen von HTTP-Anfragen, „urllib.parse“ zur URL-Kodierung, „json“ zur Verarbeitung von JSON-Daten und „JSONDecodeError“ zur Verarbeitung von JSON-Dekodierungsfehlern.

Zu Demonstrationszwecken speichern wir dieses Skript in PROJECT_FOLDER/crawl.py.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
importieren Zugriffe
importieren urllib.parse
importieren JSON
von JSON importieren JSONDecodeError
von lib.utils importieren Log
von lib.utils importieren Einstellungen laden
von lib.datenbank importieren CrawlRequest
von lib.datenbank importieren Datenbanksitzung erstellen

crawlbase_settings = lade_einstellungen()

crawlbase_token = crawlbase_einstellungen.get('Zeichen')
crawlbase_crawler = crawlbase_settings.get('Raupe')

if Crawlbase_Token is Keine Präsentation or crawlbase_token.strip() == '':
drucken('---------------------------------------------------------------- -')
drucken('Bitte stellen Sie Ihre Crawlbase Token in der Datei settings.yml‘)
drucken('---------------------------------------------------------------- -')
Ausfahrt()

if Crawlbase_Crawler is Keine Präsentation or crawlbase_crawler.strip() == '':
drucken('---------------------------------------------------------------- ----')
drucken('Bitte stellen Sie Ihre Crawlbase Crawler in der settings.yml‘)
drucken('---------------------------------------------------------------- ----')
Ausfahrt()

linked_in_profile_urls = XNUMXh geöffnet('urls.txt', 'r').readlines()

if len(LinkedIn-Profil-URLs) == 0:
drucken('---------------------------------------------------------------- -------------------------------------------------- --')
drucken(„Es sind keine URLs verfügbar. Bitte fügen Sie die URLs in ‚urls.txt‘ ein und trennen Sie sie durch eine neue Zeile.“)
drucken('---------------------------------------------------------------- -------------------------------------------------- --')
Ausfahrt()

Protokoll(„Fängt an zu krabbeln …“)

crawlbase_api_url = 'https://api.crawlbase.com?token={0}&callback=true&crawler={1}&url={2}&autoparse=true'

Sitzung = Datenbanksitzung erstellen()

für URL in URLs des LinkedIn-Profils:
url = url.strip()
codierte_URL = urllib.parse.quote(URL, sicher='')
API-URL = Crawlbase_API-URL.Format(Crawlbase-Token, Crawlbase-Crawler, codierte URL)

Protokoll(f'Anforderung zum Crawlen {URL}')

versuchen:
Antwort = Anfragen.get(API-URL)
json_response = json.loads(Antwort.text)
crawlbase_rid = json_antwort['loswerden']
crawl_request = CrawlRequest(url=url, crawlbase_rid=crawlbase_rid, status='Warten')
Sitzung.Hinzufügen(Crawl_Anforderung)
Sitzung.commit()
ausgeschlossen JSONDecodeError:
Protokoll(f'Beim Dekodieren der JSON-Antwort ist ein Fehler aufgetreten\n{response.text}')
ausgeschlossen:
Protokoll(f'Beim Crawlen ist ein unbekannter Fehler aufgetreten {URL}')

Protokoll(„Fertig mit Krabbeln.“)

Der Code liest die URLs aus dem PROJECT_FOLDER/urls.txt und sendet jede URL an die Crawlbase API zum Crawlen, die dann mit einer Request-ID antwortet, z. B. {”rid”: 12341234}. Der Code erstellt einen neuen Zeileneintrag, um die RID in unserem crawl_requests Tabelle mit dem Status waiting.

Bitte beachten Sie, dass wir die entsprechenden crawlbase_token mit einem crawlbase_crawler Name in diesem Skript, den wir später im Handbuch behandeln werden.

C. Erstellen eines Flask-Callback-Servers

Flasche ist ein in Python geschriebenes Mikro-Web-Framework, das wir zum Erstellen des Rückrufservers verwenden werden.

Stellen Sie sicher, dass Ihr Callback für die Base64-Dekodierung und Gzip-Dekomprimierung ausgestattet ist. Dies ist wichtig, da die Crawler Die Engine überträgt die Daten mithilfe der POST-Methode mit GZIP-Komprimierung und Base64-Kodierung an Ihren Rückrufendpunkt.

Zu Demonstrationszwecken speichern wir dieses Skript in PROJECT_FOLDER/callback_server.py.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
importieren gzip
von Flasche importieren Flasche
von Flasche importieren jsonify
von Flasche importieren Anforderung
von lib.utils importieren Log
von lib.datenbank importieren CrawlRequest
von lib.datenbank importieren Datenbanksitzung erstellen

app = Flasche(__name__)
Sitzung = Datenbanksitzung erstellen()

@app.route(„/crawlbase_crawler_callback“, Methoden=['POST'])
def Crawlbase_Crawler_Rückruf
crawlbase_rid = Anfrage.headers.get('loswerden')
content_encoding = Anfrage.headers.get('Inhaltskodierung')
original_status = Anfrage.headers.get('Original-Status')
if (kein Frontalunterricht. ursprünglicher_status is Keine Präsentation):
original_status = int(ursprünglicher_status.geteilt(',')[0])
crawlbase_status = Anfrage.headers.get('PC-Status')
if (kein Frontalunterricht. crawlbase_status is Keine Präsentation):
crawlbase_status = int(crawlbase_status.geteilt(',')[0])

if crawlbase_rid is Keine Präsentation:
Protokoll(f'Crawlbase rid ist nicht gesetzt.')
Rückkehr ('', 204)

if crawlbase_rid == 'Dummy-Anfrage':
Protokoll(„Callback-Server funktioniert“)
Rückkehr ('', 204)

if crawlbase_status != 200:
Protokoll(f'Crawlbase Status ist nicht 200.')
Rückkehr ('', 204)

if original_status != 200:
Protokoll(f'Ursprünglicher Status ist nicht 200.')
Rückkehr ('', 204)

crawl_request_does_not_exist = Sitzung.Abfrage(CrawlRequest).filter_by(crawlbase_rid=crawlbase_rid, Status='Warten').Erste() is Keine Präsentation

if crawl_request_existiert_nicht:
Protokoll(f'Nein Crawlbase zu befreien {crawlbase_rid} gefunden mit Status „Warten“.)
Rückkehr ('', 204)

crawl_request = Sitzung.Abfrage(CrawlRequest).filter_by(crawlbase_rid=crawlbase_rid, Status='Warten').scalar()

body = Anfrage.Daten
if Inhaltskodierung == 'gzip':
versuchen:
body = gzip.decompress(body)
ausgeschlossen OS-Fehler:
passieren

mit XNUMXh geöffnet(f'./Daten/{crawlbase_rid}.json', 'wb') as f:
f.write(body)

crawl_request.status = 'erhalten'
Sitzung.commit()

Protokoll(f'Crawlbase zu befreien {crawlbase_rid} wurde erfolgreich empfangen.')

Rückkehr ('', 201)

if __name__ == '__Main__':
app.run()

Dieser Code richtet eine Flask-App mit einer Route ein, um Rückrufe zu verarbeiten, die von der Crawlbase Crawler. Notiere dass der Crawlbase Crawler fügt die RID-Informationen in den Anforderungsheader mit dem Namen ein rid.

Darüber hinaus überprüft dieser Code unsere crawl_requests Tabelle für dieselbe RID mit einer waiting Status, andernfalls wird die Anfrage ignoriert.

Es stellt außerdem sicher, dass die Anforderungsheader Original-Status mit einem PC-Status sind vom HTTP 200 OK Erfolgsstatus-Antwortcode.

Sobald die gecrawlten Daten vom Crawler, wird es verarbeitet (dekodiert und dekomprimiert) und im Datenordner gespeichert und aktualisiert dann den Status der RID in received.

D. Skript zum Abrufen gecrawlter Daten und Speichern in der Datenbank

Dieser Code übernimmt die Aufgabe, den Status von RID in unserer crawl_requests-Tabelle regelmäßig zu überwachen. Wenn er erkennt, dass der Status empfangen wurde, leitet er die Datenverarbeitung ein, um sowohl die Tabellen linkedin_profiles als auch linkedin_profiles_experiences zu füllen. Nach Abschluss aktualisiert er den RID-Status auf „verarbeitet“.

Zu Demonstrationszwecken speichern wir dieses Skript in PROJECT_FOLDER/process.py.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
importieren JSON
importieren einplanen
importieren Zeit
von lib.utils importieren Log
von lib.utils importieren ist_iterierbar
von lib.datenbank importieren CrawlRequest
von lib.datenbank importieren LinkedinProfil
von lib.datenbank importieren LinkedinProfilErfahrung
von lib.datenbank importieren Datenbanksitzung erstellen

SCHEDULE_INTERVAL_IN_SECONDS = 60
RECORDS_COUNT_LIMIT_PER_PROCESSING = 10

def Prozessdefinierung
Sitzung = Datenbanksitzung erstellen()
empfangene Crawler-Anfragen = Sitzung.Abfrage(Crawler-Anfrage).Filtern_nach(Status='erhalten').limit(LIMIT_ANZAHL_PRO_VERARBEITUNG).alle()

if len(empfangene Crawling-Anfragen) == 0:
Protokoll(„Keine Crawling-Anfragen zum Verarbeiten empfangen.“)
sonst:
für Crawling-Anforderung in empfangene Crawling-Anfragen:
Protokoll(f'Verarbeitung Crawlbase zu befreien {crawl_request.crawlbase_rid} mit URL {crawl_request.url}.')

f = XNUMXh geöffnet(f'./Daten/{crawl_request.crawlbase_rid}.json')
Daten = json.load(f)

Titel = Daten.get(‚Titel‘)
Überschrift = Daten.get('Überschrift')
Zusammenfassungen = Daten.get('Zusammenfassung')
Zusammenfassung = '\n'.join(Zusammenfassungen) if is_iterable(Zusammenfassungen) sonst Keine Präsentation

linkedin_profile = LinkedinProfile(title=Titel, headline=Überschrift, summary=Zusammenfassung)
linkedin_profile.crawl_request_id = Crawler-Anforderung.id
Sitzung.add(linkedin_profile)

Erfahrungen = (data.get('Erfahrung') mit einem Daten.get('Erfahrung').erhalten(„Erfahrungsliste“)) or []
für Erfahrung in Erfahrungen:
Titel = Erfahrung.get(‚Titel‘)
Firmenname = Erfahrung.get('Unternehmen') mit einem Erfahrung.get('Unternehmen').erhalten('Süßkartoffel')
Beschreibungen = Erfahrung.get('Bezeichnung')
Beschreibung = '\n'.join(Beschreibungen) if is_iterable(Beschreibungen) sonst Keine Präsentation
ist_aktuell = Erfahrung.get('aktuellePosition') == richtig

linkedin_profile_experience = LinkedinProfileExperience(
Titel=Titel,
company_name=Firmenname,
Beschreibung=Beschreibung,
ist_aktuell=ist_aktuell
)
linkedin_profile_experience.linkedin_profile = linkedin_profil
Sitzung.add(linkedin_profile_experience)

crawl_request.status = 'verarbeitet'

Sitzung.commit()

def verarbeiten und neu planen
Prozess()
scheduler.enter(PLANUNGSINTERVALL IN SEKUNDEN, 1, verarbeiten und neu planen)

if __name__ == '__Main__':
Scheduler = sched.scheduler(Zeit.monoton, Zeit.Schlaf)
verarbeiten und neu planen()
scheduler.run()

Teil III: Ausführen der Skripte

A. Starten Sie einen lokalen Tunneldienst mit Ngrok

Ngrok ist ein Tool, das sichere Tunnel zum lokalen Host erstellt, sodass Sie Ihre lokal gehostete Webanwendung vorübergehend dem Internet zugänglich machen können.

Erstellen Sie mit Ngrok eine temporäre öffentliche URL, die auf Ihre lokal gehostete App verweist. Dadurch können wir unseren Flask Callback-Server als Webhook für die Crawlbase Crawler.

1
$ ngrok http 5000

Nach der Ausführung erhalten Sie die öffentliche URL, die wir später verwenden werden, um unsere Crawler.

Ngrok

Hinweis: Wir müssen ngrok auf Port 5000 als unsere Flask-App verweisen callback_server.py wird standardmäßig der gleiche Port verwendet.

B. Ausführen des Callback-Servers

Nachdem Ngrok initialisiert wurde, können wir unseren Callback-Server ausführen, der die RIDs und gecrawlten Inhalte abfängt von Crawlbase.

1
PROJEKTORDNER$ python callback_server.py

Basierend auf unserem Code ist dies die vollständige Route, die den Rückruf verarbeitet:

https://400d-120-29-87-188.ngrok.io/crawlbase_crawler_callback

C. Testen des Callback-Servers

Wir müssen sicherstellen, dass der Callback-Server wie erwartet funktioniert und die Crawlbase Anforderungen. Dazu können Sie den folgenden Codeausschnitt ausführen und das Ergebnis beobachten:

1
$ curl -i -X ​​POST „http://localhost:5000/crawlbase_crawler_callback“ -H „RID: Dummy-Anfrage“ -H 'Accept: application / json' -H „Inhaltstyp: gzip/json“ -H 'Benutzeragent: Crawlbase Überwachungsbot 1.0‘ -H „Inhaltskodierung: gzip“ --data-binary '"\x1F\x8B\b\x00+\xBA\x05d\x00\x03\xABV*\xCALQ\xB2RJ)\xCD\xCD\xAD,J-,M-.Q\xD2QJ\xCAO\xA9\x04\x8A*\xD5\x02\x00L\x06\xB1\xA7 \x00\x00\x00' --komprimiert

Dieser curl Der Befehl sendet eine POST-Anfrage an Ihre Rückruf-URL mit einem benutzerdefinierten HTTP-Header 'HTTP_RID' einstellen 'test'.

Nach erfolgreicher Ausführung sollten Sie eine identische Antwort wie unten dargestellt erhalten:

[app][2023-08-10 17:42:16] Callback server is working

D. Konfigurieren der Crawlbase Crawler mit Ihrer Callback-URL

Nachdem wir nun einen funktionierenden Callback-Server eingerichtet und erfolgreich eine Datenbank entworfen haben, ist es an der Zeit, eine Crawler und integrieren Sie unsere Callback-URL in Crawlbase.

Einloggen, um Crawlbase Konto und navigieren Sie zu Erschaffung Crawler Seite. Geben Sie Ihre gewünschte Crawler Name und fügen Sie die Rückruf-URL ein, die wir zuvor erstellt haben.

Erschaffung Crawler

Hinweis: Crawlbase hat die Normale Anfrage (TCP) zugewiesen Crawler für LinkedIn, also müssen wir diese Option auswählen. Obwohl Normale Anfrage ausgewählt ist, ist es erwähnenswert, dass Crawlbase setzt fortschrittliche KI-Bots mit Algorithmen ein, die menschliches Verhalten nachahmen. Zusätzlich werden Premium-Residential-Proxys eingesetzt, um die Erfolgsquote jedes Crawls weiter zu erhöhen.

E. Den Prozessor ausführen

Öffnen Sie eine neue Konsole oder ein neues Terminal im selben Verzeichnis und aktivieren Sie es.

1
PROJEKTORDNER$ . .venv/bin/activate

Initiieren des Skripts process.py

1
PROJEKTORDNER$ python process.py

Dieses Skript sollte kontinuierlich im Hintergrund ausgeführt werden, da es regelmäßig die Daten prüft, die von der Crawlbase Crawler.

F. Crawling einleiten

Bevor Sie Ihre Anfragen senden, stellen Sie bitte sicher, dass Sie alle korrekten Variablen für Ihre Skripte festgelegt haben. Holen Sie sich Ihren normalen Request/TCP-Token von der Crawlbase Konto-Seite.

Gehen Sie in das Hauptverzeichnis Ihres Projekts, öffnen Sie das PROJECT_FOLDER/settings.yml Datei und fügen Sie Ihren TCP-Token-Wert hinzu und Crawler Namen.

1
2
Zeichen: < >
Crawler: LinkedIn-Crawler

Öffnen Sie eine neue Konsole oder ein neues Terminal im selben Verzeichnis und aktivieren Sie es.

1
PROJEKTORDNER$ . .venv/bin/activate

Initiieren des Skripts crawl.py

1
PROJEKTORDNER$ python crawl.py

Nach dem Absenden Ihrer Anfrage sollten Sie feststellen, dass Ihre crawl_requests Die Datenbank wird mit der gecrawlten URL, der RID von Crawlbaseund den entsprechenden Status, wie im Screenshot unten gezeigt.

Crawling-Anfragen

Teil IV: Crawler Überwachung

Die Crawlbase Crawler ist ein vielseitiges System, das nützliche Funktionen wie Live-Monitoring bietet, mit dem Sie den Status der Anfragen unseres benutzerdefinierten Crawlers in Echtzeit verfolgen können. Um zur Seite zu gelangen, navigieren Sie einfach von Ihrem Crawler Dashboard und klicken Sie auf das Live-Monitor Tab.

Crawler Live-Monitor

Teil V: Fazit

Hier ist ein einfaches Komponenten-Flussdiagramm, das den Umfang unseres Projekts zusammenfasst:

Komponenten-Flussdiagramm

Zusammenfassend lässt sich sagen, dass dieser Leitfaden Sie auf die Reise mitgenommen hat, ein effizientes und hoch skalierbares LinkedIn-Profil zu erstellen. Crawler mit automatisierten Crawlbase. Angesichts der Herausforderungen beim Scraping von Daten aus LinkedIn bietet dieser Leitfaden eine strategische Lösung zum Abrufen wertvoller beruflicher Profilinformationen.

Crawlbase, ein Pionier im Web-Crawling, verfügt über einen speziellen Algorithmus für LinkedIn-Daten, der ein reibungsloses Scraping gewährleistet. Ziel des Projekts ist die Entwicklung eines Flask-Callback-Servers, der LinkedIn-Profile effizient und asynchron erfasst und in einer MySQL-Datenbank speichert. Wichtig ist, dass ausschließlich öffentlich zugängliche Daten gemäß den LinkedIn-Bedingungen verwendet werden.

Von der Einrichtung der Umgebung über das Schreiben von Skripten bis hin zur Codeausführung deckt dieser Leitfaden jeden wichtigen Schritt ab. Sie werden nahtlos vorankommen, indem Sie den Server testen, die Crawlbase Crawler, und zum Starten von Datenanforderungen.

Crawler Die Überwachung bietet Echtzeit-Einblicke in Ihren Fortschritt und ermöglicht Ihnen eine verbesserte Kontrolle über den Prozess. Mit diesem Leitfaden sind Sie bereit, die Leistungsfähigkeit von Crawlbase, Erstellen eines dynamischen LinkedIn-Profils Crawler das Ihre Projekte mit wertvollen LinkedIn-Erkenntnissen ankurbelt.

Besuchen Sie abschließend GitHub wenn Sie die komplette Codebasis dieses Projekts abrufen möchten.

Teil VI: Häufig gestellte Fragen

F: Wie sende ich zusätzliche Daten an meine asynchrone Anfrage und rufe sie von meinem Rückrufserver zurück?

Sie können die callback_headers Parameter an Ihre Anfrage anhängen. Nehmen wir beispielsweise an, wir möchten zusätzliche Daten anhängen wie BATCH-ID mit einem CUSTOMER-ID zu jeder Anfrage:

1
2
3
4
batch_id = „Eine Batch-ID“
Kunden-ID = 'eine-Kunden-ID'
raw_callback_headers = f'BATCH-ID:{token_id}|KUNDEN-ID:{Kunden-ID}'
codierte_callback_header = urllib.parse.quote(raw_callback_header, sicher='')

Dann fügen Sie die encoded_callback_headers zum URL-Parameter in der Anfrage.

Ejemplo:

1
crawlbase_api_url = f'https://api.crawlbase.com?token=mynormaltoken&callback=true&crawler=LinkedIn-Crawler&url=https%3A%2F%2Fwww.linkedin.com%2Fin%2Fwilliamhgates%2F&autoparse=true&callback_headers={kodierte_Rückruf_Header}'

Sie können diese Werte in unserem Callback-Server über HTTP-Anforderungsheader abrufen. In unserem Beispiel also BATCH-ID mit einem CUSTOMER-ID wird abgerufen als:

1
2
batch_id = anfrage.headers.get('Chargen-ID')
Kunden-ID = Anfrage.Header.get('KUNDEN-ID')

Weitere Informationen finden Sie in diesem Teil der Crawlbase Dokumentation.

F: Wie schütze ich meinen Webhook?

Nutze einfach das Schützen Sie den Webhook-Endpunkt mithilfe einer beliebigen Kombination der folgenden Methoden:

  • Fügen Sie Ihrer Anfrage einen benutzerdefinierten Header hinzu, der ein Token enthält, dessen Vorhandensein Sie im Webhook überprüfen.
  • Verwenden Sie einen URL-Parameter in Ihrer URL und prüfen Sie während der Webhook-Anforderung, ob dieser vorhanden ist. Beispiel: yourdomain.com/2340JOiow43djoqe21rjosi?token=1234.
  • Beschränken Sie die Annahme ausschließlich auf POST-Anfragen.
  • Überprüfen Sie das Vorhandensein bestimmter erwarteter Header, wie z. B. Pc-Status, Original-Status, rid, usw.

Als Randbemerkung raten wir von IP-Whitelists ab, da unsere Crawler möglicherweise von verschiedenen IPs stammen und diese IPs ohne vorherige Ankündigung geändert werden könnten.

Die Rechtmäßigkeit von Web Scraping, wie auch das Scraping von LinkedIn-Daten, ist komplex. Fall hiQ Labs gegen LinkedIn Corp, entschied der Neunte Bezirk, dass das Scraping öffentlich verfügbarer Daten möglicherweise nicht gegen den Computer Fraud and Abuse Act (CFAA) verstößt. Dies ist jedoch spezifisch für diese Gerichtsbarkeit und Auslegung des CFAA. Die Rechtmäßigkeit von Web Scraping hängt von Faktoren wie der Art der Daten, den verwendeten Methoden, Vereinbarungen und den Gesetzen der Gerichtsbarkeit ab.

Das Scraping urheberrechtlich geschützter Inhalte oder die Missachtung von Nutzungsbedingungen kann zu rechtlichen Problemen führen. Deshalb Crawlbase erlaubt nur das Scraping öffentlich verfügbarer Daten – Daten, auf die ohne Anmeldesitzung zugegriffen werden kann.

Wenn Sie weitere Erläuterungen dazu benötigen, wie dies auf Ihre Situation zutrifft, empfehlen wir Ihnen, sich für eine genaue Anleitung an einen Rechtsexperten zu wenden.

F. Welche anderen Arten von Benutzerdaten kann ich erhalten von Crawlbase LinkedIn-Scraper?

Die wertvollsten und am häufigsten aus LinkedIn-Profilen extrahierten Daten sind die folgenden:

  1. Name: Der vollständige Name des Benutzers.
  2. Überschrift/Beruf: Eine kurze Beschreibung der beruflichen Rolle oder des Fachwissens des Benutzers.
  3. Anzahl der Verbindungen: Die Anzahl der Verbindungen, die der Benutzer auf LinkedIn hat.
  4. Standort: Der geografische Standort des Benutzers.
  5. Titelbild: Ein optionales Bannerbild, das oben im Profil des Benutzers angezeigt wird.
  6. Profilbild: Das Profilbild des Benutzers.
  7. Profil-URL: Die eindeutige Webadresse des LinkedIn-Profils des Benutzers.
  8. Positionsinfo: Details zu den aktuellen und früheren Positionen des Benutzers.
  9. Bildungsinfo: Informationen zum Bildungshintergrund des Benutzers.
  10. Erfahrung: Ein umfassender Überblick über die Berufserfahrung und den beruflichen Werdegang des Benutzers.
  11. Aktivitäten: Benutzergenerierte Beiträge, Artikel und andere Aktivitäten auf LinkedIn.
  12. Qualifikationen: Zusätzliche Zertifizierungen oder Qualifikationen, die der Benutzer erworben hat.
  13. Organisationen: Details zu Organisationen, denen der Benutzer angehört.

F: Warum Flask für Webhook verwenden?

  1. Anpassung: Flask ist ein Python-Webframework, mit dem Sie einen hochgradig anpassbaren Webhook-Endpunkt erstellen können. Sie können das Verhalten, die Authentifizierung und die Verarbeitungslogik entsprechend Ihren spezifischen Anforderungen definieren.
  2. Flexibilität: Flask bietet Ihnen die Flexibilität, verschiedene Arten eingehender Daten zu verarbeiten, z. B. JSON, Formulardaten oder Dateien. Dies ist wichtig, wenn Sie mit verschiedenen Arten von Webhook-Nutzlasten arbeiten.
  3. Integration: Flask-Callback-Server lassen sich problemlos in Ihre vorhandenen Python-basierten Anwendungen oder Dienste integrieren. So können Sie Webhook-Daten bequem in Ihre Workflows integrieren.
  4. Authentifizierung und Sicherheit: Sie können Authentifizierungsmechanismen und Sicherheitsmaßnahmen in Ihrem Flask-Webhook-Server implementieren, um sicherzustellen, dass nur autorisierte Quellen den Server auslösen können.
  5. Debuggen und Protokollieren: Flask bietet Tools zum Debuggen und Protokollieren, die bei der Überwachung des Verhaltens Ihres Webhook-Servers und der Diagnose etwaiger Probleme äußerst nützlich sein können.
  6. Skalierung und Bereitstellung: Flask-Anwendungen können in verschiedenen Hosting-Umgebungen bereitgestellt werden, sodass Sie Ihren Webhook-Server nach Bedarf skalieren können.
  7. Community und Ressourcen: Flask verfügt über eine große und aktive Community. Das heißt, Sie können problemlos Tutorials, Dokumentationen und Pakete von Drittanbietern finden, die Ihnen beim Erstellen und Warten Ihres Webhook-Servers helfen.

F: Warum ein komplexeres asynchrones Crawling anstelle eines synchronen durchführen?

Beim synchronen Crawling werden Aufgaben sequenziell verarbeitet. Dies kann einfacher, aber langsamer sein, insbesondere wenn Wartezeiten erforderlich sind. Beim asynchronen Crawling werden Aufgaben gleichzeitig verarbeitet, was zu einer verbesserten Leistung und Ressourcennutzung führt. Es eignet sich auch perfekt für die gleichzeitige Verarbeitung einer großen Anzahl von Aufgaben.

Die Implementierung ist komplexer und das Debuggen kann anspruchsvoller sein, aber in diesem Fall überwiegen die Vorteile deutlich die Nachteile. Deshalb Crawlbase drängt auf asynchrones Crawlen für LinkedIn.