bugfix
This commit is contained in:
@@ -1537,41 +1537,52 @@ def process_contacts():
|
||||
# Weitere Verarbeitung der Kontakte folgt hier ...
|
||||
|
||||
# ==================== LINKEDIN HELPER ====================
|
||||
def search_linkedin_contact(company_name, website, position_query, crm_kurzform):
|
||||
def search_linkedin_contacts(company_name, website, position_query, crm_kurzform, num_results=100):
|
||||
"""
|
||||
Sucht über SERPAPI einen einzelnen LinkedIn-Kontakt basierend auf der Positionsbezeichnung und der CRM-Kurzform des Unternehmens.
|
||||
Es wird nur ein Treffer zurückgegeben, wenn der Titel auch die CRM-Kurzform (als Teilstring) enthält.
|
||||
Sucht über SERPAPI mehrere LinkedIn-Kontakte basierend auf der Positionsbezeichnung
|
||||
und der CRM-Kurzform des Unternehmens. Es werden alle Treffer zurückgegeben, bei denen
|
||||
die CRM-Kurzform (als Teilstring) im Titel auftaucht.
|
||||
|
||||
Args:
|
||||
company_name (str): Der Firmenname.
|
||||
website (str): Die Website des Unternehmens.
|
||||
position_query (str): Die zu suchende Positionsbezeichnung (z. B. "Serviceleiter").
|
||||
crm_kurzform (str): Die manuell gepflegte Kurzform des Firmennamens.
|
||||
num_results (int): Anzahl der abzurufenden Suchergebnisse (hier standardmäßig 100).
|
||||
|
||||
Returns:
|
||||
dict oder None: Ein Dictionary mit den Kontaktdaten (Vorname, Nachname, Position, LinkedInURL) oder None, falls kein passender Kontakt gefunden wurde.
|
||||
list: Eine Liste von Dictionaries mit den Kontaktdaten (Vorname, Nachname, Position, LinkedInURL)
|
||||
oder eine leere Liste, wenn keine Treffer gefunden wurden.
|
||||
"""
|
||||
try:
|
||||
with open("serpApiKey.txt", "r") as f:
|
||||
serp_key = f.read().strip()
|
||||
except Exception as e:
|
||||
debug_print("Fehler beim Lesen des SerpAPI-Schlüssels: " + str(e))
|
||||
return None
|
||||
|
||||
return []
|
||||
|
||||
query = f'site:linkedin.com/in "{position_query}" "{company_name}"'
|
||||
params = {
|
||||
"engine": "google",
|
||||
"q": query,
|
||||
"api_key": serp_key,
|
||||
"hl": "de"
|
||||
"hl": "de",
|
||||
"num": num_results
|
||||
}
|
||||
|
||||
# Logge die vollständige Such-URL
|
||||
request_url = "https://serpapi.com/search?" + urlencode(params)
|
||||
debug_print(f"Such-URL: {request_url}")
|
||||
|
||||
try:
|
||||
response = requests.get("https://serpapi.com/search", params=params, timeout=10)
|
||||
data = response.json()
|
||||
contacts = []
|
||||
if "organic_results" in data and len(data["organic_results"]) > 0:
|
||||
for result in data["organic_results"]:
|
||||
title = result.get("title", "")
|
||||
if crm_kurzform.lower() in title.lower():
|
||||
# Aufteilen des Titels in Namens- und Positionsbestandteile
|
||||
if "–" in title:
|
||||
parts = title.split("–")
|
||||
elif "-" in title:
|
||||
@@ -1589,22 +1600,22 @@ def search_linkedin_contact(company_name, website, position_query, crm_kurzform)
|
||||
lastname = ""
|
||||
linkedin_url = result.get("link", "")
|
||||
debug_print(f"Gefundener Kontakt: {firstname} {lastname}, Position: {pos_part}")
|
||||
return {
|
||||
contacts.append({
|
||||
"Firmenname": company_name,
|
||||
"Website": website,
|
||||
"Vorname": firstname,
|
||||
"Nachname": lastname,
|
||||
"Position": pos_part,
|
||||
"LinkedInURL": linkedin_url
|
||||
}
|
||||
debug_print("Kein Treffer mit CRM-Kurzform in Titel gefunden.")
|
||||
return None
|
||||
})
|
||||
if not contacts:
|
||||
debug_print("Kein Treffer mit CRM-Kurzform in Titel gefunden.")
|
||||
else:
|
||||
debug_print("Keine organic_results für Query gefunden.")
|
||||
return None
|
||||
return contacts
|
||||
except Exception as e:
|
||||
debug_print(f"Fehler bei der SerpAPI-Suche: {e}")
|
||||
return None
|
||||
debug_print(f"Fehler bei der SERPAPI-Suche: {e}")
|
||||
return []
|
||||
|
||||
def count_linkedin_contacts(company_name, website, position_query, crm_kurzform):
|
||||
"""
|
||||
@@ -1772,12 +1783,9 @@ def count_linkedin_contacts(company_name, website, position_query, crm_kurzform)
|
||||
|
||||
def process_contact_research():
|
||||
"""
|
||||
Sucht mithilfe der SerpAPI Kontakte für bestimmte Positionen für jedes Unternehmen.
|
||||
Es werden zunächst die CRM-Daten (insbesondere CRM Kurzform in Spalte C) sowie Firma und Website aus dem Hauptblatt gelesen.
|
||||
Die gefundenen Kontakte, welche den Filter (CRM Kurzform muss im Titel enthalten sein) erfüllen, werden im Kontakte-Blatt eingetragen.
|
||||
|
||||
Zusätzlich werden die Trefferzahlen (als Summen pro Position) in das Hauptblatt in den Spalten AI, AJ, AK, AL geschrieben
|
||||
und ein Timestamp in Spalte AM gesetzt.
|
||||
Sucht mithilfe der SERPAPI Kontakte für bestimmte Positionen für jedes Unternehmen.
|
||||
Die gefundenen Kontakte werden im Kontakte-Blatt eingetragen – pro Kategorie werden alle
|
||||
Treffer (die den Filter (CRM-Kurzform muss im Titel enthalten sein) erfüllen) verarbeitet.
|
||||
|
||||
Im Kontakte-Blatt wird folgende Spaltenstruktur verwendet:
|
||||
A: Firmenname
|
||||
@@ -1791,8 +1799,6 @@ def process_contact_research():
|
||||
I: E-Mail-Adresse
|
||||
J: LinkedIn-Link
|
||||
K: Timestamp
|
||||
|
||||
Detaillierte Debug-Ausgaben sorgen für Transparenz bei der Ausführung.
|
||||
"""
|
||||
debug_print("Starte Contact Research (Modus 6)...")
|
||||
# Verbinde zum Hauptblatt
|
||||
@@ -1802,20 +1808,20 @@ def process_contact_research():
|
||||
main_sheet = sh.sheet1
|
||||
data = main_sheet.get_all_values()
|
||||
|
||||
# Ermittle die letzte Zeile in Spalte AM (Spalte 39), in der ein Timestamp eingetragen wurde
|
||||
col_am = main_sheet.col_values(39) # Spalte AM hat den Index 39 (A=1, ..., AM=39)
|
||||
last_filled_row = 1 # Header-Zeile
|
||||
# Ermittle die letzte Zeile in Spalte AM (Spalte 39) mit einem Timestamp
|
||||
col_am = main_sheet.col_values(39)
|
||||
last_filled_row = 1
|
||||
for idx, cell in enumerate(col_am):
|
||||
if cell.strip() != "":
|
||||
last_filled_row = idx + 1
|
||||
start_row = last_filled_row + 1
|
||||
debug_print(f"Letzter Timestamp in Spalte AM wurde in Zeile {last_filled_row} gefunden. Starte Verarbeitung ab Zeile {start_row}.")
|
||||
debug_print(f"Letzter Timestamp in Spalte AM in Zeile {last_filled_row}. Starte Verarbeitung ab Zeile {start_row}.")
|
||||
|
||||
if start_row > len(data):
|
||||
debug_print("Keine neuen Zeilen zu verarbeiten, da Timestamp in Spalte AM bereits bis zum Ende vorhanden ist.")
|
||||
debug_print("Keine neuen Zeilen zu verarbeiten, da Timestamp in Spalte AM bis zum Ende vorhanden ist.")
|
||||
return
|
||||
|
||||
# Kontakte-Blatt öffnen oder erstellen
|
||||
# Kontakte-Blatt öffnen oder erstellen (Header: A-K)
|
||||
try:
|
||||
contacts_sheet = sh.worksheet("Contacts")
|
||||
except gspread.exceptions.WorksheetNotFound:
|
||||
@@ -1825,7 +1831,7 @@ def process_contact_research():
|
||||
contacts_sheet.update(values=[header], range_name="A1:K1")
|
||||
debug_print("Neues Blatt 'Contacts' erstellt und Header eingetragen.")
|
||||
|
||||
# Verarbeite jede Zeile ab der ermittelten Startzeile
|
||||
# Gehe alle Zeilen im Hauptblatt ab der Startzeile durch
|
||||
for i in range(start_row, len(data) + 1):
|
||||
row = data[i - 1]
|
||||
company_name = row[1] if len(row) > 1 else ""
|
||||
@@ -1840,16 +1846,16 @@ def process_contact_research():
|
||||
for pos in positions:
|
||||
count = count_linkedin_contacts(crm_kurzform, website, pos, crm_kurzform)
|
||||
contact_counts[pos] = count
|
||||
contact = search_linkedin_contact(crm_kurzform, website, pos, crm_kurzform)
|
||||
if contact:
|
||||
# Abfrage: Es sollen nun alle Treffer (bis zu 100) verarbeitet werden
|
||||
contacts = search_linkedin_contacts(crm_kurzform, website, pos, crm_kurzform, num_results=100)
|
||||
for contact in contacts:
|
||||
firstname = contact.get("Vorname", "")
|
||||
lastname = contact.get("Nachname", "")
|
||||
gender_value = get_gender(firstname) if firstname else "unknown"
|
||||
email = get_email_address(firstname, lastname, website)
|
||||
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
# Neue Reihenfolge:
|
||||
# A: Firmenname, B: CRM Kurzform, C: Website, D: Geschlecht, E: Vorname, F: Nachname,
|
||||
# G: Position, H: Suchbegriffskategorie, I: E-Mail-Adresse, J: LinkedIn-Link, K: Timestamp
|
||||
# Spaltenanordnung: A: Firmenname, B: CRM Kurzform, C: Website, D: Geschlecht, E: Vorname,
|
||||
# F: Nachname, G: Position, H: Suchbegriffskategorie, I: E-Mail-Adresse, J: LinkedIn-Link, K: Timestamp
|
||||
contact_row = [
|
||||
company_name,
|
||||
crm_kurzform,
|
||||
@@ -1865,13 +1871,10 @@ def process_contact_research():
|
||||
]
|
||||
try:
|
||||
contacts_sheet.append_row(contact_row)
|
||||
debug_print(f"Zeile {i}: Kontakt für Position '{pos}' in Contacts gespeichert: {contact_row}")
|
||||
debug_print(f"Zeile {i}: Kontakt für '{pos}' gespeichert: {contact_row}")
|
||||
except Exception as e:
|
||||
debug_print(f"Zeile {i}: Fehler beim Speichern des Kontakts in Contacts: {e}")
|
||||
else:
|
||||
debug_print(f"Zeile {i}: Kein passender Kontakt für Position '{pos}' gefunden.")
|
||||
|
||||
# Aktualisiere Hauptblatt-Zeile mit Trefferzahlen und Timestamp
|
||||
debug_print(f"Zeile {i}: Fehler beim Speichern des Kontakts für '{pos}': {e}")
|
||||
# Aktualisiere Trefferzahlen und Timestamp im Hauptblatt
|
||||
try:
|
||||
main_sheet.update(values=[[str(contact_counts.get("Serviceleiter", 0))]], range_name=f"AI{i}")
|
||||
main_sheet.update(values=[[str(contact_counts.get("IT-Leiter", 0))]], range_name=f"AJ{i}")
|
||||
|
||||
Reference in New Issue
Block a user