Node.js 小打小闹之无头浏览器

栏目: Node.js · 发布时间: 5年前

内容简介:前线客服传来消息 — “用户反馈一打开我们的 App,就直接闪退了”,刚听到这个消息,我很吃惊,上一期发的新版本 QA 都有验证过。难道是因为功能权限的问题导致的,赶紧跟客服确认具体情况。原来是客户前几天都能正常使用 App,今天一打开就莫名闪退了。刚了解清楚具体情况,一下子闪退的消息,就如滔滔江水一涌而来,随后也就开始了 iOS 证书过期填坑之旅。我们公司的产品有几十个客户,但并不是每一家客户都有反馈,而只是其中的几家。反馈闪退的几家客户中,都是同时使用 Android 和 iOS 两个平台,但反馈闪退

前线客服传来消息 — “用户反馈一打开我们的 App,就直接闪退了”,刚听到这个消息,我很吃惊,上一期发的新版本 QA 都有验证过。难道是因为功能权限的问题导致的,赶紧跟客服确认具体情况。原来是客户前几天都能正常使用 App,今天一打开就莫名闪退了。刚了解清楚具体情况,一下子闪退的消息,就如滔滔江水一涌而来,随后也就开始了 iOS 证书过期填坑之旅。

我们公司的产品有几十个客户,但并不是每一家客户都有反馈,而只是其中的几家。反馈闪退的几家客户中,都是同时使用 Android 和 iOS 两个平台,但反馈闪退问题的都是使用 iOS 平台的用户,Android 平台并没有出现闪退问题。

梳理完思路后,我们就想到了是不是反馈闪退的客户使用的 App 证书或描述文件出问题了,因此立马登陆苹果开发者后台,登陆后发现果然是几个客户使用的证书,今天就过期了。那是不是证书过期导致闪退的呢?原生开发人员,马上更新一下证书,打了个包进行验证。果然,用新的证书打出来的包,就能正常使用,不会出现闪退了。网上找了相关的资料,也很多小伙伴遇到同样的问题 —— “企业版证书过期,App 出现闪退”。问题是已经定位了,但客户那边怎么解决呢?客户一打开我们的 App 就立马闪退了,没有办法进行强制更新。此后,在网上绕了一大圈,看了很多文章,发现我们最终的方案,只能重新打包让用户重装。

苍天啊!大地啊!为什么苹果企业证书即将过期,没有发邮件通知,这真是一个大坑!!!事情竟然已经发生,只能咽下苦水,乖乖地接受外部的 “轰炸” 了。接下来我们立即针对闪退的客户重新打包,然后让公司客服与客户沟通,说明情况…

这个问题以后要如何避免?难道要安排专人,每天定时检查证书的有效性?最初的这个想法,其实我是拒绝的。这种脏活累活,肯定要请我们吃饭的家伙 —— ?(Computer)来帮我们处理咯。前阵子刚好偶遇谷歌出品的一个神器 —— GoogleChrome/ puppeteer (Headless Chrome Node API),接下来我们就先来介绍这款神器。

跳坑篇

puppeteer 简介

puppeteer 是一个 Node.js 的库,支持调用 Chrome 的 API 来操纵 Web,相比较 Selenium 或是 PhantomJS,它最大的特点就是它的操作 DOM 可以完全在内存中进行模拟既在 V8 引擎中处理而不打开浏览器,而且关键是这个是 Chrome 团队在维护,会拥有更好的兼容性和前景。

puppeteer 的神技:

  • 对网页进行截图保存为图片或 pdf。
  • 抓取单页应用(SPA)执行并渲染(解决传统 HTTP 爬虫抓取单页应用难以处理异步请求的问题)。
  • 做表单的自动提交、UI 的自动化测试、模拟键盘输入等。
  • 用浏览器自带的一些调试工具和性能分析 工具 帮助我们分析问题。
  • 在最新的无头浏览器环境里做测试、使用最新浏览器特性。
  • 写爬虫,做你想做的事情。

是不是感觉 puppeteer 棒棒哒。其实还有其它一些无头浏览器,比如:

  • phantomjs :Scriptable Headless WebKit 【Star - 25877】
  • slimerjs :A scriptable browser like PhantomJS, based on Firefox 【Star - 2738】
  • Splash :Lightweight, scriptable browser as a service with an HTTP API 【1974】
  • trifleJS :Headless automation for Internet Explorer 【Star - 764】

(友情提示:Star 统计时间 —— 2018-08-15)

简单介绍完 puppeteer ,接下来我们就来稍微介绍一下思路。其实实现思路很简单,只需要使用 puppeteer 模拟登录?开发者网站,进入证书管理的页面,获取所有证书的有效期,然后设置计算出即将过期的天数。

最终的流程如下:

  • 访问 开发者官网
  • 进入证书管理页面,获取指定类型证书(All、Pending、Development 或 Production)。
  • 取得证书列表,以当天的时间点为每个证书计算即将过期的天数。
  • 基于处理完的数据,进行预警通知(邮件、短信或微信)。

puppeteer 实战

基于 puppeteer API 的版本为: 0.11.0

const puppeteer = require('puppeteer');

(async() => {
    const browser = await puppeteer.launch({
        headless: false // 开发调试阶段,设置为false
    });
    const page = await browser.newPage();
    page.setViewport({
        width: 1376,
        height: 768,
    });
    page.on('response', async(response) => {
        if (response && response.status == 200) {
            // 判断是否加载完概览视图,然后再次进入证书页面
            if (response.url.indexOf('tpl.overview-view.html') != -1) {
                await getCertsInfo();
            }
            // 判断是否为生产环境证书列表请求
            if (response.url.indexOf('status=4&certificateStatus=0&type=distribution') 
                != -1) {
                const res = await response.json();
                if (res && res.certRequests) {
                    console.dir(calcCertsDays(res.certRequests));
                    await browser.close();
                }
            }
        }
    });

    // 跳转到苹果官网并等待页面资源加载完成
    await page.goto('https://developer.apple.com/cn/', {
        waitUntil: 'load'
    });

    // 跳转到登录页面
    await page.click('.ac-gn-account > a');
    await page.waitForSelector('#accountname', {
        timeout: 50000
    });
    await login();

    // 执行登录操作
    async function login() {
        await page.focus('#accountname');
        await page.type('开发者账号', { // 此处替换为真实账号
            delay: 100
        });
        await page.focus('#accountpassword');
        await page.type('开发者账号密码', { // 此处替换为真实密码
            delay: 100
        });
        await page.click('#submitButton2');
    }

    // 获取证书信息(等待模板加载完成后,才进入证书管理页面)
    async function getCertsInfo() {
        const CERT_ITEM_SELECTOR = '#main section.getting-started > a:nth-child(2)';
        await page.waitForSelector(CERT_ITEM_SELECTOR);
        await page.click(CERT_ITEM_SELECTOR);
        const PROD_CERT_SELECTOR = 'li.subitem > a[href*="certificate/distribution"]';
        await page.waitForSelector(PROD_CERT_SELECTOR);
        await page.click(PROD_CERT_SELECTOR);
        await page.waitForSelector(PROD_CERT_SELECTOR);
    }

    // 计算每个证书的天数
    function calcCertsDays(certs) {
        if (Array.isArray(certs)) {
            const today = new Date();
            return certs.map(cert => {
                return {
                    name: cert.name,
                    type: cert.typeString,// Apple Push Services || iOS Distribution
                    expirationDay: dateDiff(today, new Date(cert.expirationDate))
                };
            });
        }
    }

    // 计算两个日期的间隔天数
    function dateDiff(today, expirationDate) {
        return parseInt((Math.abs(expirationDate.getTime() - today.getTime())) 
          / 1000 / 60 / 60 / 24);
    }
})();

总结

通过 puppeteer 这款神器提供强大的 API,我们只是实现了基本功能,后面还有一些功能需要优化和开发,比如异常处理、账号信息灵活配置和预警机制等。个人感觉 puppeteer 在以后的工作中,还会有很多用武之地,比如此前本人使用 puppeteer 实现了简单的业务功能测试。

此外在填坑过程中,偶遇了另一款神器 —— fastlane (The easiest way to automate building and releasing your iOS and Android apps) ,感觉真是相见恨晚啊(前阵子部门刚花大力气,实现App自动打包)。有兴趣的小伙伴,可以了解一下 puppeteerfastlane 这两款神器。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

松本行弘的程序世界

松本行弘的程序世界

松本行弘 / 柳德燕、李黎明、夏倩、张文旭 / 人民邮电出版社 / 2011-8 / 75.00元

《松本行弘的程序世界》是探索程序设计思想和方法的经典之作。作者从全局的角度,利用大量的程序示例及图表,深刻阐述了Ruby编程语言的设计理念,并以独特的视角考察了与编程相关的各种技术。阅读《松本行弘的程序世界》不仅可以深入了解编程领域各个要素之间的关系,而且能够学到大师的思考方法。 《松本行弘的程序世界》面向各层次程序设计人员和编程爱好者,也可以供相关技术人员参考。一起来看看 《松本行弘的程序世界》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

随机密码生成器
随机密码生成器

多种字符组合密码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试