利用nodejs第三方库puppeteer来解决某些用js渲染页面的登陆页模拟登陆问题

偶然发现一个叫puppeteer的库,这样解释的:“谷歌浏览器在17年自行开发了Chrome Headless特性,并与之同时推出了puppeteer,可以理解成我们日常使用的Chrome的无界面版本以及对其进行操控的js接口套装”。简单说就是模拟浏览器行为的第三方库,再说直白点,只要用浏览器访问的页面,它都可以去操作,强大之至。
想起朋友在做一个学校教务系统爬虫,苦于该校登陆界面是用js渲染的,登陆接口会拼接上js加密的字符串,这个字符串只有在浏览器下才会动态生成,js又是瑞数加密,破解成本极高,极难,便来尝试利用puppeteer来模拟登陆获取用户数据。
现在开始,打开登陆界面开始分析
登陆页面
用puppeteer其实就是人怎么操作的,将它写成代码即可
1:打开网址
2:输入学号
3:输入密码
4:点击登陆
实现成代码便是:

  const puppeteer = require('puppeteer');
  const browser = await puppeteer.launch({
    ignoreDefaultArgs: ["--enable-automation"],
    headless: true,
    args: ['--no-sandbox', '--disable-setuid-sandbox']
  }); //去除自动化测试的提醒

  const page = await browser.newPage();
  //为了像一个浏览器,伪造更多数据
  await page.evaluateOnNewDocument(() => { //在每个新页面打开前执行以下脚本
    const newProto = navigator.__proto__;
    delete newProto.webdriver; //删除navigator.webdriver字段
    navigator.__proto__ = newProto;
    window.chrome = {}; //添加window.chrome字段,为增加真实性还需向内部填充一些值
    window.chrome.app = {
      "InstallState": "hehe",
      "RunningState": "haha",
      "getDetails": "xixi",
      "getIsInstalled": "ohno"
    };
    window.chrome.csi = function () {};
    window.chrome.loadTimes = function () {};
    window.chrome.runtime = function () {};
    Object.defineProperty(navigator, 'userAgent', { //userAgent在无头模式下有headless字样,所以需覆写
      get: () => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.113 Safari/537.36",
    });
    Object.defineProperty(navigator, 'plugins', { //伪装真实的插件信息
      get: () => [{
        "description": "Portable Document Format",
        "filename": "internal-pdf-viewer",
        "length": 1,
        "name": "Chrome PDF Plugin"
      }]
    });
    Object.defineProperty(navigator, 'languages', { //添加语言
      get: () => ["zh-CN", "zh", "en"],
    });
    const originalQuery = window.navigator.permissions.query; //notification伪装
    window.navigator.permissions.query = (parameters) => (
      parameters.name === 'notifications' ?
      Promise.resolve({
        state: Notification.permission
      }) :
      originalQuery(parameters)
    );
  })
  await page.goto('http://xxx/Login.html')
  await page.waitForNavigation();//等待加载完成
  await page.type('#txtUser', "20190xxxxx");
  await page.type('#txtPWD', '42052120xxxxx');
  await page.click('#ibtnLogin');
  await page.waitForNavigation();
  

登陆成功
登陆成功,接着点击【成绩单】
成绩单

  const [response] = await Promise.all([
    page.waitForNavigation(),
    page.click('a[href="SearchInfo/Score/ScoreList.aspx"]')
  ]);
  let res = await page.$eval('ul.listUl', el => el.outerHTML)//拿到dom
  await browser.close();

如果输出res则是这个表格的所有代码
效果图
这玩意还可以截屏,没错,你看不到界面,还可以用方法截屏

    await page.screenshot({

        path: 'c:/temp/temp.png'

    })

加上这段就可以截屏并存在C盘下temp文件夹里,如果没有文件夹不会自动创建,需要自己提前创建好

是不是感觉好用到爆,可是这玩意儿就好比后台打开了一个浏览器运行的,如果多个请求进来,后台也会打开多个任务,分别执行,但是并发高了岂不是服务器都要炸了。那能不能放到云函数里呢?答案是可以的。

放到微信小程序云函数中可以直接运行,无需安装库,官方nodejs10版本已经默认安装了,直接引用就可以用
在这里插入图片描述
再来看耗时和所占内存大小
云函数执行所耗时长及资源
耗时2789ms,内存135.74MB完全可以接受。

总结:puppeteer模拟登陆可以做任何形式的网站,但是速度有点慢

优点:最大优点也是优势就是可以做那些做了反爬虫的网站,和js渲染的网站
缺点:内存黑洞,放服务器上不能应对高并发(用云函数可以解决),速度慢,因为是模拟人工操作,输入内容都是一个个值输入,还要等待加载,所以比常规的请求接口方式慢不少

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值