puppeteer的内部窗口和打开的外部窗口大小不一致
我们可以看到右侧和下边栏都有一个大的空白。
我们使用下面代码
const browser = await puppeteer.launch({
headless: false
});
const page = await browser.newPage();
await page.goto('https://google.com');
关于这个原因是因为默认情况下开启了ViewPort
的功能,这里可以通过defaultViewport:null选项来禁用
const browser = await puppeteer.launch({
headless: false,
defaultViewport: null
});
waitUntil
waitUntil代表什么时候才认为导航加载成功。
- load: window.onload事件被触发时候完成导航,某些情况下它根本不会发生。
- domcontentloaded: Domcontentloaded事件触发时候认为导航成功
- networkidle0: 在 500ms 内没有网络连接时就算成功(全部的request结束),才认为导航结束
- networkidle2: 500ms 内有不超过 2 个网络连接时就算成功(还有两个以下的request),就认为导航完成。
我们对比了下加载时长 networkidle0> networkidle2>load>domcontentloaded
使用networkidle0的时候,随时可能网络加载时间在2s以上。我们希望500ms的时长是可配置的,因为500ms太长了。
function waitForNetworkIdle(page, timeout, maxInflightRequests = 0) {
page.on('request', onRequestStarted);
page.on('requestfinished', onRequestFinished);
page.on('requestfailed', onRequestFinished);
let inflight = 0;
let fulfill;
let promise = new Promise(x => fulfill = x);
let timeoutId = setTimeout(onTimeoutDone, timeout);
return promise;
function onTimeoutDone() {
page.removeListener('request', onRequestStarted);
page.removeListener('requestfinished', onRequestFinished);
page.removeListener('requestfailed', onRequestFinished);
fulfill();
}
function onRequestStarted() {
++inflight;
if (inflight > maxInflightRequests)
clearTimeout(timeoutId);
}
function onRequestFinished() {
if (inflight === 0)
return;
--inflight;
if (inflight === maxInflightRequests)
timeoutId = setTimeout(onTimeoutDone, timeout);
}
}
// Example
await Promise.all([
page.goto('https://google.com'),
waitForNetworkIdle(page, 500, 0), // 和 'networkidle0'效果相同
]);
evaluate, evaluateHandle, exposeFunction
evaluate
page.evaluate(pageFunction, …args) 返回的是一个可序列化的对象。
const result = await page.evaluate((x) => {
return x;
}, 'abc')
上面这段代码可以返回abc
字段
const result = await page.evaluate(
x => {
return x;
},
() => 'abc'
);
console.log(result); // 返回undefined
exposeFunction
这个 API 用来在页面注册全局函数,因为有时候需要在页面处理一些操作的时候需要用到一些函数,虽然可以通过 page.evaluate()
API 在页面定义函数。
await page.exposeFunction('md5', text => '__' + text);
const result = await page.evaluate(() => {
return window.md5('abc');
});
console.log(result); // 返回 __abc
但是这里也需要注意一点,exposeFunction 也不能传递,也是需要序列化的对象
evaluateHandle
Page.evaluateHandle(pageFunction, …args) 在 Page 上下文执行一个 pageFunction, 返回 JSHandle 实体
evaluateHandle可以传递一个字符串或者函数,返回promise对象。
const func = () => 'abc';
const handle = await page.evaluateHandle(`(${func.toString()})`);
const abc = await page.evaluate(a => {
return a();
}, handle);