chrome插件-实战篇(友盟导出数据)

一、功能介绍

主要是用于导出我们app 应用的埋点数据,2个app ,4个端的埋点数据,聚合成一个excel文档

二、实现思路

主要通过content.js页面注入,操作dom,抓取页面信息,利用浏览器缓存数据信息,通过jsontoexcel,转成文件

三、详细设计及编码

1、service_worker相关配置和编码

manifest.json 配置 
"background": {
        "service_worker": "background.js",
        "type": "module"
    },

background.js 编码

chrome.runtime.onInstalled.addListener(() => {

    chrome.contextMenus.create({
        id: "chatglm",
        title: "使用智谱清言",
        contexts: ["selection"] // "page" 表示菜单项将出现在页面的右键菜单中
    });
    chrome.contextMenus.create({
        id: "chatglmPage",
        title: "使用智谱清言",
        contexts: ["page"] // "page" 表示菜单项将出现在页面的右键菜单中
    });
    chrome.contextMenus.create({
        id: "allApp",
        title: "全部应用",
        contexts: ["page"] // "page" 表示菜单项将出现在页面的右键菜单中
    });
    chrome.contextMenus.create({
        id: "Android1",
        title: "安卓1埋点",
        contexts: ["page"] // "page" 表示菜单项将出现在页面的右键菜单中
    });
    chrome.contextMenus.create({
        id: "Android2",
        title: "安卓2埋点",
        contexts: ["page"] // "page" 表示菜单项将出现在页面的右键菜单中
    });
    chrome.contextMenus.create({
        id: "IOS2",
        title: "IOS1埋点",
        contexts: ["page"] // "page" 表示菜单项将出现在页面的右键菜单中
    });
    chrome.contextMenus.create({
        id: "IOS2",
        title: "IOS2埋点",
        contexts: ["page"] // "page" 表示菜单项将出现在页面的右键菜单中
    });
});

在浏览器插件上安装的时候添加菜单项

效果如下

2、 监听右键菜单项的点击事件,并跳转到指定页面

chrome.contextMenus.onClicked.addListener((info, tab) => {
    if (["chatglmPage", "allApp", "Android1", "Android2", "IOS1", "IOS1"].includes(info.menuItemId)) {
        // 当用户点击右键菜单的“示例菜单项”时,执行以下操作
        chrome.scripting.executeScript({
            target: { tabId: tab.id },
            function: openInNewTab,
            args: [info.menuItemId]
        });
    }
    if (info.menuItemId == "chatglm") {
        chrome.tabs.create({
            url: "https://chatglm.cn/",
            active: true
        });
    }
});

function openInNewTab(id) {
    let url = ''
    let obj = {
        "Android1": '6461d579', "Android2": '6461d6b', "IOS1": '6461d65', "IOS2": '6461d6c'
    }
    if (id == "allApp") {
        url = 'https://mobile.umeng.com/platform/apps/list'
    } else if (id == "chatglmPage") {
        url = 'https://chatglm.cn/'
    } else {
        url = `https://mobile.umeng.com/platform/${obj[id]}/function/events/dashboard`
        console.log(id, obj[id], url)

    }
    window.location.href = url;
}

3、content_scripts 相关配置和编码

manifest.json 配置
"content_scripts": [
        {
            "matches": [
                "https://*/*"
            ],
            "css": [
                "bossjob.css"
            ],
            "js": [
                "jquery-2.1.4.min.js",
                "JsonExportExcel.min.js",
                "bossjob.js"
            ]
        }
    ],
bossjob.js 编码
浏览器缓存函数封装
async function getAllAppEvent() {
        // let ret = await clearStorage()
        // console.log(ret,'dsfdfds')

        let arr = ["Android1", "Android2", "IOS1", "IOS2"]
        let ret = await getStorageItem(null)
        if (!ret.Android1) {
            chrome.runtime.sendMessage({ action: "showNotification", title: "Notification", message: `缺少安卓1数据!` });
            return openInNewTab("Android1")
        }
        if (!ret.Android2) {

            chrome.runtime.sendMessage({ action: "showNotification", title: "Notification", message: `缺少安卓2数据!` });
            return openInNewTab("Android2")
        }
        if (!ret.IOS1) {

            chrome.runtime.sendMessage({ action: "showNotification", title: "Notification", message: `缺少IOS1数据!` });
            return openInNewTab("IOS1")
        }
        if (!ret.IOS2) {

            chrome.runtime.sendMessage({ action: "showNotification", title: "Notification", message: `缺少IOS2数据!` });
            return openInNewTab("IOS2")

        }
        console.log('all', ret)
        let promiseArr = []
        arr.map((item) => {
            promiseArr.push(getStorageItem([item]))

        })
        let mergedData = []
        try {
            let mergedDataArr = await Promise.all(promiseArr)
            if (mergedDataArr) {
                mergedData = mergeObjectsWithSameEventID(mergedDataArr);
                console.log(mergedData);
            }
        } catch (error) {
            console.error('发生错误:', error);
        }
        try {
            let titleData = await getStorageItem('titleData')
            if (titleData) {
                console.log(mergedData, titleData)

                let option = {};
                let date = getcurrentDate()
                option.fileName = `全部应用Event-${date}`
                option.datas = [
                    {
                        sheetData: mergedData,
                        sheetHeader: titleData,
                        sheetFilter: ['EventID', 'EventName', 'NumberofMessagesYesterday', 'NumberofMessagesToday', 'NumberofIndependentUsersYesterday']
                    }
                ]
                //引用ExportJsonExcel方法导出Excel文件
                let toExcel = new ExportJsonExcel(option);
                toExcel.saveExcel();
            }
        } catch (error) {
            console.error('发生错误:', error);
        }

    }

    function getStorageItem(key) {
        return new Promise((resolve, reject) => {
            chrome.storage.sync.get(key, (result) => {
                if (chrome.runtime.lastError) {
                    reject(new Error(chrome.runtime.lastError.message));
                } else {
                    if (key == null) {
                        resolve(result);
                    }
                    resolve(result[key]);
                }
            });
        });
    }

    function setStorageItem(data) {
        return new Promise((resolve, reject) => {
            chrome.storage.sync.set(data, () => {
                if (chrome.runtime.lastError) {
                    reject(new Error(chrome.runtime.lastError.message));
                } else {
                    resolve(true);
                }
            });
        });
    }

    function removeStorageItem(key) {
        return new Promise((resolve, reject) => {
            chrome.storage.sync.remove(key, (result) => {
                if (chrome.runtime.lastError) {
                    reject(new Error(chrome.runtime.lastError.message));
                } else {
                    resolve(true);
                }
            });
        });
    }

    function clearStorage() {
        return new Promise((resolve, reject) => {
            chrome.storage.sync.clear((result) => {
                if (chrome.runtime.lastError) {
                    reject(new Error(chrome.runtime.lastError.message));
                } else {
                    resolve(true);
                }
            });
        });
    }
特定页面注入dom,并绑定函数执行相关操作
 //向页面注入一个div并添加a标签
    $('body').append('<div class="mydiv"></div>');
    let obj = {
        "allApp": "platform/apps/list",
        "Android1": '6461d579', "Android2": '6461d6b', "IOS1": '6461d65', "IOS2": '6461d6cf'
    }
    let currentUrl = window.location.href
    if (currentUrl.includes('umeng')) {

        //向页面注入一个div并添加a标签
        $('.mydiv').append('<a id="clearAllApp" class="mya" href="javascript:;">清除缓存</a>'
        );
        //向页面注入一个div并添加a标签
        $('.mydiv').append('<a id="allApp" class="mya" href="javascript:;">导出应用列表</a>'
        );
        //向页面注入一个div并添加a标签
        $('.mydiv').append('<a id="Android1" class="mya" href="javascript:;">导出安卓1埋点</a>'
        );
        //向页面注入一个div并添加a标签
        $('.mydiv').append('<a id="Android2" class="mya" href="javascript:;">导出安卓2埋点</a>');
        //向页面注入一个div并添加a标签
        $('.mydiv').append('<a id="IOS1" class="mya" href="javascript:;">导出IOS1埋点</a>'
        );
        //向页面注入一个div并添加a标签
        $('.mydiv').append('<a id="IOS2" class="mya" href="javascript:;">导出IOS2埋点</a>');
        //向页面注入一个div并添加a标签
        $('.mydiv').append('<a id="allAppEvent" class="mya" href="javascript:;">导出所有应用埋点</a>');
        $('#clearAllApp').on('click', function () {
            clearStorage()
        })
        //向注入的a标签绑定点击事件
        $('#Android1').on('click', function () {
            getDataApp('Android1', '安卓1埋点')
        })
        $('#Android2').on('click', function () {
            getDataApp('Android2', '安卓2埋点')
        })
        //向注入的a标签绑定点击事件
        $('#IOS1').on('click', function () {
            getDataApp('IOS1', 'IOS1埋点')
        })
        $('#IOS2').on('click', function () {
            getDataApp('IOS2', 'IOS2埋点')
        })
        $('#allAppEvent').on('click', function () {
            getAllAppEvent()
        })

        //向注入的a标签绑定点击事件
        $('#allApp').on('click', function () {

            //判断jq是否查找到元素
            if ($('.ant-table-tbody').find('.ant-table-row').length > 0) {

                //创建数组
                let data = [];
                let titleData = []

                $('.ant-table-thead').find('.ant-table-header-column').each(function (index) {
                    let a = $(this).find('.ant-table-column-title').text().match(/\S+/g)
                    console.log(a, typeof a)
                    if (a && a[0] != '平台') {
                        titleData.push(a[0])
                    }

                })
                console.log(titleData, 'titleData')
                $('.ant-table-tbody').find('.ant-table-row').each(function (index) {
                    let a = $(this).find('.ant-table-column-has-actions.ant-table-column-has-sorters.ant-table-row-cell-break-word')
                    let arr = []
                    a.each(function (index, value) {
                        let b = value.
                            innerText
                            .match(/\S+/g)[0]
                        // console.log(b, index, 'b')
                        arr.push(b)
                    })
                    console.log(arr, 'arr')
                    data[index] = {
                        ApplicationName: arr[0],
                        NewUserToday: arr[1],
                        NewUserYesterday: arr[2],
                        ActiveUserToday: arr[3],
                        ActiveUserYesterday: arr[4],
                        NumberofStartsToday: arr[5],
                        NumberofStartsYesterday: arr[6],
                        AccumulatedUsersToday: arr[7]
                    }
                })
                console.log(titleData, 'titleData', data)

                //配置option,用于ExportJsonExcel
                let option = {};
                let date = getcurrentDate()
                option.fileName = `应用列表用户分析-${date}`
                option.datas = [
                    {
                        sheetData: data,
                        sheetHeader: titleData,
                        sheetFilter: ['ApplicationName', 'NewUserToday', 'NewUserYesterday', 'ActiveUserToday', 'ActiveUserYesterday', 'NumberofStartsToday', 'NumberofStartsYesterday', 'AccumulatedUsersToday']
                    }
                ]

                //引用ExportJsonExcel方法导出Excel文件
                let toExcel = new ExportJsonExcel(option);
                toExcel.saveExcel();

            } else {
                chrome.runtime.sendMessage({ action: "showNotification", title: "Notification", message: "没有匹配到应用列表用户分析!" });

                // alert('没有匹配到应用列表用户分析!');
            }
        })
        Object.entries(obj).map(item => {
            if (currentUrl.includes(`${item[1]}/function/events/dashboard`)) {
                $(`#${item[0]}`).show()
            } else {
                $(`#${item[0]}`).hide()
            }

            console.log(item[0], item[1])
        })
    }
获取全部应用数据,通过缓存判断,四个应用缺失哪个,浏览器通知提示,跳转到哪个应用的埋点数据页面,去获取相关数据
 // 在新标签页中打开网址
    function openInNewTab(id) {
        let url = ''
        let obj = {
            "Android1": '6461d57', "Android2": '6461d6', "IOS1": '6461d65', "IOS2": '6461'
        }
        url = `https://mobile.umeng.com/platform/${obj[id]}/function/events/dashboard`
        console.log(id, obj[id], url)
        // window.open(url);
        redirect(url)
    }
    async function getAllAppEvent() {
        // let ret = await clearStorage()
        // console.log(ret,'dsfdfds')

        let arr = ["Android1", "Android2", "IOS1", "IOS2"]
        let ret = await getStorageItem(null)
        if (!ret.Android1) {
            chrome.runtime.sendMessage({ action: "showNotification", title: "Notification", message: `缺少安卓1数据!` });
            return openInNewTab("Android1")
        }
        if (!ret.Android2) {

            chrome.runtime.sendMessage({ action: "showNotification", title: "Notification", message: `缺少安卓2数据!` });
            return openInNewTab("Android2")
        }
        if (!ret.IOS1) {

            chrome.runtime.sendMessage({ action: "showNotification", title: "Notification", message: `缺少IOS1数据!` });
            return openInNewTab("IOS1")
        }
        if (!ret.IOS2) {

            chrome.runtime.sendMessage({ action: "showNotification", title: "Notification", message: `缺少IOS2数据!` });
            return openInNewTab("IOS2")

        }
        console.log('all', ret)
        let promiseArr = []
        arr.map((item) => {
            promiseArr.push(getStorageItem([item]))

        })
        let mergedData = []
        try {
            let mergedDataArr = await Promise.all(promiseArr)
            if (mergedDataArr) {
                mergedData = mergeObjectsWithSameEventID(mergedDataArr);
                console.log(mergedData);
            }
        } catch (error) {
            console.error('发生错误:', error);
        }
        try {
            let titleData = await getStorageItem('titleData')
            if (titleData) {
                console.log(mergedData, titleData)

                let option = {};
                let date = getcurrentDate()
                option.fileName = `全部应用Event-${date}`
                option.datas = [
                    {
                        sheetData: mergedData,
                        sheetHeader: titleData,
                        sheetFilter: ['EventID', 'EventName', 'NumberofMessagesYesterday', 'NumberofMessagesToday', 'NumberofIndependentUsersYesterday']
                    }
                ]
                //引用ExportJsonExcel方法导出Excel文件
                let toExcel = new ExportJsonExcel(option);
                toExcel.saveExcel();
            }
        } catch (error) {
            console.error('发生错误:', error);
        }

    }

效果图如下

获取当前应用的数据并导出缓存,以及聚合所有应用数据导出文件
 // 创建一个函数来合并具有相同 EventID 的对象的数值属性
    function mergeObjectsWithSameEventID(arrays) {
        // 创建一个结果对象,用于存储合并后的数据
        let result = {};

        // 遍历每个数组
        arrays.forEach(array => {
            array.forEach(obj => {
                // 如果结果对象中还没有这个 EventID,创建一个新的对象
                if (!result[obj.EventID]) {
                    result[obj.EventID] = {
                        EventID: obj.EventID,
                        EventName: obj.EventName,
                        NumberofMessagesToday: obj.NumberofMessagesToday,
                        NumberofIndependentUsersYesterday: 0,
                        NumberofMessagesYesterday: 0
                    };
                }
                // 将数值相加
                result[obj.EventID].NumberofIndependentUsersYesterday += parseInt(obj.NumberofIndependentUsersYesterday, 10);
                result[obj.EventID].NumberofMessagesYesterday += parseInt(obj.NumberofMessagesYesterday, 10);
            });
        });

        // 将结果对象转换回数组
        let mergedArray = Object.values(result);

        // 返回合并后的数组
        return mergedArray;
    }

    function getcurrentDate() {
        // 创建一个新的Date对象,表示当前日期和时间
        let currentDate = new Date();

        // 获取年、月、日信息
        let year = currentDate.getFullYear(); // 获取当前年份
        let month = currentDate.getMonth() + 1; // 获取当前月份(注意:月份从0开始,需要加1)
        let day = currentDate.getDate(); // 获取当前是几号

        // 将年、月、日拼接成日期字符串
        let formattedDate = year + '-' + (month < 10 ? '0' + month : month) + '-' + (day < 10 ? '0' + day : day);

        console.log(formattedDate); // 输出当前日期,格式为YYYY-MM-DD
        return formattedDate

    }
    async function getDataApp(id, name) {
        setTimeout(async () => {
            //判断jq是否查找到元素
            if ($('.ant-table-tbody').find('.ant-table-row').length > 0) {
                //创建数组
                let titleData = []
                //创建数组
                let data = [];
                $('.ant-table-thead').find('.ant-table-header-column').each(function (index) {
                    let a = $(this).find('.ant-table-column-title').text().match(/\S+/g)
                    console.log(a, typeof a, 'Android1')

                    if (a && a[0] != '详情') {
                        titleData.push(a[0])
                    }
                })
                console.log(titleData, 'titleData')
                $('.ant-table-tbody').find('.ant-table-row').each(function (index) {
                    let a = $(this).find('.ant-table-column-has-actions.ant-table-column-has-sorters.ant-table-row-cell-break-word')
                    let arr = []
                    a.each(function (index, value) {
                        let b = value.
                            innerText
                            .match(/\S+/g)[0]
                        // console.log(b, index, 'b')
                        arr.push(b)
                    })
                    console.log(arr, 'arr')

                    data[index] = {
                        EventID: arr[0],
                        EventName: arr[1],
                        NumberofMessagesYesterday: arr[2],
                        NumberofMessagesToday: arr[3],
                        NumberofIndependentUsersYesterday: arr[4],
                    }
                })
                console.log(titleData, 'titleData', data)
                //配置option,用于ExportJsonExcel
                let option = {};
                let date = getcurrentDate()
                option.fileName = `${name}-${date}`
                option.datas = [
                    {
                        sheetData: data,
                        sheetHeader: titleData,
                        sheetFilter: ['EventID', 'EventName', 'NumberofMessagesYesterday', 'NumberofMessagesToday', 'NumberofIndependentUsersYesterday']
                    }
                ]

                try {
                    let ret = await setStorageItem({ [id]: data });
                    console.log(`${id}数据已存储`, ret);
                } catch (error) {
                    console.error(`${id}数据error`, error);
                }

                try {
                    await setStorageItem({ titleData: titleData });
                    console.log(`titleData数据已存储`);
                } catch (error) {
                    console.error(`titleData数据error`, error);
                }

                //引用ExportJsonExcel方法导出Excel文件
                let toExcel = new ExportJsonExcel(option);
                toExcel.saveExcel();
            }
            else {
                chrome.runtime.sendMessage({ action: "showNotification", title: "Notification", message: `没有匹配到${name}!` });
            }
        }, 1000)
    }

效果图如下

导出的结果文件如下

四、相关icon和插件目录说明

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值