From 509c06e00bb3448f65e24c2961b0c1058bef3dd6 Mon Sep 17 00:00:00 2001 From: Oscar Date: Tue, 9 Jun 2026 18:10:26 +0300 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(src/hh/scraper.ts):=20=D0=B4?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D1=8F=D0=B5=D1=82=20=D1=84=D1=83?= =?UTF-8?q?=D0=BD=D0=BA=D1=86=D0=B8=D1=8E=20=D0=BF=D1=80=D0=BE=D0=BA=D1=80?= =?UTF-8?q?=D1=83=D1=82=D0=BA=D0=B8=20=D0=B4=D0=BB=D1=8F=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=B3=D1=80=D1=83=D0=B7=D0=BA=D0=B8=20=D0=B2=D1=81=D0=B5=D1=85?= =?UTF-8?q?=20=D0=B2=D0=B0=D0=BA=D0=B0=D0=BD=D1=81=D0=B8=D0=B9=20=D0=BD?= =?UTF-8?q?=D0=B0=20=D1=81=D1=82=D1=80=D0=B0=D0=BD=D0=B8=D1=86=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hh/scraper.ts | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/hh/scraper.ts b/src/hh/scraper.ts index 18923a2..ac9c10a 100644 --- a/src/hh/scraper.ts +++ b/src/hh/scraper.ts @@ -261,11 +261,25 @@ function buildVacancySearchUrl(query: string, searchMode: 'text' | 'resume', res parts.push(`resume=${encodeURIComponent(resumeId)}`) if (area) parts.push(`area=${encodeURIComponent(area)}`) - parts.push('items_on_page=100', `page=${page}`) + parts.push('ored_clusters=true', 'items_on_page=100', `page=${page}`) return `https://hh.ru/search/vacancy?${parts.join('&')}` } +async function scrollToLoadAll(page: Page) { + let previousCount = 0 + for (let i = 0; i < 20; i++) { + await page.evaluate(() => window.scrollBy(0, window.innerHeight * 3)) + await page.waitForTimeout(400) + const count = await page.$$eval('[data-qa="vacancy-serp__vacancy"]', els => els.length) + if (count === previousCount) + break + previousCount = count + } + await page.evaluate(() => window.scrollTo(0, 0)) +} + async function collectPageVacancies(page: Page) { + await scrollToLoadAll(page) return page.$$eval( '[data-qa="vacancy-serp__vacancy"]', (cards) => { @@ -326,7 +340,10 @@ export async function applyToJobs( await page.goto(pageUrl, { waitUntil: 'domcontentloaded' }) await page.waitForSelector('[data-qa="vacancy-serp__vacancy"]', { timeout: 10000 }).catch(() => null) const more = await collectPageVacancies(page) + log.divider('Page Vacancies') + log.info(more) vacancies.push(...more) + await status(`🔎 Страница ${p}`) } } @@ -463,8 +480,8 @@ export async function applyToJobs( const submitBtn = await page.$('[data-qa="vacancy-response-submit-popup"]')// vacancy-response-popup-submit if (submitBtn) { - await submitBtn.click() - await page.waitForTimeout(randomDelay()) + // await submitBtn.click() + // await page.waitForTimeout(randomDelay()) } else { const errMsg = 'Not found submit button' @@ -503,8 +520,8 @@ export async function applyToJobs( const submitBtn = await page.$('[data-qa="vacancy-response-letter-submit"]') ?? await page.$('[data-qa="vacancy-response-submit-popup"]')// vacancy-response-popup-submit // await page.pause() if (submitBtn) { - await submitBtn.click() - await page.waitForTimeout(randomDelay()) + // await submitBtn.click() + // await page.waitForTimeout(randomDelay()) } else { const errMsg = 'Not found submit button'