一、获取元素信息

page.$(selector)

在页面内执行 document.querySelector。

 

page.$$(selector)

在页面内执行 document.querySelectorAll。

 

page.$x(expression)

解析指定的XPath表达式。

 

page.$$eval(selector, pageFunction[, ...args])

在页面内执行 Array.from(document.querySelectorAll(selector)),然后把匹配到的元素数组作为第一个参数传给 pageFunction。

//计算div的个数

const divsCounts = await page.$$eval('div', divs => divs.length);

 

page.$eval(selector, pageFunction[, ...args])

在页面内执行 document.querySelector,然后把匹配到的元素作为第一个参数传给pageFunction。

//示例

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);

 

page.evaluate(pageFunction[, ...args])

执行脚本

//示例

const bodyHandle = await page.$('body');

const html = await page.evaluate(body => body.innerHTML, bodyHandle);

await bodyHandle.dispose();

 

page.evaluateHandle(pageFunction[, ...args])

此方法和 page.evaluate 的唯一区别是此方法返回的是页内类型(JSHandle)

const aHandle = await page.evaluateHandle(() => document.body);

const resultHandle = await page.evaluateHandle(body => body.innerHTML, aHandle);

console.log(await resultHandle.jsonValue());

await resultHandle.dispose();

 

page.evaluateOnNewDocument(pageFunction[, ...args])

在所属页面的任意 script 执行之前被调用。常用于修改页面js环境

复制代码

// preload.js
// 重写 `languages` 属性,使其用一个新的get方法
Object.defineProperty(navigator, "languages", {
  get: function() {
    return ["en-US", "en", "bn"];
  }
});

复制代码

 

// 假设 preload.js 和当前的代码在同一个目录
const preloadFile = fs.readFileSync('./preload.js', 'utf8');
await page.evaluateOnNewDocument(preloadFile);

 

jsHandle.getProperties()

jsHandle.getProperty(propertyName)

jsHandle.jsonValue()

复制代码

//示例
const handle = await page.evaluateHandle(() => ({window, document}));
const properties = await handle.getProperties();
const windowHandle = properties.get('window');
const documentHandle = properties.get('document');
await handle.dispose();

复制代码

 

二、模拟用户操作

1.Page类

page.click(selector[, options])

找到一个匹配 selector 选择器的元素,如果需要会把此元素滚动到可视,然后通过 page.mouse 点击它。

要注意如果 click() 触发了一个跳转,会有一个独立的 page.waitForNavigation() Promise对象需要等待。 正确的等待点击后的跳转是这样的:

const [response] = await Promise.all([

  page.waitForNavigation(waitOptions),

  page.click(selector, clickOptions),

]);

 

page.focus(selector)

找到一个匹配selector的元素,并且把焦点给它

 

page.hover(selector)

找到一个匹配的元素,如果需要会把此元素滚动到可视,然后通过 page.mouse 来hover到元素的中间。

 

page.select(selector, ...values)

当提供的下拉选择器完成选中后,触发change和input事件

page.select('select#colors', 'blue'); // 单选择器

page.select('select#colors', 'red', 'green', 'blue'); // 多选择器

 

page.type(selector, text[, options])

每个字符输入后都会触发 keydown, keypress/input 和 keyup 事件

要点击特殊按键,比如 Control 或 ArrowDown,用 keyboard.press

page.type('#mytextarea', 'Hello'); // 立即输入

page.type('#mytextarea', 'World', {delay: 100}); // 输入变慢,像一个用户

 

2.Mouse类

每个 page 对象都有它自己的 Mouse 对象,使用见 page.mouse

mouse.click(x, y, [options])

mouse.down([options])

mouse.move(x, y, [options])

mouse.up([options])

// 使用 ‘page.mouse’ 追踪 100x100 的矩形。

await page.mouse.move(0, 0);

await page.mouse.down();

await page.mouse.move(0, 100);

await page.mouse.move(100, 100);

await page.mouse.move(100, 0);

await page.mouse.move(0, 0);

await page.mouse.up();

 

3.Keyboard类

keyboard.down(key[, options])

keyboard.press(key[, options])

keyboard.sendCharacter(char)

keyboard.type(text, options)

keyboard.up(key)

 

按下 Shift 来选择一些字符串并且删除的例子:

await page.keyboard.type('Hello World!');

await page.keyboard.press('ArrowLeft');

 

await page.keyboard.down('Shift');

for (let i = 0; i < ' World'.length; i++)

  await page.keyboard.press('ArrowLeft');

await page.keyboard.up('Shift');

 

await page.keyboard.press('Backspace');

// 结果字符串最终为 'Hello!'

按下 A 的例子:

await page.keyboard.down('Shift');

await page.keyboard.press('KeyA');

await page.keyboard.up('Shift');

 

三、选择器语法

1.Document.querySelector()

格式:element = parentNode.querySelector(selectors);

 

2.Document.querySelectorAll()

格式:elementList = parentNode.querySelectorAll(selectors);

 

获取文档中所有<p>元素的NodeList

获取文档中类名为 "myclass" 的元素的NodeList

var matches = document.querySelectorAll("p");

var el = document.querySelector(".myclass");

 

获取文档中所有class包含"note"或"alert"的<div>元素的列表,

var matches = document.querySelectorAll("div.note, div.alert");

 

获取ID为"test"的容器内,其直接父元素是一个class为"highlighted"的div的所有<p>元素的列表。

var container = document.querySelector("#test"); var matches = container.querySelectorAll("div.highlighted > p");

 

获取class为"select"的容器内,其祖先元素是一个class为"outer"的下的所有class为“inner"的元素列表。(这里即使outer不在select内,inner也会被找到)

var select = document.querySelector('.select'); var inner = select.querySelectorAll('.outer .inner');

 

获取文档中属性名为"data-src"的iframe元素列表:

var matches = document.querySelectorAll("iframe[data-src]");

 

获取列表后,再找匹配项

var highlightedItems = userList.querySelectorAll(".highlighted");

highlightedItems.forEach(function(userItem)

  { deleteUser(userItem);

});

 

四、使用示例

1.获取所有链接的href、title信息

 

await page.goto('https://segmentfault.com/news/frontend')

var SfFeArticleList = await page.evaluate(() => {
    var list = [...document.querySelectorAll('.news__list .news__item-title a')]
    return list.map(el => {
        return {
       href: el.href.trim(), 
           title: el.innerText
   }
    })
})

 

 

2.获取属性为某个值的元素

 

var login = await page.$('.login')
await login.click()

var loginPhoneOrEmail = await page.$('[name=loginPhoneOrEmail]')
await loginPhoneOrEmail.click()
await page.type('123456789@163.com', {delay: 20})

var password = await page.$('[placeholder=请输入密码]')
await password.click()
await page.type('123456', {delay: 20})

var authLogin = await page.$('.panel .btn')
await authLogin.click()

 

 

3.获取符合条件的元素,再过滤,并点击

 

await page.evaluate(() => {
          let li = [...document.querySelectorAll('.category-list-box .category-list .item')]
          li.forEach(el => {
              if (el.innerText == '前端')
                  el.click()
          })
      })

var submitBtn = await page.$('.submit-btn')
await submitBtn.click()

 

 

4.找到元素

 

  const result = await page.evaluate(() => {
    let $ = window.$;
    let nodeItems = $('.list-wp a');
    let links = [];
    
    /* 获取对应的元素节点 */
    if(nodeItems.length >= 1) {
      nodeItems.each((index, item) => {
        let elem = $(item);
        let movieId = elem.find('div').data('id');
        let title = elem.find('.title').text();
        let rate = Number(elem.find('.rate').text());
        let poster = elem.find('img').attr('src').replace('s_ratio_poster','l_ratio_poster');

        links.push({
          movieId,
          title,
          rate,
          poster,
        })
      })
    }

    return links;
  });