Puppeteer的使用

摘要:
//下面是使用Browser创建Page的例子constpuppeteer=require;puppeteer.launch().then;//一个断开连接和重连到Browser的例子:constpuppeteer=require;puppeteer.launch().then;3.PagePage提供操作一个tab页或者extensionbackgroundpage的方法。下面的例子创建一个Page实例,导航到一个url,然后保存截图:constpuppeteer=require;puppeteer.launch().then;4.KeyboardKeyboard提供一个接口来管理虚拟键盘.高级接口为keyboard.type,其接收原始字符,然后在你的页面上生成对应的keydown,keypress/input,和keyup事件.为了更精细的控制,你可以使用keyboard.down,keyboard.up和keyboard.sendCharacter来手动触发事件,就好像这些事件是由真实的键盘生成的.//持续按下Shift来选择一些字符串并且删除的例子:awaitpage.keyboard.type('HelloWorld!

资源链接

Puppeteer官方文档:https://github.com/GoogleChrome/puppeteer

puppeteer社区:https://slack.com/

安装

//安装puppeteer
cnpm i puppeteer
//安装puppeteer-core
cnpm i puppeteer-core

常用方法或属性

1.puppeteer.launch([options])

//Puppeteer 模块提供了一种启动 Chromium 实例的方法。 下面就是使用 Puppeteer 进行自动化的一个典型示例:
const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser =>{
  const page = awaitbrowser.newPage();
  await page.goto('https://www.google.com');
  //其他操作...
  awaitbrowser.close();
});

2.Browser

当 Puppeteer 连接到一个 Chromium 实例的时候会通过 puppeteer.launch 或 puppeteer.connect 创建一个 Browser 对象。

//下面是使用 Browser 创建 Page 的例子
const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser =>{
  //存储节点以便能重新连接到 Chromium
  const browserWSEndpoint =browser.wsEndpoint();
  //从 Chromium 断开和 puppeteer 的连接
browser.disconnect();

  //使用节点来重新建立连接
  const browser2 = awaitpuppeteer.connect({browserWSEndpoint});
  //关闭 Chromium
  awaitbrowser2.close();
});
//一个断开连接和重连到 Browser 的例子:
const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser =>{
  //存储节点以便能重新连接到 Chromium
  const browserWSEndpoint =browser.wsEndpoint();
  //从 Chromium 断开和 puppeteer 的连接
browser.disconnect();

  //使用节点来重新建立连接
  const browser2 = awaitpuppeteer.connect({browserWSEndpoint});
  //关闭 Chromium
  awaitbrowser2.close();
});

3.Page

Page 提供操作一个 tab 页或者 extension background page 的方法。一个 Browser 实例可以有多个 Page 实例。

下面的例子创建一个 Page 实例,导航到一个 url ,然后保存截图:

const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser =>{
  const page = awaitbrowser.newPage();
  await page.goto('https://example.com');
  await page.screenshot({path: 'screenshot.png'});
  awaitbrowser.close();
});

4.Keyboard

Keyboard 提供一个接口来管理虚拟键盘. 高级接口为 keyboard.type, 其接收原始字符, 然后在你的页面上生成对应的 keydown, keypress/input, 和 keyup 事件.

为了更精细的控制(虚拟键盘), 你可以使用 keyboard.down, keyboard.up 和 keyboard.sendCharacter 来手动触发事件, 就好像这些事件是由真实的键盘生成的.

//持续按下 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');

5.Mouse

Mouse 类在相对于视口左上角的主框架 CSS 像素中运行。

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

//使用 ‘page.mouse’ 追踪 100x100 的矩形。
await page.mouse.move(0, 0);
awaitpage.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();

实战

实战01:跳转指定页面

源码:跳转到百度首页

const puppeteer=require('puppeteer');

(async ()=>{

    const browser = await puppeteer.launch({headless:false,defaultViewport:{1000,height:800}});
    const page=  awaitbrowser.newPage();
    await page.goto("https://www.baidu.com");

})();

Puppeteer的使用第1张

实战02:输入文本与元素点击

代码:在百度中搜索

const puppeteer=require('puppeteer');

(async ()=>{

    const browser = await puppeteer.launch({headless:false,defaultViewport:{1000,height:800}});
    const page=  awaitbrowser.newPage();
    await page.goto("https://www.baidu.com");  //跳转页面
    const input_text= await page.$("#kw");     //获取百度首页的搜索框。page.$()用来查找元素
    await input_text.type("Hello Word!");      //type()输入内容
    const btn_click=await page.$("#su");       //获取百度首页的搜索按钮。
    await btn_click.click();                   //点击搜索按钮。
})();

Puppeteer的使用第2张

实战03:获取文本元素值

源码:获取百度词条的值

const puppeteer=require('puppeteer');

(async ()=>{

    const browser = await puppeteer.launch({headless:false,defaultViewport:{1000,height:800}});
    const page=  awaitbrowser.newPage();
    await page.goto("https://www.baidu.com");  //跳转页面
    const input_text= await page.$("#kw");     //获取百度首页的搜索框。page.$()用来查找元素
    await input_text.type("Hello Word!");      //type()输入内容
    const btn_click=await page.$("#su");       //获取百度首页的搜索按钮。
    await btn_click.click();                  //点击搜索按钮。

    await page.waitFor('div#content_left > .result-op.c-container.xpath-log',{visible:true});//由于获取元素是异步操作,需要等待该元素加载出来
let resultText= await page.$eval('div#content_left > .result-op.c-container.xpath-log',ele=>{return ele.innerHTML})//获取元素并返回元素下的innerHTML。 .$eval表示获取单个元素
    console.log("result is ",resultText);//在控制台打印出值。
})();

Puppeteer的使用第3张

实战04:puppeteer文件上传操作

代码:在百度首页上传图片

const puppeteer=require('puppeteer');

(async ()=>{
    const browser = await puppeteer.launch({headless:false,defaultViewport:{1000,height:800}});
    const page = awaitbrowser.newPage();
    await page.goto('https://www.baidu.com');

    await page.waitForSelector('span.soutu-btn');  //等待选择元素出现
    const soutuBtn=await page.$('span.soutu-btn'); //获取图片按钮
    await soutuBtn.click();                        //点击展开图片按钮

    await page.waitForSelector('input.upload-pic');   //等待上传按钮出现
    const uploadPic=await page.$('input.upload-pic'); //获取上传按钮
    await uploadPic.uploadFile('C:\Capture.PNG');    //上传图片。注意:路径要用双斜杠。
})();

Puppeteer的使用第4张

实战05:puppeteer处理多个元素

代码:打印京东上的手机信息

const puppeteer = require('puppeteer');

(async()=>{
    const browser=await puppeteer.launch({headless:false,defaultViewport:{1000,height:800}});
    const page =awaitbrowser.newPage();
    await page.goto('https://www.jd.com');

    await page.waitFor("#key");
    const inputText=await page.$("#key");
    await inputText.type("手机");
    await page.keyboard.press('Enter');

    await page.waitForSelector("ul.gl-warp > li");
    const items=await page.$$eval("ul.gl-warp > li",eles=>eles.map(ele=>ele.innerText));
    console.log("手机列表=",items);
})();

Puppeteer的使用第5张

实战06:puppeteer切换iframe进行操作

iframe跟page的用法类似。使用前需要切换到iframe里面并用src定位要操作的iframe。

操作可参考:https://github.com/GoogleChrome/puppeteer/blob/v1.20.0/docs/api.md#class-frame

代码:自动在阿里云的注册iframe里面填写注册信息

const puppeteer = require('puppeteer');

(async()=>{
    const browser = await puppeteer.launch({headless:false,defaultViewport:{1000,height:800}});
    const page = awaitbrowser.newPage();
    await page.goto("https://account.aliyun.com/register/register.html");

    //切换iframe
    const frame= await page.frames().find(frame=>frame.url().includes("https://passport.aliyun.com"));//切换iframe,并找到对应src的iframe
    await frame.waitFor("input#nick"); //等待输入框加载完成
    const nick =await frame.$("input#nick");//获取输入框
    await nick.type("测试用户");//输入数据
})();

Puppeteer的使用第6张

实战07:puppeteer拖拽操作阿里云验证码

代码:自动操作阿里云验证滑动模块

const puppeteer = require('puppeteer');

(async()=>{
    const browser = await puppeteer.launch({headless:false,defaultViewport:{1000,height:800},ignoreDefaultArgs:["--enable-automation"]});//在有些页面可能需要将automation提示去掉。使用ignoreDefaultArgs:["--enable-automation"]参数
    const page = awaitbrowser.newPage();
    await page.goto("https://account.aliyun.com/register/register.html");

    //切换iframe
    const frame= await page.frames().find(frame=>frame.url().includes("https://passport.aliyun.com"));//切换iframe,并找到对应src的iframe
    await frame.waitForSelector("span#nc_1_n1z");//等待滑动块加载完成
    const span =await frame.$("span#nc_1_n1z");  //获取滑动元素
    const spanInfo=await span.boundingBox();     //获取滑动块的信息,包括位置(x,y)以及宽和高
    //console.log(spanInfo);

    await frame.waitForSelector("div#nc_1_n1t"); //等待包裹滑块的div加载完成
    const outDiv=await frame.$("div#nc_1_n1t");  //获取包裹滑块的div
    const outDivInfo=await outDiv.boundingBox(); //获取包裹滑块的div的信息,包括位置(x,y)以及宽和高
    //console.log(outDivInfo);

    await page.mouse.move(spanInfo.x,spanInfo.y);//将鼠标移动到滑块位置
    await page.mouse.down();                     //将鼠标按下(默认是左键)
    for(var i=0;i<outDivInfo.width;i++){
        page.mouse.move(spanInfo.x+i,spanInfo.y);//让鼠标向左移动outDivInfo的宽度距离
}
    await page.mouse.up();                       //将鼠标松开
})();

Puppeteer的使用第7张

实战08:puppeteer自动抓取百度新闻上的语句并自动登录微博账户发一条微博

代码:这个实战似乎翻车了,被微博检测到自动化而被要求输入验证码

const puppeteer = require('puppeteer');
const config=require('./config'); //为了保护我的个人隐私,所以我把账号和密码保存在了config文件中
(async ()=>{
    //console.log(config.username);
    //console.log(config.password);
    const browser = awaitpuppeteer.launch({
        headless:false,
        defaultViewport:{1280,height:800},
        ignoreDefaultArgs:["--enable-automation"],//移除自动化,防止页面生成验证码
        slowMo:200,//输入延迟时间
        args:['--window-size:1280,800'],//调整窗口大小
});
    const page= awaitbrowser.newPage();
    await page.goto('https://news.baidu.com/',{waitUntil:"networkidle2"});//第一个参数是要前往的地址url,第二个参数是保证页面全部加载

    await page.waitForSelector('#imgTitle>a>strong');
    const newsText=await page.$eval("#imgTitle>a>strong",ele=>ele.innerText);//匹配第一个元素
    //console.log(newsText);

    await page.goto('https://weibo.com',{waitUntil:"networkidle2"});
    await page.waitFor(5*1000);//防止被检测
    await page.reload();//防止被检测

    await page.waitForSelector('#loginname');                   //等待账号输入框加载完成
    const inputText=await page.$('#loginname');                 //获取账号输入框元素
    await inputText.click();                                    //防止被检测,具体情况具体分析
    awaitinputText.type(config.username);

    await page.waitForSelector('input[name="password"]');       //等待密码输入框加载完成
    const inputPwd=await page.$('input[name="password"]');      //获取密码输入框
    await inputPwd.click();//防止被检测,具体情况具体分析
    awaitinputPwd.type(config.password);


    await page.waitForSelector('a[action-type="btn_submit"]');  //等待确认按钮加载
    const submit=await page.$('a[action-type="btn_submit"]');   //获取确认按钮
    await submit.click();                                       //点击
})();

Puppeteer的使用第8张

实战09:puppeteer模拟快捷键

代码演示:https://github.com/GoogleChrome/puppeteer/blob/v1.20.0/docs/api.md#class-keyboard

实战10:puppeteer切换浏览器tab页

主要用到api:browser.target();

文档:https://github.com/GoogleChrome/puppeteer/blob/v1.20.0/docs/api.md#class-browser

实战11:puppeteer处理弹出的对话框

主要用到的api:Dialog处理弹出的内容

文档:https://github.com/GoogleChrome/puppeteer/blob/v1.20.0/docs/api.md#class-dialog

实战12:puppeteer执行JavaScript方法

主要用到的方法:page.evaluate(()=>{ 在这里面可以写任意JS代码 })

文档:https://github.com/GoogleChrome/puppeteer/blob/v1.20.0/docs/api.md#class-page

实战13:配置typescript环境,并在其中使用puppeteer

待完善

实战14:获取全屏截图

const puppeteer =require('puppeteer');//引入puppeteer
(async()=>{//使用自执行函数
    const browser = await puppeteer.launch();//生成browser实例

    const page = await browser.newPage();//生成一个页面
    await page.goto('https://cn.aliyun.com/');//前往页面
console.log(await page.content());//打印页面信息(源码)
    await page.screenshot({//截图
    path: 'ali.png',
    fullPage: true});

    await browser.close();//关闭browser实例
})();

Puppeteer的使用第9张

Puppeteer的使用第10张Puppeteer的使用第11张文章就分享到这,欢迎关注“前端大神之路”Puppeteer的使用第11张

Puppeteer的使用第13张

免责声明:文章转载自《Puppeteer的使用》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇mirai 使用教程MySQL集群搭建下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

js数组中的每一项异步请求

数组中的每一个选项,都进行一次异步请求,然后所有请求完成再操作返回值,Promise.all     getInfo = (param) => {         const { getData } = this.props // getData为接口请求         return new Promise(resolve => {    ...

OpenCV 图像采样 插值 几何变换

InitLineIterator 初始化线段迭代器 int cvInitLineIterator( const CvArr* image, CvPoint pt1, CvPoint pt2, CvLineIterator* line_iterator, int connectivity=8 ); image 带采线段的输入图像. pt1 线段起始点 pt...

nodejs bull 实现延时队列

bull.js const Queue = require('bull'); const queue = new Queue('nike', { redis: { port: 6379, host: '127.0.0.1', db: 3, password: null }, prefix: 'nike_',...

jQuery同步Ajax带来的UI线程阻塞问题及解决办法

俗话说不作死就不会死,今天作死了一回,写了一个比较二逼的函数,遇到了同步Ajax引起的UI线程阻塞问题,在此记录一下。   事情起因是这样的,因为页面上有多个相似的异步请求动作,本着提高代码可重用性的原则,我封装了一个名为getData的函数,它接收不同参数,只负责获取数据,然后把数据return。基本的逻辑剥离出来是这样的: function get...

关于for循环里面异步操作的问题

一、使用自执行函数   1、当自执行函数在循环当中使用时,自执行函数会在循环结束之后才会运行。比如你在自执行函数外面定义一个数组,在自执行函数当中给这个数组追加内容,你在自执行函数之外输出时,会发现这个数组当中仕么都没有,这就是因为自执行函数会在循环运行完后才会执行。   2、当自执行函数在循环当中使用时,要是自执行函数当中嵌套ajax,那么循环当中的下标...

C/C++文件输入输出操作——FILE*、fstream、windowsAPI

基于C的文件操作在ANSI C中,对文件的操作分为两种方式,即流式文件操作和I/O文件操作,下面就分别介绍之。 一、流式文件操作这种方式的文件操作有一个重要的结构FILE,FILE在头文件stdio.h中定义如下: typedef struct {int level;unsigned flags;char fd;unsigned char hold;int...