googlejobs: traverse <template> content to find apply URLs

Apply links (Indeed, Glassdoor, Monster, etc.) are pre-rendered inside
a <template> tag within each card's share_el. <template> content is
inert in the rendered DOM — a regular querySelectorAll from outside
returns nothing, which is why the previous fix produced empty URLs.

Iterate share_el's <template> elements and search their .content for
links matching utm_campaign=google_jobs_apply. Verified on the live
Google Jobs page that each card's template contains the correct
external apply URL.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
main
I Luk Kim 3 months ago
parent fa748bebf9
commit 37e5b59126

@ -23,22 +23,21 @@ _EXTRACT_JS = """() => {
if (docMatch) htidocid = decodeURIComponent(docMatch[1]); if (docMatch) htidocid = decodeURIComponent(docMatch[1]);
} }
// Use the first external apply URL (Indeed, Glassdoor, Monster, etc.) // Apply URLs (Indeed, Glassdoor, Monster, etc.) live INSIDE a <template>
// pre-loaded inside the card's share_el. These are direct links to the // tag within share_el. <template> content is inert in the rendered DOM
// source posting and work regardless of session/location, unlike // querySelectorAll('a[...]') from outside doesn't see them. We must
// Google Jobs htidocid deep-links which require the job to be in the // traverse template.content explicitly. These are stable direct links
// current search context. // to the source posting that work regardless of session/location.
let jobUrl = ''; let jobUrl = '';
if (shareEl) { if (shareEl) {
const links = Array.from(shareEl.querySelectorAll('a[href^="https://"]')); const templates = shareEl.querySelectorAll('template');
const apply = links.find(a => { for (const t of templates) {
const href = a.getAttribute('href') || ''; const link = t.content.querySelector('a[href*="utm_campaign=google_jobs_apply"]');
return !href.includes('://www.google.com') if (link) {
&& !href.includes('://google.com') jobUrl = link.getAttribute('href');
&& !href.includes('gstatic.com') break;
&& !href.includes('accounts.google.com'); }
}); }
if (apply) jobUrl = apply.getAttribute('href');
} }
const dateSpan = card.querySelector('span[aria-label^="Posted"]'); const dateSpan = card.querySelector('span[aria-label^="Posted"]');

Loading…
Cancel
Save