Các trang tuyển dụng như Indeed, LinkedIn và Glassdoor triển khai CAPTCHA khi chúng phát hiện các mẫu truy cập tự động. Các nền tảng tuyển dụng, nhà nghiên cứu thị trường và công cụ phân tích nhân sự cần giải pháp CAPTCHA đáng tin cậy để thu thập dữ liệu danh sách việc làm trên quy mô lớn.
CAPTCHA trên các bảng việc làm chính
| Nền tảng | Loại CAPTCHA | Trình kích hoạt | Dữ liệu có sẵn |
|---|---|---|---|
| Quả thực | reCAPTCHA v2 | Khối lượng yêu cầu cao | Danh sách việc làm, mức lương |
| Cloudflare Challenge | Phát hiện bot | Việc làm, dữ liệu công ty | |
| cửa kính | reCAPTCHA v2 | Phát hiện cạo | Đánh giá, lương, việc làm |
| ZipNhà tuyển dụng | Cloudflare Turnstile | Truy cập tự động | Danh sách việc làm |
| Quái vật | reCAPTCHA v2 | Trang tìm kiếm | Danh sách việc làm |
| Tuyển dụng | reCAPTCHA v3 | Đăng nhập, tìm kiếm | Danh sách việc làm, tìm kiếm sơ yếu lý lịch |
Trình quét bảng công việc có xử lý CAPTCHA
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)}")
Thu thập dữ liệu tiền lương
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",
)
Mẹo cấu hình lén lút cho bảng công việc
| Kỹ thuật | Tại sao nó giúp ích |
|---|---|
| đa dạng nguồn yêu cầu luân phiên | Phân phối yêu cầu trên các IP thực |
| Độ trễ 3-5 giây giữa các trang | Bắt chước tốc độ duyệt web của con người |
| Tác nhân người dùng nhất quán mỗi phiên | Tránh dấu vân tay không khớp |
| Chấp nhận cookie | Bảng công việc theo dõi các phiên thông qua cookie |
| Thứ tự tìm kiếm ngẫu nhiên | Tránh các mẫu trang tuần tự |
| Giới hạn ở 200 trang/day cho mỗi tên miền | Ở dưới ngưỡng phát hiện |
Khắc phục sự cố
| Vấn đề | Nguyên nhân | Cách xử lý |
|---|---|---|
| CAPTCHA trên mọi tìm kiếm | IP bị gắn cờ hoặc vượt quá tốc độ | Chuyển đổi IP, thêm độ trễ dài hơn |
| Trang kết quả trống | Thay vào đó, khối CAPTCHA được trả về | Phát hiện CAPTCHA trước khi phân tích cú pháp |
| "Xin hãy xác minh bạn là con người" | Đã kích hoạt tính năng phát hiện bot | Sử dụng đa dạng nguồn yêu cầu + UA thực tế |
| Yêu cầu đăng nhập cho dữ liệu tiền lương | Nội dung kiểm soát nền tảng | Triển khai phiên xác thực |
| Kết quả khác với trình duyệt | Vị trí/cookie sự khác biệt | Phù hợp với ngôn ngữ chấp nhận và proxy địa lý |
Câu hỏi thường gặp
Tôi có thể thu thập bao nhiêu danh sách việc làm mỗi ngày?
Với các proxy dân dụng luân phiên và độ trễ thích hợp, có thể đạt được 500-2000 trang cho mỗi tên miền mà không cần phải gặp CAPTCHA liên tục.
Bảng công việc có chặn việc cạo không?
Hầu hết các bảng việc làm đều có các điều khoản không khuyến khích truy cập tự động nhưng có cách thực thi khác nhau. CAPTCHA là biện pháp bảo vệ chính của chúng, được CaptchaAI xử lý.
Loại proxy nào hoạt động tốt nhất cho bảng công việc?
Các ủy quyền dân cư luân phiên là sự cân bằng tốt nhất giữa chi phí và tỷ lệ thành công. IP của trung tâm dữ liệu thường xuyên bị LinkedIn và Glassdoor chặn.
Hướng dẫn liên quan
- Ủy quyền dân cư luân phiên
- Chất lượng proxy ảnh hưởng đến tỷ lệ giải quyết
- Phiên cố định và phiên luân phiên
Thu thập dữ liệu thị trường việc làm trên quy mô lớn —lấy khóa CaptchaAI của bạnđể giải CAPTCHA tự động.