LoginSignup
danodano
@danodano

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Puppeteerでスクレイピングするときの「Error: failed to find element matching selector」というエラー

Puppeteerでスクレイピングをしたいのですが下記のようなエラーが出ます。

発生している問題・エラー


UnhandledPromiseRejectionWarning: Error: Error: failed to find element matching selector "body > div.ts-h-l-root > div.ts-h-l-body > div.ts-h-company-upperArea > div.ts-h-company-upperArea-companyNameArea.ts-s-cf > div.ts-h-company-upperArea-companyNameArea-dataArea > table > tbody > tr:nth-child(1) > td > div.ts-h-company-dataTable-main"


ソースコード

const puppeteer = require('puppeteer');
const readline = require('readline');



const RIKUNAVI_TARGET_URL = 'https://job.rikunabi.com/2022/';
const RIKUNAVI_COMPANY_NAME_SELECTOR = '#mp_sp_input';
const RIKUNAVI_SEARCH_SELECTOR = '#mp_mv > div > div > div.mp_sp_01 > div > form > div.mp_clearfix.mp_mb13 > a';

function getFilename() {

    const offset = (new Date()).getTimezoneOffset() * 60000;
    const iso = (new Date(Date.now() - offset)).toISOString();
    const m = iso.match(/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})/);
    return `${m[1]}${m[2]}${m[3]}-${m[4]}${m[5]}${m[6]}.png`;
}


(async () => {
    const browser = await puppeteer.launch({ 
        headless: false,
    });
    const page = await browser.newPage(); 
    await page.setViewport({ width: 1440, height: 900 }); 
    await page.setExtraHTTPHeaders({
        'Accept-Language': 'ja'
    });

    await page.goto(RIKUNAVI_TARGET_URL);
    const answer = await prompt('企業名検索');
    await page.type(RIKUNAVI_COMPANY_NAME_SELECTOR, answer); 
    await Promise.all([ 
        page.waitForNavigation({ waitUntil: 'networkidle0' }),
        page.click(RIKUNAVI_SEARCH_SELECTOR),
    ]);
    let RIKUNAVI_COMPANY_LINK = '//*[@id="cassette-r742110032"]/div[1]/div/a';
    await page.waitForXPath(RIKUNAVI_COMPANY_LINK);
    let elementHandleList = await page.$x(RIKUNAVI_COMPANY_LINK);
    await elementHandleList[0].click();


    const COMPANY_NAME = await page.$eval('body > div.ts-h-l-root > div.ts-h-l-body > div.ts-h-company-upperArea > div.ts-h-company-upperArea-companyNameArea.ts-s-cf > div.ts-h-company-upperArea-companyNameArea-dataArea > table > tbody > tr:nth-child(1) > td > div.ts-h-company-dataTable-main', e => e.innerText);
    console.log(COMPANY_NAME);
await browser.close();
})();

const prompt = async (msg) => {
    console.log(msg);
    const answer = await question('> ');
    return answer.trim();
  };

  const question = (question) => {
    const readlineInterface = readline.createInterface({
      input: process.stdin,
      output: process.stdout
    });
    return new Promise((resolve) => {
      readlineInterface.question(question, (answer) => {
        resolve(answer);
        readlineInterface.close();
      });
    });
  };

スクレイピングしたいサイト

URLは
https://job.rikunabi.com/2022/company/r742110032/
です。

0

1Answer

詳細のページは新しいタブで開かれているのでそのタブに対してスクレイピングを行う必要があるのではないでしょうか。

0

Comments

  1. @danodano

    Questioner
    回答ありがとうございます。
    教えていただいたページを参考にしてみたのですが、同じエラーが発生してしまいました。
    他に考えられる要因はありますか?
  2. スクレイピングするページが誤っている、スクレイピングの処理が誤っているの2つが考えられそうですね。
    直接詳細のページを開いてスクレイピングしたらどうなりますか?
  3. @danodano

    Questioner
    直接開いた場合はスクレイピングできます。
    また、このサイトでは何故かセレクタを用いたクリックの処理ができず、XPathを用いればクリックの処理ができるので、教えていただいた方法ではできませんでした。
  4. 新しいタブに対してスクレイピングができないのか、できているけど件のエラーが出ているのかで大きく違うのですがどちらでしょうか?
  5. @danodano

    Questioner
    おそらく新しいタブに対してスクレイピングができていません。
  6. 先のリンクを参考にするなら次のようなコードで新しいタブを取得できそうですがいかがでしょうか。

    ```javascript
    const [newPage] = await Promise.all([
    browser.waitForTarget(t => t.opener() === page.target()).then(t => t.page()),
    elementHandleList[0].click(),
    ]);
    ```

    `newPage.url()` や `newPage.content()` の値を確認してみてください。
  7. @danodano

    Questioner
    教えていただいたコードで試したところ`newPage.url()`で遷移後のページのURLを取得できたのですが、セレクタやXpathでのスクレイピングはできませんでした。
  8. `newPage.content()` を見てもらうとわかるのですが遷移直後は対象の要素が存在していないようなので読み込まれるのを待つ必要がありそうですね。
  9. @danodano

    Questioner
    できました!
    'newPage.waitForSelector'で遷移を待ち、スクレイピングのコードを'newPage.$eval'にするとスクレイピングすることができました。
    教えていただきありがとうございました!
  10. 良かったですね。

Your answer might help someone💌