单击带有操纵符的元素列表

时间:2020-10-19 16:29:22

标签: javascript node.js asynchronous puppeteer

我想使用puppeteer从ZipRecruiter抓取工作数据,用于我的个人项目。我当前的方法是使用puppeteer转到ziprecruiter URL(例如https://www.ziprecruiter.com/candidate/search?search=React&location=San+Francisco)并获取所有可单击的作业名称。由于这些项目实际上不是<a>标记,因此我不能简单地获取它们的href属性并使用puppeteer转到该页面,然后将页面的HTML传递给cheerio来擦除我需要的数据。

相反,我试图将所有职位(类为('.just_job_title'))保存在变量中,然后使用puppeteer单击每个职位,打开新页面,如果该页面属于ZipRecruiter ,抓取我需要的信息。然后使用page.goBack()返回到原始URL。但是,我当前的方法引起了错误:UnhandledPromiseRejectionWarning: Error: Protocol error (Runtime.callFunctionOn): Target closed.,而且我不确定如何实现上面概述的理想方案。

这是我的代码:

export async function getJobsZipRecruiter(params) {
const ZIPRECRUITER_URL = `https://www.ziprecruiter.com/candidate/search?search=React&location=San+Francisco`;

try {
  console.log('Trying to scrape *************');
  const browser = await puppeteer.launch({ headless: false });
  const page = await browser.newPage();
  await page.goto(ZIPRECRUITER_URL);
  await page.waitForSelector('#createAlertPop');

 
  const jobs = await page.$$('.just_job_title');

  jobs.forEach(async (job) => {
      await page.waitForSelector('.just_job_title');
      await job.click();
      console.log('Yes it worked');
      // Get the data you want here and push it into the data array
      await page.goBack();
    });

  console.log(jobs)


  await browser.close();
  return zipRecruiterJobs;
} catch (err) {
  console.log(err);
}


}

1 个答案:

答案 0 :(得分:1)

  1. .forEach()不太适合异步任务:它会立即启动所有callbac,因此,在您的情况下,所有功能都是混合在一起的,只能处理一页混乱的标题。通常for..of循环会更好。

  2. '.just_job_title'元素是链接的子元素,因此您可以收集所有href并逐一处理它们。

尝试这样的事情:

const puppeteer = require('puppeteer');

async function getJobsZipRecruiter(params) {
  const ZIPRECRUITER_URL = `https://www.ziprecruiter.com/candidate/search?search=React&location=San+Francisco`;

  try {
    console.log('Trying to scrape *************');
    const browser = await puppeteer.launch({ headless: false });
    const [page] = await browser.pages();
    await page.goto(ZIPRECRUITER_URL);
    await page.waitForSelector('#createAlertPop');

    const urls = await page.evaluate(() => Array.from(
      document.querySelectorAll('a[href][data-tracking="job_title"].job_link.t_job_link'),
      link => link.href,
    ));

    console.log(urls);
    const zipRecruiterJobs = [];

    for (const url of urls) {
      await page.goto(url);
      if (!page.url().startsWith('https://www.ziprecruiter.com/')) continue;
      await page.waitForSelector('h1.job_title');
      // Get the data you want here and push it into the data array
      zipRecruiterJobs.push(
        await page.evaluate(() => document.querySelector('h1.job_title').innerText)
      );
    }

    await browser.close();
    console.log(zipRecruiterJobs);
    return zipRecruiterJobs;
  } catch (err) {
    console.log(err);
  }
}

getJobsZipRecruiter();