Un hilo de r/hiringcafe compartió el patrón del Agente de búsqueda de empleo con IA: extraiga páginas de carreras de empleadores reales, resuma con IA cada función y muestre el salario por adelantado. Este es un agregador estilo HiringCafe con Scavio + LLM.
Requisitos previos
- Clave API de Scavio
- Una clave API de LLM
- Una lista de empleadores objetivo (o una forma de descubrirlos)
Guia paso a paso
Paso 1: Descubra las URL de páginas profesionales mediante una búsqueda tonta
sitio:company.com carreras + trabajos.lever.co + patrones boards.greenhouse.io.
import requests, os
H = {'x-api-key': os.environ['SCAVIO_API_KEY']}
DORKS = [
'site:{domain}/careers',
'site:{domain}/jobs',
'site:jobs.lever.co/{domain}',
'site:boards.greenhouse.io/{domain}',
]
def find_career_urls(domain):
out = []
for d in DORKS:
q = d.format(domain=domain.replace('.com',''))
r = requests.post('https://api.scavio.dev/api/v1/search', headers=H, json={'query': q}).json()
out.extend(o['link'] for o in r.get('organic_results', [])[:5])
return list(set(out))Paso 2: Extraer páginas de listado como rebajas
Scavio /extract convierte la página de carreras en una rebaja limpia.
def extract(url):
return requests.post('https://api.scavio.dev/api/v1/extract',
headers=H, json={'url': url, 'format': 'markdown'}).json().get('markdown', '')Paso 3: Analizar roles con un LLM
Extracción estructurada: título, ubicación, salario si se muestra, resumen.
PROMPT = '''Extract job postings from this careers page. For each, return JSON with:
- title, team, location, remote (bool), salary_min, salary_max (null if not shown), apply_url, summary (2 sentences).
Return a JSON list.
Page:
{md}'''
result = llm.complete(PROMPT.format(md=markdown))Paso 4: Deduplicar por (empleador, cargo, ubicación)
Mismo rol en múltiples agregadores = un registro.
def dedupe(roles):
seen = set(); out = []
for r in roles:
key = (r['employer'], r['title'], r['location'])
if key not in seen:
seen.add(key); out.append(r)
return outPaso 5: Clasificación por salario + actualidad + puntuación del partido
Los filtros de entrada del usuario impulsan la superficie.
def rank(roles, user_skills):
for r in roles:
match = sum(1 for s in user_skills if s.lower() in (r['summary'] + r['title']).lower())
r['score'] = (r.get('salary_max') or 0) * 0.3 + match * 100
return sorted(roles, key=lambda x: -x['score'])Ejemplo en Python
# Per-employer cost: ~3 dorked searches + 1 extract + 1 LLM call = ~$0.02-0.05Ejemplo en JavaScript
// Same flow in TS.Salida esperada
JSON list of jobs with title, salary, summary, apply_url. Dedupes across aggregators. Ranks by user skills + salary. The hard part remains the relevance ranking; the data layer is the easy part.