Dart: puppeteer库

和node的差不多,只有写API不一样

  1. 安装依赖
dependencies:
  puppeteer: ^1.7.1
  1. 下载 chrome-win 到 <project_root>/.local-chromium/662092/ 下面,不然跑不起,要最新版的chromium,何以用cnpm下载 cnpm i puppeteer -S 然后在依赖里面找到复制出来。
  2. 跑起来 dart ./bin/main.dart
import 'package:puppeteer/puppeteer.dart';

main(List<String> arguments) async {
  var browser = await puppeteer.launch(headless: false);
  var myPage = await browser.newPage();
  await myPage.goto('https://www.github.com', wait: Until.networkIdle);
}

执行js

import 'package:puppeteer/puppeteer.dart';

main(List<String> arguments) async {
  var browser = await puppeteer.launch(
    headless: false,
    devTools: true,
  );
  var page = await browser.newPage();
  await page.goto(base_url);
  // 执行一段js
  var title = await page.evaluate('''(newTitle) => {
      document.title = newTitle;
      return document.title
    }''', args: ["hello world"]);
  print(title);

  // 两秒后关闭浏览器
  await Future.delayed(Duration(seconds: 2));
  await browser.close();
}

获取页面内的元素

  // document.querySelector 没找到返回null
  var target = await page.$('#nav-dongman');
  await target?.click()

  // document.querySelectorAll 没找到返回null
  var target = await page.$$('p');
  await target?.elementAt(0)?.click()

  // document.querySelector然后把匹配到的元素作为第一个参数传给 pageFunction
  var target = await page.$eval('#nav-dongman', 'e => e.children[0].href');
  print(target);

  // Array.from(document.querySelectorAll(selector)) 没找到返回null
  // 然后把匹配到的元素数组作为第一个参数传给 pageFunction
  // 如果 pageFunction 返回的是 Promise,那么此方法会等 promise 完成后返回其返回值
  var target = await page.$$eval('p', '(es, index) => es[index].tagName', args: [0]);
  print(target);

  // 找到一个匹配 selector 选择器的元素,并点击它
  // 如果需要会把此元素滚动到可视,然后通过 page.mouse 点击它。 如果选择器没有匹配任何元素,此方法将会报错
  await page.click('#nav-dongman')
  

  // 找到一个匹配selector的元素,并且把焦点给它。 如果没有匹配的元素,此方法将报错
  page.focus(selector)


  // 加载到页面中的所有iframe标签
  // page.frames()
  
  // 要hover的元素的选择器,如果有多个匹配的元素,hover第一个
  page.hover(selector)

  // page.select(selector, ...values)
  // 当提供的选择器完成选中后,触发change和input事件 如果没有元素匹配指定选择器,将报错
  await page.select('select#colors', ['blue'])

  // 要点击的元素的选择器。如果有多个匹配的元素,点击第一个
  // 如果需要会把此元素滚动到可视,然后通过 page.touchscreen 来点击元素的中间位置 如果没有匹配的元素,此方法会报错
  await page.tap('#a')

  // 返回页面标题
  await page.title;
  
// 返回页面的 url
  await page.url;


  // 要输入内容的元素选择器。如果有多个匹配的元素,输入到第一个匹配的元素
  // 每个字符输入后都会触发 keydown, keypress/input 和 keyup 事件
  // 要点击特殊按键,比如 Control 或 ArrowDown,用 keyboard.press
  await page.type('form.form-horizontal input.form-control', 'hello world',
      delay: Duration(microseconds: 300))


  // 等待指定的选择器匹配的元素出现在页面中
  // 如果调用此方法时已经有匹配的元素,那么此方法立即返回。 如果指定的选择器在超时时间后扔不出现,此方法会报错
  ElementHandle first_img =
      await page.waitForSelector('img', timeout: Duration(seconds: 10));
  print(await first_img.propertyValue<String>('src'));

页面导航

page.goBack([options])  导航到页面历史的前一个页面
page.goForward([options])  导航到页面历史的后一个页面
page.goto(url[, options])  导航到的地址. 地址应该带有http协议, 比如 https://

向页面注入js

  // 添加一个script标签到body的最后
  await page.addScriptTag(
    content: 'alert(1)',
    type: 'text/javascript',
  );

向页面注入css

  // 添加一个style标签到head的最后面
  await page.addStyleTag(content: '''
      p {
        color: red;
      }''')

返回页面的html代码

page.content()

指定启动页面的模拟器

  var page = await browser.newPage();
  // devices: https://github.com/GoogleChrome/puppeteer/blob/master/lib/DeviceDescriptors.js
  await page
      .emulate(Device('iPhone 7', userAgent: "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1", viewport: DeviceViewport(
        width: 375,
        height: 667,
        deviceScaleFactor: 2,
        isMobile: true,
        hasTouch: true,
        isLandscape: false,
      )));
  await page.goto(base_url);

禁用js

改变这个值不会影响已经执行的js。下一个跳转会完全起作用。
await page.setJavaScriptEnabled(false);
posted @ 2019-05-25 14:22  Ajanuw  阅读(443)  评论(0编辑  收藏  举报