18

我正在尝试从这个 NCBI.gov 页面中抓取 html 。我需要包含#see-all URL 片段,这样我才能保证获得搜索页面,而不是从不正确的基因页面https://www.ncbi.nlm.nih.gov/gene/119016中检索 HTML 。

URL 片段不会传递给服务器,而是由页面客户端的 javascript 用于(在这种情况下)创建完全不同的 HTML,这是您在浏览器中访问页面并“查看page source”,这是我要检索的 HTML。R readLines() 忽略 url 标签后跟 #

我首先尝试使用 phantomJS,但它只是返回了此处描述的错误ReferenceError: Can't find variable: Map,这似乎是由于 phantomJS 不支持 NCBI 正在使用的某些功能,因此消除了这种解决方法。

我使用以下用 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?

4

6 回答 6

12

您可以尝试更改此设置:

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.

乐:

这也可能派上用场:

await page.waitForSelector('h3'); // replace h3 with your selector
于 2017-08-29T14:37:46.053 回答
8

也许尝试等待

await page.waitForNavigation(5);

之后

let html = await page.content();
于 2017-08-26T04:39:46.813 回答
3

我使用以下内容成功获取了页面加载后生成的 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);
}

希望这可以帮助。

于 2018-06-18T14:29:08.100 回答
0

如果你想真正等待一个自定义事件,你可以这样做。

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的示例构建

于 2019-05-16T16:34:19.307 回答
0

确实你需要innerHTML:

fs.writeFileSync( "test.html", await (await page.$("html")).evaluate( (content => content.innerHTML ) ) );
于 2021-09-22T19:50:26.987 回答
0

在我的情况下,等待网络空闲是不够的,所以我使用了 dom 加载事件:

await page.goto(url, {waitUntil: 'domcontentloaded', timeout: 60000} );
const data = await page.content();
于 2020-11-24T19:53:51.503 回答