feat: add Google Jobs extractor and fix scraper reliability gaps
CI / skip-ci-check (pull_request) Successful in 8s
CI / docker-ci (pull_request) Successful in 10s
CI / secret-scan (pull_request) Successful in 7s

Ship a Camoufox-backed Google Jobs source, restore Glassdoor results discarded by a python-jobspy GraphQL quirk, and fix Himalayas/Gradcracker zero-job failures. Also harden prior-skip dismiss matching and multi-profile basic-auth switching for CA/US runs.
This commit is contained in:
2026-07-09 15:11:53 -04:00
parent 84e6835b11
commit 40c7cdece3
47 changed files with 1989 additions and 87 deletions
+26 -5
View File
@@ -116,11 +116,32 @@ router.addHandler(
const title = (await titleLocator.textContent())?.trim() ?? null;
const jobUrl = toAbsolute(await titleLocator.getAttribute("href"));
const employerImg = article.locator("figure img");
const employer = (await employerImg.getAttribute("alt"))?.trim() ?? null;
const employerAnchor = article.locator("figure a");
const employerUrl = toAbsolute(await employerAnchor.getAttribute("href"));
// Employer logo/link are optional — some cards omit <figure img>, and a
// hard getAttribute timeout used to fail the whole region page (0 jobs)
// even after we had already counted cards.
let employer: string | null = null;
let employerUrl: string | null = null;
try {
const employerImg = article.locator("figure img").first();
if ((await employerImg.count()) > 0) {
employer =
(
await employerImg.getAttribute("alt", { timeout: 2000 })
)?.trim() ?? null;
}
} catch {
// optional
}
try {
const employerAnchor = article.locator("figure a").first();
if ((await employerAnchor.count()) > 0) {
employerUrl = toAbsolute(
await employerAnchor.getAttribute("href", { timeout: 2000 }),
);
}
} catch {
// optional
}
let disciplines: string | null = null;
try {