使用Puppeteer进行数据抓取——Page对象
Posted TianFang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Puppeteer进行数据抓取——Page对象相关的知识,希望对你有一定的参考价值。
page对象是puppeteer最常用的对象,它可以认为是chrome的一个tab页,主要的页面操作都是通过它进行的。Google的官方文档详细介绍了page对象的使用,这里我只是简单的小结一下。
客户端模拟
页面模拟设置相关函数有如下几个,
- page.setViewport: 设置视图大小
- page.setUserAget: 设置UserAgent
- 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
?
页面跳转
页面跳转相关函数有如下几个,
- page.goto(url, options)
- page.goBack(options)
- page.goForward(options)
- page.reload(options)
其中比较常用的是page.goto,相当于在浏览器中输入了地址,然后回车。此外,也可以同通过执行js跳转和模拟点击link跳转。
?
选择
常用的元素函数选择有:
- page.$(selector)
- page.$$(selector)
它们的功能类似于document.querySelector和document.querySelectorAll。
它们返回的对象是<Promise<?ElementHandle>>,可以用它判断某元素是否存在,也可以对ElementHandle执行相应操作,具体在后面的ElementHandle中介绍。
另外,还有一个使用xpath的select版本。
- page.$x(expression)
虽然这个用的相对少点,但也还是非常有用的。
?
模拟输入
page本身提供原始的mouse和keyboard的模拟输入类。
但同时也提供更方便快捷的模拟输入函数
- page.click(selector[, options])????????在被选择元素上模拟点击
- page.type(selector, text[, options])????在被选择的输入框中输入
- page.hover(selector)????????????????模拟鼠标移动到被选择元素上
- page.select(selector, ...values)????????在被选择元素上模拟选择select选项
- 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函数不能调试,但仍然是有非常大的好处的,
- 不用考虑字符串转义的问题,书写起来非常直接
- 脚本在IDE中有高亮显示和智能提示的,写起来更加方便
另外,还有几个其它的执行脚本的函数,应用于不同的场合,也是非常有用的。
- page.evaluateHandle(pageFunction, ...args)
- page.evaluateOnNewDocument(pageFunction, ...args)
- page.$$eval(selector, pageFunction[, ...args])
- 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提供了一些查看页面信息的函数,
- page.url()
- page.content()
- page.frames()
- page.mainFrame()
- page.metrics()
- page.target()
- page.title()
- 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,都是非常有用的函数。
?
事件
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和截图
- page.pdf(options)
- page.screenshot([options])
?
不常用
另外,还有一些用的较少的函数,但一旦用上也是能解决比较问题的。
- page.authenticate(credentials)
- page.bringToFront()
- page.browser()
- page.close(options)
- page.coverage
- page.exposeFunction(name, puppeteerFunction)
- page.queryObjects(prototypeHandle)
- page.setBypassCSP(enabled)
- page.setCacheEnabled(enabled)
- page.setContent(html)
- page.setDefaultNavigationTimeout(timeout)
- page.setJavaScriptEnabled(enabled)
- page.setOfflineMode(enabled)
- page.tracing
除了page对象外,还有其他的几个对象,如果有空再详细的介绍一下。
以上是关于使用Puppeteer进行数据抓取——Page对象的主要内容,如果未能解决你的问题,请参考以下文章
使用CucumberJS / Puppeteer,如何使用多个场景扩展Page对象?