web-dev-qa-db-ja.com

Puppeteerを使用してJavaScriptでレンダリングされたHTMLを取得する

このNCBI.govページ からHTMLを取得しようとしています。 #see-all URLフラグメントを含める必要があります。これにより、誤った遺伝子ページからHTMLを取得する代わりに検索ページを取得できることが保証されます https://www.ncbi.nlm.nih.gov/gene/ 119016

URLフラグメントはサーバーに渡されず、代わりにクライアント側のページのJavaScriptによって使用され(この場合)、まったく異なるHTMLが作成されます。これは、ブラウザーでページに移動して「表示」したときに得られるものです。ページのソース」、つまり取得したいHTMLです。 R readLines()は、#が後に続くURLタグを無視します

私は最初にphantomJSを使用しようとしましたが、ここで説明されているエラー ReferenceError:Ca n't find variable:Map を返しましたが、NCBIが使用していた一部の機能をphantomJSがサポートしていないため、これを排除していますソリューションにルーティングします。

Node.jsで評価される次のJavascriptを使用して、Puppeteerでより多くの成功を収めました。

const puppeteer = require('puppeteer');
(async() => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto(
    'https://www.ncbi.nlm.nih.gov/gene/?term=AGAP8#see-all');
  var HTML = await page.content()
  const fs = require('fs');
  var ws = fs.createWriteStream(
    'TempInterfaceWithChrome.js'
  );
  ws.write(HTML);
  ws.end();
  var ws2 = fs.createWriteStream(
    'finishedFlag'
  );
  ws2.end();
  browser.close();
})();

ただし、これにより、事前にレンダリングされたhtmlと思われるものが返されました。ブラウザで取得した最終的なHTMLを(プログラムで)取得するにはどうすればよいですか?

10
Sir_Zorg

これを変更してみてください:

_await page.goto(
  'https://www.ncbi.nlm.nih.gov/gene/?term=AGAP8#see-all');
_

これに:

_  await page.goto(
    'https://www.ncbi.nlm.nih.gov/gene/?term=AGAP8#see-all', {waitUntil: 'networkidle'});
_

または、ページ読み込み時にカスタムイベントをリッスンする関数listenFor()を作成できます。

_function listenFor(type) {
  return page.evaluateOnNewDocument(type => {
    document.addEventListener(type, e => {
      window.onCustomEvent({type, detail: e.detail});
    });
  }, type);
}`

await listenFor('custom-event-ready'); // Listen for "custom-event-ready" custom event on page load.
_

LE:

これも役に立つかもしれません:

_await page.waitForSelector('h3'); // replace h3 with your selector
_
8

たぶん待ってみよう

await page.waitForNavigation(5);

以降

let html = await page.content();
4

以下を使用して、ページが読み込まれた後に生成されたhtmlコンテンツを取得することに成功しました。

const browser = await puppeteer.launch();
try {
  const page = await browser.newPage();
  await page.goto(url);
  await page.waitFor(2000);
  let html_content = await page.evaluate(el => el.innerHTML, await page.$('.element-class-name'));
  console.log(html_content);
} catch (err) {
  console.log(err);
}

お役に立てれば。

2
Darren Hall

カスタムイベントを実際に待機する場合は、この方法で行うことができます。

const page = await browser.newPage();

/**
  * Attach an event listener to page to capture a custom event on page load/navigation.
  * @param {string} type Event name.
  * @return {!Promise}
  */
function addListener(type) {
  return page.evaluateOnNewDocument(type => {
    // here we are in the browser context
    document.addEventListener(type, e => {
      window.onCustomEvent({ type, detail: e.detail });
    });
  }, type);
}

const evt = await new Promise(async resolve => {
  // Define a window.onCustomEvent function on the page.
  await page.exposeFunction('onCustomEvent', e => {
    // here we are in the node context
    resolve(e); // resolve the outer Promise here so we can await it outside
  });

  await addListener('app-ready'); // setup listener for "app-ready" custom event on page load
  await page.goto('http://example.com');  // N.B! Do not use { waitUntil: 'networkidle0' } as that may cause a race condition
});

console.log(`${evt.type} fired`, evt.detail || '');

https://github.com/GoogleChrome/puppeteer/blob/master/examples/custom-event.js の例に基づいて構築

0
mflodin