原文发自我的 GitHub 博客 https://github.com/xiaoyu2er/blog/issues/14
缘由
小 N 同学通讯录太多, 希望可以导出到 Excel 中, 网上大部分做法都需要安装软件或者还有自己整理数据, 太麻烦.
我们来试一试可不可以通过前端的思路来解决这个问题.
思路
拿到通讯录
导出到 Excel
既然是前端工程师, 那么最简单的方式就是登录微信 web 版, 直接去看微信活动通讯录的接口.
我们看一下
可以看到, 由于微信后端返回数据中中文出现了乱码, 暂且没有想好如何处理这些乱码.
但是界面中的中文确实正常的, 我们看一下有没有其他别的方法呢?
通过看网页结构, 我们发现这是一个用 AngularJS 1.x 编写的网页应用(出现了 ng-style ng-repeat 等关键词)
我们知道 AngularJS 中的双向绑定, 一般变量都会挂在 scope 上
既然所有的联系人都出现在了 $('.scroll-wrapper .J_ContactScrollBody')中, 那我们看看这个列表关联的 scope 中是否含有这些信息
- var scope = angular.element($('.scroll-wrapper .J_ContactScrollBody')).scope();
- var allContacts = scope.allContacts;
果不其然, 在 $('.scroll-wrapper .J_ContactScrollBody') 关联的 scope 上挂载有 allContracts
(其实在观察的过程中, 发现微信的工程师把所有的联系人信息放到了 Windows._contracts 上了, 这也是一种方法.)
拿到数据之后接下来就是导出到 Excel 了, 这里选用了 https://github.com/sheetjs/js-xlsx 库, 其中的细节不再赘述
直接看一下源码
源码 + 注释
- // 点击通讯录 tab
- $('.web_wechat_tab_friends').click();
- // 等待几秒钟...
- // 获取通讯录列表
- // 方法一
- var scope = angular.element($('.scroll-wrapper .J_ContactScrollBody')).scope();
- var allContacts = scope.allContacts;
- // 方法二
- // var allContacts = Object.keys(Windows._contacts).map(k => Windows._contacts[k]);
- // 过滤真实的用户
- var contacts = allContacts.filter(c => c.UserName);
- // 下载 Excel 脚本
- loadScript('https://oss.sheetjs.com/js-xlsx/xlsx.full.min.js')
- .then(() => {
- console.log('download js-xlsx successful');
- var config = {bookType: 'xlsx', bookSST: false, type: 'binary'};// 这里的数据是用来定义导出的格式类型
- var wb = {SheetNames: ['Sheet1'], Sheets: {}, Props: {}};
- // 通过 json_to_sheet 转成单页 (Sheet) 数据
- wb.Sheets['Sheet1'] = XLSX.utils.json_to_sheet(formatContacts(contacts));
- var fileName = '微信通讯录' + '.' + (config.bookType == "biff2" ? "xls" : config.bookType);
- saveAs(new Blob([s2ab(XLSX.write(wb, config))], {type: 'application/octet-stream'}), fileName);
- });
- // ---- helper functions -----
- /**
- * 将 contacts 转化成你需要的格式
- * 这里可以任意发挥
- * @param contacts
- * @returns {*}
- */
- function formatContacts(contacts) {
- return contacts.map(({NickName, Sex, RemarkName}) => {
- return {
- '昵称': NickName,
- '备注': RemarkName
- }
- })
- }
- /**
- * 加载 script
- * @param url
- * @returns {Promise}
- */
- function loadScript(url) {
- return new Promise((resolve) => {
- var head = document.getElementsByTagName('head')[0];
- var script = document.createElement('script');
- script.type = 'text/javascript';
- script.onload = resolve;
- script.src = url;
- head.appendChild(script);
- })
- }
- /**
- * 下载文件
- * @param obj
- * @param fileName
- */
- function saveAs(obj, fileName) {
- var a = document.createElement('a');
- a.download = fileName || '下载';
- a.href = URL.createObjectURL(obj);
- a.click(); // 模拟点击实现下载
- setTimeout(function () {
- URL.revokeObjectURL(obj); // 释放 objectURL
- }, 100);
- }
- /**
- * 字符串转字符流
- * @param s
- * @returns {ArrayBuffer}
- */
- function s2ab(s) {
- var buf = new ArrayBuffer(s.length);
- var view = new Uint8Array(buf);
- for (var i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
- return buf;
- }
参考文章
https://www.jianshu.com/p/044c183edf42
来源: https://juejin.im/post/5bebd0e5f265da61417120a9