El scraping de job boards es uno de los escenarios más demandados para la recopilación de datos en análisis de recursos humanos, monitoreo del mercado laboral y automatización del reclutamiento. Pero los sitios de ofertas de trabajo se protegen activamente contra la recopilación automática de datos: bloquean IP después de 50-100 solicitudes, muestran CAPTCHA y bloquean cuentas sospechosas. En este artículo, analizaremos cómo configurar correctamente un proxy para un scraping estable de hh.ru, Superjob, LinkedIn y otras plataformas sin bloqueos.
Por qué los job boards bloquean el scraping y cómo funciona la protección
Los sitios de ofertas de trabajo pierden dinero por el scraping: los datos se venden a competidores, se crean agregadores sin licencia y los empleadores evitan las publicaciones pagadas. Por lo tanto, todas las grandes plataformas han implementado una protección de múltiples niveles contra la recopilación automática de datos.
Métodos principales de protección de job boards:
- Limitación de tasa por IP — hh.ru bloquea IP después de 80-120 solicitudes por hora, Superjob — después de 50-70 solicitudes. El bloqueo puede durar de 1 hora a un día.
- Fingerprinting del navegador — los sitios analizan el User-Agent, los encabezados HTTP, la resolución de pantalla, las fuentes instaladas. Si los datos no corresponden a un navegador real, la solicitud se bloquea.
- Verificaciones de JavaScript — muchos sitios utilizan Cloudflare o sus propios scripts para verificar que la solicitud proviene de un navegador real y no de un bot.
- Trampas de Honeypot — enlaces y campos ocultos que solo ve el parser. Si el bot accede a ellos, la IP se agrega a la lista negra.
- CAPTCHA ante actividad sospechosa — aparece después de una serie de solicitudes rápidas o al utilizar IP de centros de datos.
Sin proxies, podrá scrapear un máximo de 100-200 ofertas de trabajo, después de lo cual su IP será bloqueada. Para la recopilación masiva de datos (miles de ofertas diarias), los proxies se convierten en una herramienta indispensable.
Importante: El scraping debe cumplir con los términos de uso del sitio. Muchos job boards ofrecen API oficiales para el acceso legal a los datos. Por ejemplo, hh.ru tiene una API gratuita con un límite de solicitudes que es adecuada para la mayoría de las tareas.
Qué tipo de proxy elegir para el scraping de ofertas de trabajo
La elección del tipo de proxy depende de la escala del scraping, el presupuesto y los requisitos de velocidad. Analicemos tres opciones principales con escenarios de uso específicos.
| Tipo de proxy | Velocidad | Riesgo de bloqueo | Cuándo usar |
|---|---|---|---|
| Proxies de centros de datos | Alta (50-200 ms) | Alto | Pruebas del scraper, recopilación de datos públicos sin autorización |
| Proxies residenciales | Media (200-800 ms) | Bajo | Scraping masivo de hh.ru, Superjob con rotación de IP |
| Proxies móviles | Media (300-1000 ms) | Muy bajo | Scraping con autorización, eludir la protección estricta de LinkedIn |
Proxies de centros de datos para scraping
Esta es la opción más rápida y económica, pero con limitaciones. Las IP de centros de datos son fácilmente reconocibles por los sitios, por lo que son adecuadas solo para tareas simples: scraping de listas de ofertas sin autorización, recopilación de datos públicos, pruebas del scraper antes de lanzarlo en proxies residenciales.
Cuándo funcionan los proxies de centros de datos:
- Scraping de pequeñas cantidades de datos (hasta 500 ofertas al día)
- Recopilación de datos de sitios sin protección estricta (pequeños job boards regionales)
- Uso de API oficiales con rotación de IP para eludir límites de tasa
- Scraping de feeds RSS y archivos XML de ofertas
Para hh.ru y Superjob, los proxies de centros de datos funcionarán de manera inestable: obtendrá CAPTCHA después de 20-30 solicitudes, y muchas IP ya están en las listas negras de estos sitios.
Proxies residenciales: la mejor opción para job boards
Los proxies residenciales utilizan direcciones IP de usuarios domésticos reales, por lo que los sitios los perciben como visitantes normales. Este es el equilibrio óptimo entre precio y calidad para el scraping de ofertas.
Ventajas para el scraping de job boards:
- Bajo riesgo de bloqueo — hh.ru y Superjob no pueden distinguir una IP residencial de un usuario real
- Gran pool de direcciones IP — se puede configurar la rotación en cada solicitud o cada 5-10 minutos
- Vinculación geográfica — se pueden scrapear ofertas de una ciudad específica utilizando IP de esa región
- Estabilidad — una IP residencial puede manejar de 200 a 500 solicitudes sin bloqueo
Para el scraping masivo (más de 1000 ofertas al día), los proxies residenciales con rotación de IP son la solución estándar. Configura el cambio de IP cada 5-10 minutos, agrega retrasos aleatorios entre solicitudes (3-7 segundos) y obtén una recopilación de datos estable sin bloqueos.
Proxies móviles para LinkedIn y scraping con autorización
Los proxies móviles utilizan IP de operadores móviles. Su principal ventaja es que una IP es utilizada por cientos de usuarios reales al mismo tiempo, por lo que los sitios no pueden bloquear esa dirección sin arriesgarse a bloquear a miles de visitantes normales.
Cuándo se necesitan proxies móviles:
- Scraping de LinkedIn — esta plataforma tiene la protección más estricta contra bots y bloquea agresivamente las IP de centros de datos e incluso las residenciales
- Trabajo con autorización — si necesita scrapear ofertas cerradas o datos de perfiles, las IP móviles reducen el riesgo de bloqueo de la cuenta
- Scraping de job boards extranjeras — Indeed, Glassdoor, Monster utilizan sistemas de protección avanzados donde las IP móviles funcionan de manera más confiable
- Eludir bloqueos estrictos — si sus proxies residenciales comienzan a recibir CAPTCHA, cambiar a móviles resolverá el problema
La desventaja de los proxies móviles es el alto costo y menor velocidad. Pero para tareas críticas, donde el bloqueo es inaceptable, esta es la mejor opción.
Características del scraping de hh.ru: protección y métodos de elusión
hh.ru es el mayor sitio de ofertas de trabajo en Rusia con la protección más avanzada contra el scraping entre los job boards nacionales. El sitio utiliza una combinación de limitación de tasa, fingerprinting y análisis de comportamiento para detectar bots.
Cómo funciona la protección de hh.ru
1. Límites por dirección IP: Después de 80-120 solicitudes por hora desde una IP, el sitio comienza a mostrar CAPTCHA o devuelve HTTP 429 (Demasiadas Solicitudes). El bloqueo dura de 1 a 6 horas dependiendo de la agresividad del scraping.
2. Verificación de User-Agent y encabezados: hh.ru analiza los encabezados de las solicitudes HTTP. Si el User-Agent no corresponde a un navegador real o faltan encabezados estándar (Accept-Language, Accept-Encoding), la solicitud se bloquea.
3. Verificaciones de JavaScript: Algunas páginas de hh.ru requieren la ejecución de JavaScript para cargar datos. Un simple scraper HTTP sin navegador headless no podrá obtener el contenido completo.
4. Enlaces de Honeypot: En las páginas hay elementos ocultos que solo ve el parser. Si su script accede a estos enlaces, la IP se agrega a la lista negra durante 24 horas.
Estrategia para eludir la protección de hh.ru con proxies
Para un scraping estable de hh.ru sin bloqueos, utilice la siguiente configuración:
Configuración óptima para el scraping de hh.ru:
- Tipo de proxy: Residenciales con rotación de IP cada 5-10 minutos
- Retraso entre solicitudes: 4-8 segundos (valor aleatorio)
- User-Agent: Rotación de User-Agent reales de navegadores modernos (Chrome, Firefox, Safari de las últimas versiones)
- Encabezados: Conjunto completo de encabezados estándar del navegador (Accept, Accept-Language, Accept-Encoding, Referer)
- Cookies: Almacenamiento y transmisión de cookies entre solicitudes dentro de una misma sesión
- Límite de solicitudes: No más de 60-80 solicitudes por IP, después de lo cual cambiar proxy
Ejemplo de secuencia de acciones segura:
- Conéctese a un proxy residencial con IP de la región deseada (por ejemplo, Moscú)
- Realice la primera solicitud a la página principal de hh.ru, obtenga y guarde las cookies
- Espere 5-7 segundos (simulación de lectura de la página)
- Realice una solicitud a la página de búsqueda de ofertas con los filtros necesarios
- Scrapee la lista de ofertas (generalmente 20-50 por página)
- Para cada oferta, realice una solicitud a la página de detalles con un retraso de 4-6 segundos
- Después de 60-70 solicitudes, cambie el proxy y repita el ciclo
Con esta estrategia, puede scrapear de 1000 a 2000 ofertas al día desde un solo hilo sin un solo bloqueo. Si necesita un mayor volumen, inicie varios hilos paralelos con diferentes proxies.
Consejo: hh.ru proporciona una API gratuita para acceder a ofertas. Para la mayoría de las tareas (análisis del mercado laboral, monitoreo de salarios), la API será una solución más estable que el scraping de HTML. Los proxies se pueden utilizar para la rotación de IP al trabajar con la API, para eludir los límites de tasa.
Scraping de Superjob, LinkedIn y plataformas extranjeras
Superjob: características de la protección
Superjob tiene una protección menos estricta en comparación con hh.ru, pero aún así lucha activamente contra el scraping. Las principales diferencias son:
- Límite de tasa más bajo: El bloqueo ocurre después de 50-70 solicitudes por hora (en comparación con 80-120 en hh.ru)
- Verificación de encabezados menos estricta: Se puede usar un conjunto simplificado de encabezados
- Ausencia de protección de JavaScript: La mayoría de los datos están disponibles a través de una simple solicitud HTTP sin navegador headless
- Bloqueo regional: Algunas ofertas solo están disponibles desde IP de una región específica
Para Superjob, son suficientes proxies residenciales con rotación cada 10-15 minutos y un retraso entre solicitudes de 3-5 segundos. Esto permitirá scrapear de manera estable entre 500 y 1000 ofertas al día.
LinkedIn: la protección más estricta
LinkedIn es una historia aparte. La plataforma utiliza algoritmos avanzados de aprendizaje automático para detectar bots y tiene uno de los sistemas de protección más agresivos entre todas las redes sociales y job boards.
Características de la protección de LinkedIn:
- Autenticación obligatoria: La mayoría de los datos solo están disponibles para usuarios autenticados
- Análisis de comportamiento: LinkedIn analiza los patrones de acción: velocidad de desplazamiento, movimientos del mouse, tiempo en la página
- Bloqueo de cuentas: Ante actividad sospechosa, no solo se bloquea la IP, sino también la cuenta misma
- Restricciones en las vistas de perfiles: Las cuentas gratuitas pueden ver un número limitado de perfiles al mes
- Ejecución obligatoria de JavaScript: Sin un navegador headless, el scraping es imposible
Estrategia de scraping de LinkedIn:
- Utilice proxies móviles — ofrecen el menor riesgo de bloqueo. Una IP móvil se puede usar para 100-200 vistas de perfiles al día.
- El navegador headless es obligatorio — use Puppeteer o Playwright con la configuración de un fingerprint real del navegador (resolución de pantalla, WebGL, Canvas).
- Velocidad de scraping lenta — no más de 20-30 perfiles por hora desde una cuenta. Agregue retrasos de 10-20 segundos entre vistas.
- Simulación de comportamiento real — desplazamiento por la página, clics aleatorios, transiciones entre secciones del perfil.
- Calentamiento de cuentas — las nuevas cuentas de LinkedIn no se pueden usar de inmediato para el scraping. Deben simular actividad de un usuario normal durante 1-2 semanas.
- Rotación de cuentas — use varias cuentas con diferentes proxies para distribuir la carga.
El scraping de LinkedIn es la tarea más compleja entre todos los job boards. Si necesita datos de esta plataforma, considere usar la API oficial de Sales Navigator o servicios de terceros que proporcionen datos legalmente.
Job boards extranjeros: Indeed, Glassdoor, Monster
Las plataformas extranjeras generalmente tienen una protección más estricta que los sitios rusos (excepto hh.ru). Las principales características son:
- Indeed — utiliza Cloudflare con verificaciones de JavaScript. Se necesita un navegador headless y proxies residenciales/móviles del país cuyas ofertas está scrapeando.
- Glassdoor — requiere autenticación para ver la mayoría de los datos. Bloquea activamente las IP de centros de datos. Use proxies residenciales y una velocidad de scraping lenta (retraso de 8-12 segundos).
- Monster — tiene API para socios, pero para el scraping de HTML se necesitan proxies residenciales con vinculación geográfica al país deseado.
Para todas las plataformas extranjeras, la vinculación geográfica de los proxies es críticamente importante. Si está scrapeando ofertas en EE. UU., utilice IP residenciales estadounidenses. Las solicitudes desde IP de otros países pueden generar sospechas y llevar a bloqueos.
Configuración de rotación de IP y retrasos entre solicitudes
La configuración correcta de la rotación de proxies es la clave para un scraping estable sin bloqueos. Analicemos dos estrategias principales: rotación en cada solicitud y rotación por tiempo.
Rotación en cada solicitud (Rotating Proxies)
Con este enfoque, cada solicitud HTTP se realiza desde una nueva dirección IP. Este es el método más seguro, pero tiene limitaciones:
Ventajas:
- No se puede rastrear la actividad de una sola IP
- Se pueden hacer más solicitudes en un período de tiempo
- No es necesario rastrear los límites en cada IP
Desventajas:
- No es posible mantener la sesión (las cookies se pierden al cambiar de IP)
- No es adecuado para scraping con autorización
- Algunos sitios bloquean solicitudes si la IP cambia con demasiada frecuencia
La rotación en cada solicitud es adecuada para el scraping de páginas públicas de hh.ru y Superjob sin autorización. Se configura a través del parámetro del proveedor de proxies (generalmente es un endpoint especial con rotación automática).
Rotación por tiempo (Sticky Sessions)
Con este enfoque, una IP se utiliza durante un período de tiempo determinado (5-30 minutos), después del cual se produce un cambio automático. Esta es la opción óptima para la mayoría de las tareas de scraping de job boards.
Intervalos de rotación recomendados:
| Sitio | Intervalo de rotación | Máx. solicitudes por IP | Retraso entre solicitudes |
|---|---|---|---|
| hh.ru | 5-10 minutos | 60-80 | 4-8 segundos |
| Superjob | 10-15 minutos | 50-70 | 3-5 segundos |
| 30-60 minutos | 20-40 | 10-20 segundos | |
| Indeed | 10-20 minutos | 40-60 | 5-10 segundos |
| Glassdoor | 15-30 minutos | 30-50 | 8-12 segundos |
Configuración de retrasos aleatorios
Un retraso fijo entre solicitudes (por ejemplo, exactamente 5 segundos) parece sospechoso para los sistemas de protección. Un usuario real no puede actuar con tal precisión. Siempre utilice retrasos aleatorios dentro de un rango.
Ejemplos de implementación de retrasos aleatorios:
// Python
import time
import random
# Retraso de 4 a 8 segundos
delay = random.uniform(4, 8)
time.sleep(delay)
# Lógica más compleja: a veces hacemos una pausa larga
if random.random() < 0.1: # 10% de probabilidad
time.sleep(random.uniform(15, 30)) # Simulación de distracción del usuario
else:
time.sleep(random.uniform(4, 8))
// JavaScript / Node.js
const sleep = (min, max) => {
const delay = Math.random() * (max - min) + min;
return new Promise(resolve => setTimeout(resolve, delay * 1000));
};
// Uso
await sleep(4, 8); // Retraso de 4-8 segundos
// Con probabilidad de pausa larga
if (Math.random() < 0.1) {
await sleep(15, 30); // 10% de probabilidad de pausa larga
} else {
await sleep(4, 8);
}
Agregar pausas largas aleatorias (15-30 segundos) con una probabilidad del 5-10% hace que el comportamiento del scraper se asemeje aún más al de un usuario real, que puede distraerse por una llamada telefónica u otra tarea.
Manejo de CAPTCHA y otros bloqueos
Incluso con la configuración correcta de proxies y retrasos, puede encontrarse con CAPTCHA u otros tipos de bloqueos. Analicemos cómo reaccionar correctamente ante estas situaciones.
Tipos de bloqueos en job boards
1. HTTP 429 Too Many Requests — el tipo de bloqueo más común. El sitio informa claramente que ha superado el límite de solicitudes. Normalmente, en el encabezado de respuesta hay un Retry-After, que indica cuántos segundos debe esperar antes de repetir la solicitud.
Cómo manejar: Cambie inmediatamente el proxy y agregue la IP actual a la lista negra durante el tiempo indicado en Retry-After (generalmente de 1 a 6 horas). Si Retry-After no está presente, agregue la IP a la lista negra durante 2 horas.
2. HTTP 403 Forbidden — la IP está bloqueada a nivel de servidor. Este es un bloqueo más serio que puede durar desde varias horas hasta un día.
Cómo manejar: Cambie el proxy y agregue la IP a la lista negra a largo plazo (24 horas). Analice los registros: es posible que esté scrapeando de manera demasiado agresiva o utilizando IP de centros de datos donde se necesitan residenciales.
3. CAPTCHA — el sitio muestra una verificación "no soy un robot". Esto significa que su comportamiento ha parecido sospechoso, pero la IP aún no está completamente bloqueada.
Cómo manejar: Hay tres opciones:
- Cambiar proxy — la forma más sencilla. La IP actual se agrega a la lista negra durante 6-12 horas.
- Resolución automática de CAPTCHA — uso de servicios como 2Captcha, Anti-Captcha, CapSolver. Cuestan entre $1-3 por 1000 resoluciones.
- Resolución manual — si el scraping no es crítico en tiempo, se puede enviar el CAPTCHA para resolución manual a un operador.
4. Desafío de Cloudflare — verificación de JavaScript que requiere la ejecución de código en el navegador. Una biblioteca HTTP normal no pasará esta verificación.
Cómo manejar: Utilizar un navegador headless (Puppeteer, Playwright, Selenium) con la configuración de un fingerprint real. Bibliotecas como puppeteer-extra-plugin-stealth ayudan a eludir la detección del modo headless.
Integración de servicios de resolución de CAPTCHA
Si ha decidido resolver CAPTCHA automáticamente, aquí hay un ejemplo de integración con el popular servicio 2Captcha:
// Python usando la biblioteca 2captcha-python
from twocaptcha import TwoCaptcha
import requests
solver = TwoCaptcha('YOUR_API_KEY')
try:
# Resolución de reCAPTCHA v2
result = solver.recaptcha(
sitekey='6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-',
url='https://hh.ru/search/vacancy',
proxy={
'type': 'HTTPS',
'uri': 'login:password@ip:port'
}
)
# Obtenemos el token de resolución
captcha_token = result['code']
# Enviamos la solicitud con el token
response = requests.post(
'https://hh.ru/search/vacancy',
data={
'g-recaptcha-response': captcha_token,
# otros parámetros del formulario
},
proxies={
'http': 'http://login:password@ip:port',
'https': 'http://login:password@ip:port'
}
)
except Exception as e:
print(f'Error resolviendo CAPTCHA: {e}')
Resolver un CAPTCHA lleva entre 10 y 30 segundos y cuesta alrededor de $0.001-0.003. Para scraping masivo, esto puede ser costoso, por lo que es mejor configurar el scraping de manera que el CAPTCHA aparezca con la menor frecuencia posible.
Sistema de monitoreo y alertas
Para un funcionamiento estable del scraper, es importante configurar el monitoreo de bloqueos y alertas automáticas:
Qué monitorear:
- Porcentaje de solicitudes exitosas — si cae por debajo del 90%, es necesario verificar los proxies y la configuración
- Cantidad de CAPTCHAs por hora — si hay más de 5-10, está scrapeando de manera demasiado agresiva
- Velocidad media de respuesta de los proxies — si ha aumentado drásticamente, es posible que los proxies estén sobrecargados
- Cantidad de errores 429/403 — indicador de la calidad de los proxies y la corrección de la configuración
- Lista de IP bloqueadas — si una misma IP se bloquea constantemente, exclúyala del pool
Configure el envío de notificaciones (Telegram, correo electrónico, Slack) si el porcentaje de solicitudes exitosas cae por debajo del umbral. Esto permitirá reaccionar rápidamente a los problemas y no perder tiempo en el scraping.
Configuración de proxies en herramientas populares de scraping
Analicemos cómo configurar proxies en las herramientas más populares para el scraping de job boards: Python (requests, Scrapy), Node.js (axios, Puppeteer) y soluciones listas.
Python: requests y Scrapy
Python es el lenguaje más popular para el scraping gracias a las bibliotecas requests, BeautifulSoup y Scrapy.
Ejemplo con la biblioteca requests:
import requests
import random
import time
# Lista de proxies (obtenga de su proveedor)
PROXIES = [
'http://user:[email protected]:8080',
'http://user:[email protected]:8080',
'http://user:[email protected]:8080'
]
# Lista de User-Agent para rotación
USER_AGENTS = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36'
]
def parse_vacancy(url):
proxy = random.choice(PROXIES)
user_agent = random.choice(USER_AGENTS)
headers = {
'User-Agent': user_agent,
'Accept': 'text/html,application/xhtml+xml',
'Accept-Language': 'ru-RU,ru;q=0.9,en;q=0.8',
'Accept-Encoding': 'gzip, deflate, br',
'Connection': 'keep-alive'
}
proxies = {
'http': proxy,
'https': proxy
}
try:
response = requests.get(
url,
headers=headers,
proxies=proxies,
timeout=30
)
if response.status_code == 200:
return response.text
elif response.status_code == 429:
print(f'Límite de tasa para {proxy}, cambiando proxy')
# Eliminamos el proxy de la lista temporalmente
return None
else:
print(f'Error {response.status_code}')
return None
except Exception as e:
print(f'Error en la solicitud: {e}')
return None
# Uso
for i in range(100):
html = parse_vacancy('https://hh.ru/vacancy/123456')
if html:
# Procesamiento de datos
pass
# Retraso aleatorio
time.sleep(random.uniform(4, 8))
Ejemplo de configuración de Scrapy:
# settings.py
# Habilitamos el soporte para proxies
DOWNLOADER_MIDDLEWARES = {
'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 110,
'scrapy_rotating_proxies.middlewares.RotatingProxyMiddleware': 610,
'scrapy_rotating_proxies.middlewares.BanDetectionMiddleware': 620,
}
# Lista de proxies
ROTATING_PROXY_LIST = [
'http://user:[email protected]:8080',
'http://user:[email protected]:8080',
'http://user:[email protected]:8080'
]
# Detección automática de bloqueos
ROTATING_PROXY_BAN_POLICY = 'scrapy_rotating_proxies.policy.BanDetectionPolicy'
# Retraso entre solicitudes
DOWNLOAD_DELAY = 5
RANDOMIZE_DOWNLOAD_DELAY = True # Retraso aleatorio ±50%
# Rotación de User-Agent
DOWNLOADER_MIDDLEWARES.update({
'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None,
'scrapy_user_agents.middlewares.RandomUserAgentMiddleware': 400,
})
# Máximo de solicitudes simultáneas
CONCURRENT_REQUESTS = 4
CONCURRENT_REQUESTS_PER_DOMAIN = 1
Node.js: Puppeteer con proxies
Para el scraping de sitios con JavaScript (LinkedIn, Indeed) se necesita un navegador headless. Puppeteer es la solución más popular para Node.js.
const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
// Plugin para eludir la detección del navegador headless
puppeteer.use(StealthPlugin());
async function parseWithProxy() {
const proxy = 'http://user:[email protected]:8080';
const browser = await puppeteer.launch({
headless: true,
args: [
`--proxy-server=${proxy}`,
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
'--disable-blink-features=AutomationControlled'
]
});
const page = await browser.newPage();
// Establecemos un User-Agent real
await page.setUserAgent(
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
);
// Establecemos el resto de la lógica aquí...