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.mouse
  • page.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,都是非常有用的函数。

  • page.addScriptTag(options)
  • page.addStyleTag(options)
  • puppteer提供了一系列事件的通知:

  • 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对象外,还有其他的几个对象,如果有空再详细的介绍一下。