Einleitung

LinkedIn ist dafür berüchtigt, die Automatisierung beim Scraping seiner Daten zu blockieren. Wie stellen Sie sicher, dass Sie die begehrten beruflichen Profildaten für Ihr Unternehmen erfolgreich abrufen können?

Wenn es sich hierbei um ein großes Problem handelt, das Sie lösen möchten, dann erwartet Sie eine Freude.

Crawlbase ist sich der Fülle an Möglichkeiten, die das Crawlen von LinkedIn-Daten mit sich bringt, voll bewusst. Als Pionier im Internet-Crawling ist Crawlbase auf die Erfassung von LinkedIn-Daten spezialisiert und verfügt über einen einzigartigen Algorithmus, der ein erfolgreiches Scraping-Erlebnis gewährleistet, das speziell auf LinkedIn-Daten zugeschnitten ist.

Den Projektumfang verstehen

In dieser Anleitung wird gezeigt, wie Sie mit Flask einen robusten Callback-Server erstellen. Dieser Server fungiert als Webhook für die Crawlbase Crawler, wodurch das asynchrone Abrufen von LinkedIn-Benutzerprofilen erleichtert wird. Der Schwerpunkt liegt dabei auf der Analyse des Abschnitts „Erfahrung“ und der Speicherung in einer MySQL-Datenbank. Dieser Prozess optimiert die Erfassung wichtiger Daten, die für Folgendes verwendet werden können:

  1. Talentsuche und Rekrutierung
  2. HR und Personalentwicklung
  3. Marktinformationen und -analysen
  4. Prädiktive Datenanalyse
  5. KI- und maschinelle Lernalgorithmen

Beim Umgang mit solchen Daten müssen unbedingt die Nutzungsbedingungen und Datenschutzrichtlinien von LinkedIn eingehalten werden. Crawlbase verbietet strengstens das Extrahieren privater Daten von LinkedIn oder anderen Websites. Das hier aufgeführte Beispiel basiert ausschließlich auf öffentlich zugänglichen Daten und dient Bildungszwecken.

Lass uns anfangen.

Table of Contents:

Teil I: Vorbereiten der Umgebung

a. Crawlbase-Konto erstellen und LinkedIn-Crawling aktivieren
b. Einrichten einer MySQL-Datenbank
c. Datei- und Verzeichnisstruktur
d. Erstellen einer virtuellen Umgebung in Python
e. So erhalten Sie eine Liste mit LinkedIn-Profilen

Teil II: Schreiben von Skripten für das Projekt

a. Erstellen Sie eine ORM-Definition mit SQLAlchemy zur Interaktion mit Ihrer Datenbank
b. Skript zum Senden von Anfragen an die Crawlbase Crawler
c. Erstellen eines Flask-Callback-Servers
d. Skript zum Abrufen gecrawlter Daten und Speichern in der Datenbank

Teil III: Ausführen der Skripte

a. Starten Sie einen lokalen Tunneldienst mit Ngrok
b. Ausführen des Callback-Servers
c. Testen des Callback-Servers
d. Konfigurieren der Crawlbase Crawler mit Ihrer Callback-URL
e. Führen Sie den Prozessor aus
f. Crawling einleiten

Teil IV: Crawler Netzwerk Performance

Teil VI: Fazit

Teil VI: Häufig gestellte Fragen

Teil I: Vorbereiten der Umgebung

A. Erstellen eines Crawlbase-Kontos und Aktivieren des LinkedIn-Crawlings

  1. Besuchen Sie zunächst die 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
CREATE TABELLE IF NICHT VORHANDEN `crawl_requests` (
`Id` INT AUTO_INCREMENT PRIMARY SCHLÜSSEL,
`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
CREATE TABELLE IF NICHT VORHANDEN `linkedin_profiles` (
`Id` INT AUTO_INCREMENT PRIMARY SCHLÜSSEL,
`crawl_request_id` INT NICHT NULL,
`Titel` VARCHAR(255),
`Überschrift` VARCHAR(255),
`Zusammenfassung` TEXT,

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

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

AUSLÄNDISCH SCHLÜSSEL (`linkedin_profile_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.

Öffnen 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 welches als Platzhalter für Ihr Crawlbase (TCP)-Token dient 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 mithilfe von Crawlbase einen separaten Scraper erstellen, um die Erfassung von LinkedIn-URLs zu automatisieren. Möglicherweise behandeln wir dies in einem zukünftigen Artikel, 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
für Eingabe         importieren Liste
für sqlalchemie importieren Unbekannter Schlüssel
für sqlalchemie importieren Engine erstellen
für sqlalchemy.orm importieren DeklarativeBasis
für sqlalchemy.orm importieren Session
für sqlalchemy.orm importieren Mapped
für sqlalchemy.orm importieren zugeordnete_Spalte
für sqlalchemy.orm importieren Beziehung

Klasse Basis(DeklarativeBasis):
passieren

Klasse CrawlRequest(Basis):
__Tabellenname__ = 'Crawl_Anfragen'

id: Zugeordnet[int] = zugeordnete Spalte (Primärschlüssel =Wahre)
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 =Wahre)
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 =Wahre)
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 =Wahre)
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 der 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
für JSON importieren JSONDecodeError
für lib.utils importieren Log
für lib.utils importieren Einstellungen laden
für lib.datenbank importieren CrawlRequest
für 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 or crawlbase_token.strip() == '':
drucken('---------------------------------------------------------------- -')
drucken(„Bitte legen Sie Ihr Crawlbase-Token in der Datei settings.yml fest.“)
drucken('---------------------------------------------------------------- -')
Ausfahrt()

if Crawlbase_Crawler is Keine or crawlbase_crawler.strip() == '':
drucken('---------------------------------------------------------------- ----')
drucken(„Bitte legen Sie Ihren Crawlbase-Crawler in der Datei settings.yml fest.“)
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 zum Crawlen an die Crawlbase-API, die dann mit einer Anforderungs-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 und 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
für Flasche importieren Flasche
für Flasche importieren jsonify
für Flasche importieren Anforderung
für lib.utils importieren Log
für lib.datenbank importieren CrawlRequest
für 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 (nicht ursprünglicher_status is Keine):
original_status = int(ursprünglicher_status.geteilt(',')[0])
crawlbase_status = Anfrage.headers.get('PC-Status')
if (nicht crawlbase_status is Keine):
crawlbase_status = int(crawlbase_status.geteilt(',')[0])

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

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

if crawlbase_status != 200:
Protokoll(„Der 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

if crawl_request_existiert_nicht:
Protokoll(f'Kein Crawlbase-Rind {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 los {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 von der Crawlbase zu verarbeiten Crawler. Beachten Sie, dass die 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 und 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
für lib.utils importieren Log
für lib.utils importieren ist_iterierbar
für lib.datenbank importieren CrawlRequest
für lib.datenbank importieren LinkedinProfil
für lib.datenbank importieren LinkedinProfilErfahrung
für 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 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

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') und Daten.get('Erfahrung').erhalten(„Erfahrungsliste“)) or []
für ERFAHRUNGEN in Erfahrungen:
Titel = Erfahrung.get(‚Titel‘)
Firmenname = Erfahrung.get('Unternehmen') und Erfahrung.get('Unternehmen').erhalten('Süßkartoffel')
Beschreibungen = Erfahrung.get('Bezeichnung')
Beschreibung = '\n'.join(Beschreibungen) if is_iterable(Beschreibungen) sonst Keine
ist_aktuell = Erfahrung.get('aktuellePosition') == Wahre

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 verwenden. 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 nun initialisiert wurde, können wir unseren Callback-Server ausführen, der die RIDs und gecrawlten Inhalte von Crawlbase abfängt.

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 „Benutzer-Agent: 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

Dieses 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 Rückruf-URL in Crawlbase.

Melden Sie sich bei Ihrem Crawlbase-Konto an und navigieren Sie zu Erstellen Crawler Seite. Geben Sie Ihre gewünschte Crawler Name und fügen Sie die Rückruf-URL ein, die wir zuvor erstellt haben.

Erstellen Crawler

Hinweis: Crawlbase hat die normale Anfrage (TCP) zugewiesen Crawler für LinkedIn, also müssen wir diese Option auswählen. Auch wenn die normale Anfrage ausgewählt ist, ist es erwähnenswert, dass Crawlbase fortschrittliche KI-Bots mit Algorithmen verwendet, die menschliches Verhalten nachahmen sollen. Darüber hinaus werden Premium-Residential-Proxys verwendet, um die Erfolgsrate jedes Crawls weiter zu verbessern.

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 nach Daten sucht, die von der Crawlbase kommen. 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-Kontoseite.

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 Crawlbase und dem entsprechenden Status gefüllt, wie im Screenshot unten gezeigt.

Crawling-Anfragen

Teil IV: Crawler Netzwerk Performance

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

Definition der Begriffe

Krabbelt - Die Gesamtzahl der erfolgreichen Crawls

Schlägt fehl - Die Anzahl der internen Crawl-Fehler (kostenlos)

Gleichzeitige Crawls – Die Anzahl der Anfragen, die zu einem bestimmten Zeitpunkt gleichzeitig gecrawlt werden.

Warten - Anfragen, die sich derzeit in der Warteschlange befinden und darauf warten, gecrawlt zu werden.

Zu wiederholende Sets - Die Anzahl der Anfragen, die wiederholt werden müssen. Crawler versucht, die Ziel-URLs bis zu 110 Mal zu crawlen oder bis eine erfolgreiche Antwort eingeht.

Sobald die Crawler Wenn ein Crawl erfolgreich abgeschlossen wird, werden die Daten an Ihren Callback-Server zurückgesendet. Daher ist es wichtig, die Verfügbarkeit des Servers jederzeit aufrechtzuerhalten. Ihre Datenbanktabellen linkedin_profiles und linkedin_profile_experiences sollten automatisch aktualisiert werden, sobald sie die Scraped-Daten empfangen, sodass kein manuelles Eingreifen erforderlich ist.

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 Crawlbase. Dieser Leitfaden stellt sich den Herausforderungen des Scraping von Daten aus LinkedIn und bietet eine strategische Lösung zum Abrufen wertvoller beruflicher Profilinformationen.

Crawlbase, ein Pionier im Bereich Web-Crawling, verfügt über einen speziellen Algorithmus, der für LinkedIn-Daten entwickelt wurde und ein reibungsloses Scraping-Erlebnis gewährleistet. Das Projekt zielt darauf ab, einen Flask-Callback-Server zu erstellen, der LinkedIn-Profile effizient und asynchron erfasst und in einer MySQL-Datenbank speichert. Es ist wichtig zu beachten, dass nur öffentlich verfügbare Daten gemäß den Bedingungen von LinkedIn verwendet werden.

Von der Einrichtung der Umgebung und dem 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 konfigurieren Crawler, und zum Starten von Datenanforderungen.

Crawler Die Überwachung bietet Echtzeiteinblicke, während Sie voranschreiten, und bietet eine verbesserte Kontrolle über den Prozess. Mit diesem Leitfaden sind Sie bereit, die Leistungsfähigkeit von Crawlbase zu nutzen und ein dynamisches LinkedIn-Profil zu erstellen 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 und 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.

Beispiel:

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 und 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?

Du kannst dich 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 Scrapen von urheberrechtlich geschützten Inhalten oder die Missachtung von Nutzungsbedingungen kann zu rechtlichen Problemen führen. Aus diesem Grund erlaubt Crawlbase nur das Scrapen von öffentlich verfügbaren Daten – Daten, auf die ohne Anmeldung 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 vom Crawlbase LinkedIn Scraper erhalten?

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 die Nachteile bei weitem. Aus diesem Grund drängt Crawlbase auf asynchrones Crawling für LinkedIn.