使用Puppeteer进行数据抓取——Page对象

Posted TianFang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Puppeteer进行数据抓取——Page对象相关的知识,希望对你有一定的参考价值。

page对象是puppeteer最常用的对象,它可以认为是chrome的一个tab页,主要的页面操作都是通过它进行的。Google的官方文档详细介绍了page对象的使用,这里我只是简单的小结一下。

客户端模拟

页面模拟设置相关函数有如下几个,

  1. page.setViewport: 设置视图大小
  2. page.setUserAget: 设置UserAgent
  3. page.SetCookie: 设置Cookie

另外,也可以使用emulate函数提供快捷设置,puppeteer/DeviceDescriptors还提供了常用设备的预设

const?puppeteer?=?require(‘puppeteer‘);
const?devices?=?require(‘puppeteer/DeviceDescriptors‘);|
const?iPhone?=?devices[iPhone?6];

puppeteer.launch().then(async?browser?=>?{
????const?page?=?await?browser.newPage();
????await?page.emulate(iPhone);
????await?page.goto(‘https://www.google.com‘);
????//?other?actions...
????await?browser.close();
});
除此之外
,还可以使用page.setExtraHTTPHeaders设置其它HttpHeader

?

页面跳转

页面跳转相关函数有如下几个,

  1. page.goto(url, options)
  2. page.goBack(options)
  3. page.goForward(options)
  4. page.reload(options)

其中比较常用的是page.goto,相当于在浏览器中输入了地址,然后回车。此外,也可以同通过执行js跳转和模拟点击link跳转。

?

选择

常用的元素函数选择有:

  1. page.$(selector)
  2. page.$$(selector)

它们的功能类似于document.querySelector和document.querySelectorAll。

它们返回的对象是<Promise<?ElementHandle>>,可以用它判断某元素是否存在,也可以对ElementHandle执行相应操作,具体在后面的ElementHandle中介绍。

另外,还有一个使用xpath的select版本。

  1. page.$x(expression)

虽然这个用的相对少点,但也还是非常有用的。

?

模拟输入

page本身提供原始的mouse和keyboard的模拟输入类。

  1. page.mouse
  2. page.keyboard

但同时也提供更方便快捷的模拟输入函数

  1. page.click(selector[, options])????????在被选择元素上模拟点击
  2. page.type(selector, text[, options])????在被选择的输入框中输入
  3. page.hover(selector)????????????????模拟鼠标移动到被选择元素上
  4. page.select(selector, ...values)????????在被选择元素上模拟选择select选项
  5. page.tap(selector)????????????????????在被选择元素上模拟触摸

?

等待

当我们使用page.goto等跳转函数主动跳转页面时,本身该函数就是可以异步等待的,可以直接使用await等待跳转完成。

除此之外,系统也提供了如下等待函数

  • page.waitForNavigation(options)
  • page.waitFor(selectorOrFunctionOrTimeout[, options[, ...args]])
  • page.waitForSelector(selector[, options])
  • page.waitForXPath(xpath[, options])
  • page.waitForFunction(pageFunction[, options[, ...args]])

其中最常用的是page.waitForNavigation,常用于等待跳转结束,例如点击搜索按钮后,等待跳转至搜索结果页面。

const?navigationPromise?=?page.waitForNavigation();
await?page.click(‘a.my-link‘);?
await?navigationPromise;?

另外,我们如果需要更细粒度的等待,可以使用其它几个wait函数,如如果我们要等待某图片的第一次加载。

?

执行脚本

执行脚本最常用的函数是page.evaluate,它类似于在控制台中执行指令。

console.log(await page.evaluate(‘1 + 2‘));
var title = await page.evaluate(‘document.title‘)

它也可以用来执行写好的node函数,实际上该函数是在浏览器中执行的,但可以像本地函数一样编写,还支持参数传值。

var?title?=?await?page.evaluate(async?(i)?=>?{
????return?document.title?+?‘?‘?+?i;
},?‘hello‘);

console.log(title);

虽然这node函数不能调试,但仍然是有非常大的好处的,

  1. 不用考虑字符串转义的问题,书写起来非常直接
  2. 脚本在IDE中有高亮显示和智能提示的,写起来更加方便

另外,还有几个其它的执行脚本的函数,应用于不同的场合,也是非常有用的。

  1. page.evaluateHandle(pageFunction, ...args)
  2. page.evaluateOnNewDocument(pageFunction, ...args)
  3. page.$$eval(selector, pageFunction[, ...args])
  4. page.$eval(selector, pageFunction[, ...args])

例如:

const?searchValue?=?await?page.$eval(‘#search‘,?el?=>?el.value);
const?preloadHref?=?await?page.$eval(‘link[rel=preload]‘,?el?=>?el.href);
const?html?=?await?page.$eval(‘.main-container‘,?e?=>?e.outerHTML);

?

信息查看

puppeteer提供了一些查看页面信息的函数,

  1. page.url()
  2. page.content()
  3. page.frames()
  4. page.mainFrame()
  5. page.metrics()
  6. page.target()
  7. page.title()
  8. page.viewport()

?

请求中断

page.setRequestInterception提供了中断请求的机制,例如,我们可以通过它实现一个无图模式。

await?page.setRequestInterception(true);
page.on(‘request‘,?interceptedRequest?=>?{
????if?(interceptedRequest.url().endsWith(‘.png‘)?||?interceptedRequest.url().endsWith(‘.jpg‘))
????????interceptedRequest.abort();
????else
????????interceptedRequest.continue();
});
await?page.goto(‘https://example.com‘);

这里有一个interceptedRequest对象,它提供了三种响应模式:abort、continue和respond。

?

内容注入

内容保存主要包括注入javascript和style,都是非常有用的函数。

  1. page.addScriptTag(options)
  2. page.addStyleTag(options)

?

事件

puppteer提供了一系列事件的通知:

close

frameattached

pageerror

console

framedetached

request

dialog

framenavigated

requestfailed

domcontentloaded

load

requestfinished

error

metrics

response

简单的示例如下:

page.on(‘load‘,
????async?()?=>?{
????????console.log(‘page?loading?done,?start?fetch...‘);
????});

?

内容保存

内容保存主要包括保存为pdf和截图

  1. page.pdf(options)
  2. page.screenshot([options])

?

不常用

另外,还有一些用的较少的函数,但一旦用上也是能解决比较问题的。

  1. page.authenticate(credentials)
  2. page.bringToFront()
  3. page.browser()
  4. page.close(options)
  5. page.coverage
  6. page.exposeFunction(name, puppeteerFunction)
  7. page.queryObjects(prototypeHandle)
  8. page.setBypassCSP(enabled)
  9. page.setCacheEnabled(enabled)
  10. page.setContent(html)
  11. page.setDefaultNavigationTimeout(timeout)
  12. page.setJavaScriptEnabled(enabled)
  13. page.setOfflineMode(enabled)
  14. page.tracing

除了page对象外,还有其他的几个对象,如果有空再详细的介绍一下。

以上是关于使用Puppeteer进行数据抓取——Page对象的主要内容,如果未能解决你的问题,请参考以下文章

使用Puppeteer进行数据抓取——图片下载

使用CucumberJS / Puppeteer,如何使用多个场景扩展Page对象?

使用Chrome快速实现数据的抓取—— puppeteer

已在Puppeteer中定义函数后如何调用该函数

Puppeteer page.evaluate querySelectorAll 返回空对象

puppeteer + nodejs 抓取网页内容