Jobbörsen wie Indeed, LinkedIn und Glassdoor setzen CAPTCHAs ein, wenn sie automatisierte Zugriffsmuster erkennen. Rekrutierungsplattformen, Marktforscher und HR-Analysetools benötigen zuverlässige CAPTCHA-Lösungen, um Daten zu Stellenangeboten in großem Umfang zu sammeln.
CAPTCHAs auf wichtigen Jobbörsen
| Plattform | CAPTCHA-Typ | Auslöser | Daten verfügbar |
|---|---|---|---|
| Tatsächlich | reCAPTCHA v2 | Hohes Anfragevolumen | Stellenangebote, Gehälter |
| Cloudflare Challenge | Bot-Erkennung | Jobs, Unternehmensdaten | |
| Glastür | reCAPTCHA v2 | Kratzerkennung | Bewertungen, Gehälter, Jobs |
| ZipRecruiter | Cloudflare Turnstile | Automatisierter Zugriff | Stellenangebote |
| Monster | reCAPTCHA v2 | Suchseiten | Stellenangebote |
| CareerBuilder | reCAPTCHA v3 | Einloggen, suchen | Stellenangebote, Lebenslaufsuche |
Jobbörsen-Scraper mit CAPTCHA-Verwaltung
import requests
import time
import re
from bs4 import BeautifulSoup
CAPTCHAAI_KEY = "YOUR_API_KEY"
CAPTCHAAI_URL = "https://ocr.captchaai.com"
def solve_captcha(method, sitekey, pageurl, **kwargs):
data = {
"key": CAPTCHAAI_KEY,
"method": method,
"googlekey": sitekey,
"pageurl": pageurl,
"json": 1,
}
data.update(kwargs)
resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data=data)
task_id = resp.json()["request"]
for _ in range(60):
time.sleep(5)
result = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
"key": CAPTCHAAI_KEY, "action": "get",
"id": task_id, "json": 1,
})
r = result.json()
if r["request"] != "CAPCHA_NOT_READY":
return r["request"]
raise TimeoutError("Solve timeout")
class JobBoardScraper:
def __init__(self, proxy=None):
self.session = requests.Session()
if proxy:
self.session.proxies = {"http": proxy, "https": proxy}
self.session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 Chrome/126.0.0.0 Safari/537.36",
"Accept-Language": "en-US,en;q=0.9",
})
def search_jobs(self, base_url, query, location, pages=5):
"""Search job listings across multiple pages."""
all_jobs = []
for page in range(pages):
url = f"{base_url}/jobs?q={query}&l={location}&start={page * 10}"
resp = self.session.get(url, timeout=30)
# Check for CAPTCHA
if self._has_captcha(resp.text):
resp = self._solve_and_retry(resp.text, url)
if resp.status_code == 200:
jobs = self._parse_listings(resp.text)
all_jobs.extend(jobs)
print(f"Page {page + 1}: {len(jobs)} jobs found")
else:
print(f"Page {page + 1}: Request failed ({resp.status_code})")
time.sleep(3) # Rate limit
return all_jobs
def _has_captcha(self, html):
indicators = [
'data-sitekey=',
'g-recaptcha',
'cf-turnstile',
'captcha-delivery',
]
return any(ind in html.lower() for ind in indicators)
def _solve_and_retry(self, html, url):
# Try reCAPTCHA first
match = re.search(r'data-sitekey="([^"]+)"', html)
if match:
sitekey = match.group(1)
# Detect Turnstile vs reCAPTCHA
if 'cf-turnstile' in html:
token = solve_captcha("turnstile", sitekey, url)
field = "cf-turnstile-response"
else:
token = solve_captcha("userrecaptcha", sitekey, url)
field = "g-recaptcha-response"
return self.session.post(url, data={field: token})
return self.session.get(url)
def _parse_listings(self, html):
soup = BeautifulSoup(html, "html.parser")
jobs = []
for card in soup.select(".job_seen_beacon, .jobsearch-ResultsList > li"):
title_el = card.select_one("h2 a, .jobTitle a")
company_el = card.select_one(".companyName, [data-testid='company-name']")
location_el = card.select_one(".companyLocation, [data-testid='text-location']")
salary_el = card.select_one(".salary-snippet, .estimated-salary")
if title_el:
jobs.append({
"title": title_el.get_text(strip=True),
"company": company_el.get_text(strip=True) if company_el else "",
"location": location_el.get_text(strip=True) if location_el else "",
"salary": salary_el.get_text(strip=True) if salary_el else "",
"url": title_el.get("href", ""),
})
return jobs
# Usage
scraper = JobBoardScraper(
proxy="http://user:pass@residential.proxy.com:5000"
)
jobs = scraper.search_jobs(
base_url="https://jobs.example.com",
query="python developer",
location="New York",
pages=10,
)
print(f"Total jobs collected: {len(jobs)}")
Gehaltsdatenerfassung
import csv
def collect_salary_data(titles, locations, output_file):
"""Collect salary data across job titles and locations."""
scraper = JobBoardScraper(
proxy="http://user:pass@residential.proxy.com:5000"
)
results = []
for title in titles:
for location in locations:
try:
jobs = scraper.search_jobs(
"https://jobs.example.com",
title, location, pages=3,
)
salaries = [j["salary"] for j in jobs if j["salary"]]
results.append({
"title": title,
"location": location,
"listings": len(jobs),
"with_salary": len(salaries),
"salary_samples": "; ".join(salaries[:5]),
})
time.sleep(5)
except Exception as e:
results.append({
"title": title,
"location": location,
"error": str(e),
})
with open(output_file, "w", newline="") as f:
writer = csv.DictWriter(
f, fieldnames=["title", "location", "listings",
"with_salary", "salary_samples", "error"],
)
writer.writeheader()
writer.writerows(results)
return results
# Collect salary data for market analysis
collect_salary_data(
titles=["Data Engineer", "ML Engineer", "DevOps Engineer"],
locations=["San Francisco", "New York", "Austin", "Remote"],
output_file="salary_data.csv",
)
Anti-Erkennungs-Tipps für Jobmärkte
| Technik | Warum es hilft |
|---|---|
| Rotierende Wohn-Proxys | Verteilt Anfragen über echte IPs |
| 3–5 Sekunden Verzögerung zwischen den Seiten | Imitiert die menschliche Surfgeschwindigkeit |
| Konsistenter User-Agent pro Sitzung | Verhindert Fehlanpassungen von Browser-Signalprofilen |
| Akzeptieren Sie Cookies | Jobbörsen verfolgen Sitzungen über Cookies |
| Suchreihenfolge zufällig festlegen | Vermeiden Sie sequentielle Seitenmuster |
| Beschränkung auf 200 Seiten/day pro Domain | Bleiben Sie unter den Erkennungsschwellen |
Fehlerbehebung
| Problem | Ursache | Lösung |
|---|---|---|
| CAPTCHA bei jeder Suche | IP-Adresse markiert oder Rate überschritten | Wechseln Sie die IP und fügen Sie längere Verzögerungen hinzu |
| Leere Ergebnisseite | Stattdessen wurde ein CAPTCHA-Block zurückgegeben | Erkennen Sie CAPTCHA vor dem Parsen |
| „Bitte bestätigen Sie, dass Sie ein Mensch sind“ | Bot-Erkennung ausgelöst | Verwenden Sie einen Wohn-Proxy + realistische UA |
| Für Gehaltsdaten ist eine Anmeldung erforderlich | Plattform-Gating-Inhalte | Implementieren Sie eine authentifizierte Sitzung |
| Andere Ergebnisse als der Browser | Location/cookie Unterschiede | Passen Sie Accept-Language und Geo-Proxy an |
FAQ
Wie viele Stellenangebote kann ich pro Tag durchsuchen?
Mit rotierenden Privat-Proxys und angemessenen Verzögerungen sind 500–2000 Seiten pro Domain erreichbar, ohne auf dauerhafte CAPTCHAs zu stoßen.
Blockieren Jobbörsen das Scraping?
In den meisten Jobbörsen gibt es Bedingungen, die einen automatisierten Zugriff verhindern, die Durchsetzung ist jedoch unterschiedlich. CAPTCHAs sind ihre primäre Verteidigung, die von CaptchaAI übernommen wird.
Welcher Proxy-Typ eignet sich am besten für Jobbörsen?
Rotierende Wohnraum-Proxys bieten das beste Gleichgewicht zwischen Kosten und Erfolgsquote. Rechenzentrums-IPs werden häufig von LinkedIn und Glassdoor blockiert.
Verwandte Leitfäden
- Rotierende Residential-Proxys
- Rotierende Residential-Proxys für höhere Lösungsraten
- Sticky vs. rotierende Sitzungen
Erfassen Sie Arbeitsmarktdaten in großem Maßstab –Holen Sie sich Ihren CaptchaAI-Schlüsselzur automatisierten CAPTCHA-Lösung.