Conectores de fontes¶
Objetivo¶
Este documento organiza quais fontes o SotuHire pode integrar e como cada uma deve ser tratada.
A regra principal é:
Cada fonte deve virar um conector isolado que retorna o mesmo schema de vaga.
Isso evita espalhar lógica de scraping pela aplicação inteira.
Interface conceitual¶
class JobSourceConnector:
name: str
def search(self, query: JobSearchQuery) -> list[RawJob]:
...
def normalize(self, raw_job: RawJob) -> NormalizedJob:
...
Tipos de fonte¶
1. Entrada manual¶
Fonte mais importante no começo.
Entradas:
- descrição colada;
- post colado;
- link colado;
- arquivo JSON;
- arquivo CSV.
Vantagem: permite testar o matcher sem depender de scraper.
2. ATS / job boards públicos¶
Fontes possíveis:
- Greenhouse;
- Lever;
- Ashby;
- Gupy;
- InHire;
- Vagas.com;
- Programathor;
- Remotar;
- páginas públicas de empresas;
- páginas de programas de estágio;
- CIEE;
- Companhia de Estágios;
- Cia de Talentos;
- Nube;
- 99jobs;
- Eureca.
Essas fontes devem ser avaliadas caso a caso.
3. Agregadores de vagas¶
Possíveis fontes:
- Indeed Brasil;
- InfoJobs;
- Catho;
- Trabalha Brasil;
- BNE;
- sites regionais;
- newsletters públicas.
Exigem cuidado porque podem ter termos próprios, bloqueios e estruturas variáveis.
4. Posts e conteúdo informal¶
Entradas:
- texto colado pelo usuário;
- post público salvo manualmente;
- newsletter;
- comunidade;
- thread pública;
- página de recrutador.
O Hidden Jobs Radar entra aqui.
Política por fonte¶
Cada fonte deve ter um arquivo de configuração:
source: "example"
enabled: true
type: "public_page"
requires_login: false
allowed_collection: true
rate_limit_seconds: 3
max_pages_per_run: 20
robots_txt_required: true
notes: "Only public job pages."
Estados de uma fonte¶
manual_only
planned
experimental
active
paused
blocked
deprecated
Exemplo:
LinkedIn: manual_only
Greenhouse: planned
Lever: planned
Company pages: experimental
Gupy: planned
InfoJobs: planned
Indeed Brasil: planned
CIEE: planned
Companhia de Estágios: experimental
InHire: planned_dynamic
Vagas.com: planned
Catho: planned
Generic public pages: active
LinkedIn¶
LinkedIn deve ser tratado como fonte manual/assistiva no SotuHire.
Permitido no produto:
- usuário colar texto de vaga;
- usuário colar texto de post;
- usuário colar link para registro;
- usuário usar uma extensão local para enviar o texto da página aberta ao SotuHire, se implementado com limites claros.
Não implementar:
- login automático;
- scraping de perfis;
- scraping de feed autenticado em massa;
- envio automático de mensagens;
- candidatura automática;
- bypass de limites.
Greenhouse / Lever / Ashby¶
São boas fontes candidatas para o futuro porque muitas empresas usam páginas públicas de vagas. A implementação deve começar com links de empresas específicas e não com varredura global.
Exemplo de abordagem:
- usuário cadastra uma empresa/fonte;
- sistema coleta vagas daquela página pública;
- normaliza os dados;
- calcula match;
- salva no histórico.
Gupy¶
A Gupy é relevante no Brasil, mas deve ser analisada com cuidado por causa de estrutura, termos e eventuais limitações técnicas. Para MVP, o melhor é aceitar link ou descrição colada. O conector automático pode entrar depois.
Páginas de carreira de empresas¶
Bom ponto inicial para scraping.
Exemplos de campos:
- título;
- departamento;
- localização;
- modalidade;
- descrição;
- requisitos;
- link de aplicação.
Programas de estágio¶
O SotuHire deve ter um modo especial para programas de estágio/trainee, pois são muito relevantes para o público-alvo.
Campos úteis:
- nome do programa;
- empresa;
- prazo de inscrição;
- áreas aceitas;
- requisitos de curso;
- período mínimo;
- localidade;
- modalidade;
- link.
Portais brasileiros específicos¶
A matriz completa está em brazilian-job-portals.md.
Conectores prioritários por valor para o público-alvo:
- Gupy;
- LinkedIn em modo manual/assistivo;
- CIEE;
- Companhia de Estágios;
- InfoJobs;
- Indeed Brasil;
- InHire;
- Vagas.com;
- Catho;
- Cia de Talentos/Nube/99jobs/Eureca para programas de entrada.
Esses conectores não devem compartilhar código improvisado. Cada fonte deve ter parser, normalizador, testes e política própria.
Normalização de senioridade¶
Cada fonte escreve senioridade de um jeito. O conector deve normalizar:
estágio -> internship
intern -> internship
trainee -> trainee
júnior -> junior
jr -> junior
pleno -> mid
sênior -> senior
specialist -> specialist
tech lead -> lead
Normalização de modalidade¶
remoto -> remote
híbrido -> hybrid
presencial -> onsite
home office -> remote
anywhere -> remote
Normalização de localidade¶
Separar:
- cidade;
- estado;
- país;
- remoto nacional;
- remoto global;
- híbrido com cidade;
- presencial.
Erros por fonte¶
Cada conector deve retornar erros controlados, não quebrar o app inteiro.
class SourceError:
source: str
url: str
error_type: str
message: str
recoverable: bool
Testes¶
Cada conector deve ter fixtures:
tests/fixtures/sources/
├── greenhouse_sample.html
├── lever_sample.html
├── company_page_sample.html
└── hidden_post_sample.txt
Testes:
- extrai título;
- extrai empresa;
- extrai local;
- extrai descrição;
- normaliza senioridade;
- não quebra com campo ausente;
- ignora vaga sem título.
Contrato expandido de conectores¶
Conectores devem implementar uma interface comum.
class JobSourceConnector:
source_name: str
access_mode: str
def search(self, query: JobSearchQuery) -> list[JobPosting]:
...
def parse(self, raw: str) -> list[JobPosting]:
...
Conectores planejados¶
ManualConnectorLinkedInManualConnectorGupyConnectorInfoJobsConnectorIndeedConnectorCieeConnectorCompanhiaEstagiosConnectorInHireConnectorRemotarConnectorMeuHomeConnectorGreenhouseConnectorLeverConnectorAshbyConnector
Status possíveis¶
manual_only
planned
experimental
active
paused
blocked
deprecated
Testes obrigatórios¶
- parse com HTML fixture;
- normalização de campos;
- deduplicação;
- erro de rede;
- fonte sem resultado;
- fonte com layout alterado;
- limite de rate.
Complemento: JobSpy como referência experimental¶
O JobSpy pode ser estudado como referência técnica de agregação de vagas, mas qualquer adoção precisa passar por revisão de compliance. O SotuHire não deve se vender como ferramenta de bypass, proxy agressivo ou coleta automatizada contra termos de plataformas.
Status sugerido:
jobspy: experimental_reference
production_use: not_decided
requires_compliance_review: true
Conectores ativos na v0.7.0¶
A implementação inicial usa um registry extensível com:
ManualUrlConnector;GenericPublicPageConnector;RssFeedConnector;CompanyCareerPageConnector;ConfiguredSourceConnector.
Todos recebem ScrapingSource, retornam CollectionResult e dependem de um protocolo pequeno de cliente. Isso permite testes com fixtures sem rede e novas implementações sem acoplar o parser ao transporte HTTP.
Fontes públicas compatíveis podem ser adicionadas em config/sources.toml. O dispatcher escolhe o conector pelo campo type.
Modos de acesso da fonte¶
Além do tipo de conector, cada fonte declara um modo:
PUBLIC_SCRAPING
MANUAL_URL
USER_ASSISTED_CAPTURE
AUTHENTICATED_BROWSER
USER_ASSISTED_CAPTURE não é um crawler HTTP. Ele recebe somente a vaga ou publicação atual que a pessoa usuária decidiu enviar a partir do navegador, mesmo quando essa página está dentro de uma sessão própria autenticada.
AUTHENTICATED_BROWSER usa AuthenticatedBrowserConnector e conecta via CDP a um Chromium
iniciado e autenticado pela pessoa usuária. O conector possui presets para listas de vagas e
publicações do LinkedIn, aceita seletores customizados para outras fontes autorizadas e registra a
referência de autorização em ScrapingSource.authorization_reference.
O transporte real fica em PlaywrightAuthenticatedCrawler, atrás do protocolo
AuthenticatedCrawler. Assim, normalização, deduplicação e erros podem ser testados sem iniciar
um navegador real.