NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name 中控做表助手 - 抖音直播大屏数据导出 // @namespace doupoa.site // @version 1.0.2 // @description 抖音专业版直播大屏数据导出。脚本启用后会在左侧logo旁出现"导出数据"字样。建议下播后再进行导出操作。开启的大屏必须从巨量百应中进入,巨量百应与抖音罗盘的数据大屏接口不同。导出的数据为:头部核心数据,流量统计及短视频引流。导出的数据仅供数据分析,不得用于非法行为。所有数据均在您浏览器中处理,不会上传至任何第三方平台,请自行解决数据保密问题,发生任何意外与本脚本及作者无关。 // @author doupoa // @copyright 2023,doupoa.site // @license MIT // @updateURL https://openuserjs.org/meta/doupoa/douyin_live_screen_data_export.meta.js // @downloadURL https://openuserjs.org/install/doupoa/中控做表助手.user.js // @match *://compass.jinritemai.com/screen/live/* // @icon https://p1-ecda.byteimg.com/tos-cn-i-n15nrygpm8/563a38e870c441b8af75c0c8c38b1a39~tplv-n15nrygpm8-image.image // @grant none // @run-at document-end // ==/UserScript== // TODO : 关于大屏核心数据项获取并实现自动分配请求 (function () { "use strict"; var roomID = ""; var getFlowDistributionUrl = "https://compass.jinritemai.com/compass_api/content_live/author/live_screen/flow_distribution"; // 获取自然、付费流量数据接口 var getFlowVideoUrl = "https://compass.jinritemai.com/compass_api/author/live/live_screen/flow_video"; // 获取引流视频数据接口 var getCoreDataUrl = "https://compass.jinritemai.com/compass_api/author/live/live_screen/core_data"; //获取大屏核心数据接口 var csvData = ""; function getUrlParams() { const url = window.location.href; let urlStr = url.split("?")[1]; const urlSearchParams = new URLSearchParams(urlStr); const result = Object.fromEntries(urlSearchParams.entries()); return result; } function parseFlowDistributionData(data) { data = JSON.parse(data); return new Promise((resolve) => { let temp = ",\r\n渠道名称,流量占比,成交金额,成交金额占比,渠道千次观看成交,,注:自然流量\r\n"; let nd = data.data.natural_data; let pd = data.data.pay_data; if (nd.length > 0) { for (let i = 0; i < nd.length; i++) { //遍历自然流量数据 temp += nd[i].channel_name + ","; // 渠道名称 temp += nd[i].watch_ratio.value * 100 + "%,"; //流量占比 temp += "¥" + nd[i].pay_amt.value / 100 + ","; // 成交金额 temp += nd[i].pay_ratio.value * 100 + "%,"; //成交金额占比 temp += "¥" + nd[i].gpm.value / 100 + "\r\n"; //渠道千次观看成交 if (nd[i].hasOwnProperty("sub_flow")) { //判断是否存在子数据 for (let k = 0; k < nd[i].sub_flow.length; k++) { temp += " - " + nd[i].sub_flow[k].channel_name + ","; // 渠道名称 temp += nd[i].sub_flow[k].watch_ratio.value * 100 + "%,"; //流量占比 temp += "¥" + nd[i].sub_flow[k].pay_amt.value / 100 + ","; // 成交金额 temp += nd[i].sub_flow[k].pay_ratio.value * 100 + "%,"; //成交金额占比 temp += "¥" + nd[i].sub_flow[k].gpm.value / 100 + "\r\n"; //渠道千次观看成交 } } } } else { temp += "暂无数据\r\n"; } temp += ",\r\n渠道名称,流量占比,成交金额,成交金额占比,渠道千次观看成交,,注:付费流量\r\n"; if (pd.length > 0) { for (let i = 0; i < pd.length; i++) { //遍历自然流量数据 temp += pd[i].channel_name + ","; // 渠道名称 temp += pd[i].watch_ratio.value * 100 + "%,"; //流量占比 temp += "¥" + pd[i].pay_amt.value / 100 + ","; // 成交金额 temp += pd[i].pay_ratio.value * 100 + "%,"; //成交金额占比 temp += "¥" + pd[i].gpm.value / 100 + "\r\n"; //渠道千次观看成交 if (pd[i].hasOwnProperty("sub_flow")) { //判断是否存在子数据 for (let k = 0; k < pd[i].sub_flow.length; k++) { temp += " - " + pd[i].sub_flow[k].channel_name + ","; // 渠道名称 temp += pd[i].sub_flow[k].watch_ratio.value * 100 + "%,"; //流量占比 temp += "¥" + pd[i].sub_flow[k].pay_amt.value / 100 + ","; // 成交金额 temp += pd[i].sub_flow[k].pay_ratio.value * 100 + "%,"; //成交金额占比 temp += "¥" + pd[i].sub_flow[k].gpm.value / 100 + "\r\n"; //渠道千次观看成交 } } } } else { temp += "暂无数据\r\n"; } csvData += temp; resolve(); }); } function parseFlowVideo(data) { data = JSON.parse(data); return new Promise((resolve) => { let temp = ",\r\n视频标题,发布时间,直播间入口曝光次数,引流直播间次数,直播间入口点击率(次数),,注:数据按引流直播间次数排序\r\n"; let dr = data.data.data_result; if (dr.length > 0) { for (let i = 0; i < dr.length; i++) { temp += dr[i].title + ","; //标题 temp += dr[i].publish_time + ","; //时间 if (dr[i].show_in_live_cnt.includes("万")) { temp += (dr[i].show_in_live_cnt.replace("万", "") - 0) * 10000 + ","; } else { temp += dr[i].show_in_live_cnt.replace(",", "") + ","; //直播入口曝光次数 } temp += dr[i].drainage_in_live_cnt.replace(",", "") + ","; //引流直播间次数 temp += dr[i].show_to_drainage_rate + ",\r\n"; //直播间入口点击率(次数) } } else { temp += "暂无数据\r\n"; } csvData += temp; resolve(); }); } function parseCoreData(data, count) { data = JSON.parse(data); return new Promise((resolve, reject) => { let temp = "\r\n大屏核心数据 - 第" + count + "批\r\n"; let cd = data.data.core_data; if (cd.length > 0) { for (let i = 0; i < cd.length; i++) { if (cd[i].index_display != "") { temp += cd[i].index_display + ", -> ,"; // 数据名称 } else { temp += cd[i].index_name + ", -> ,"; // 数据名称 } switch (cd[i].value.unit) { case "price": //金额 temp += "¥" + cd[i].value.value + "\r\n"; break; case "ratio": //百分数 temp += cd[i].value.value * 100 + "%\r\n"; break; default: temp += cd[i].value.value + "".replace(",", "") + "\r\n"; } } } else { temp += "暂无第" + count + "批大屏数据"; } csvData += temp; resolve(); }); } function doGet(url) { return new Promise((resolve, reject) => { let req = new XMLHttpRequest(); req.open("Get", url); req.send(); req.onload = function () { if (req.status == 200) { resolve(req.response); } else { reject(Error("Network Error")); } }; req.onerror = function () { reject(Error("Network Error")); }; }); } async function getData() { await parseFlowDistributionData( await doGet(getFlowDistributionUrl + "?room_id=" + roomID) ); await parseFlowVideo( await doGet( getFlowVideoUrl + "?room_id=" + roomID + "&page_no=1&page_size=10&sort_field=show_in_live_cnt" ) ); await parseCoreData( await doGet( getCoreDataUrl + "?room_id=" + roomID + "&index_selected=current_cnt,watch_cnt_show_ratio,watch_ucnt,live_show_cnt,avg_watch_duration,avg_min_comment_cnt,interact_watch_ucnt_ratio,follow_anchor_ucnt,follow_anchor_watch_ucnt_ratio,fans_club_join_ucnt" ), 1 ); await parseCoreData( await doGet( getCoreDataUrl + "?room_id=" + roomID + "&index_selected=fans_club_join_watch_ucnt_ratio,ecom_live_ecf_joinclub_ucnt_td,ecf_club_join_watch_ucnt_ratio,pay_ucnt,gpm,watch_pay_ucnt_ratio,product_click_pay_ucnt_ratio,real_refund_amt,real_refund_amt_ratio" ), 2 ); await parseCoreData( await doGet( getCoreDataUrl + "?room_id=" + roomID + "&index_selected=pay_deposit_pre_order_amt,pay_combo_cnt,old_fans_pay_ucnt_ratio,livetoind_pay_amt,stat_cost,punish_cnt" ), 3 ); var newDate = new Date(); export_csv( csvData, document.getElementsByClassName("accountName--jyOI0")[0].innerText + newDate.toLocaleDateString() ); } function export_csv(data, name) { //导出表格 // “\ufeff” BOM头 var uri = "data:text/csv;charset=utf-8," + encodeURIComponent(data); var downloadLink = document.createElement("a"); downloadLink.href = uri; downloadLink.download = name + ".csv" || "大屏数据导出.csv"; document.body.appendChild(downloadLink); downloadLink.click(); document.body.removeChild(downloadLink); } async function main() { // 尝试自动获取房间号 let urlParams = getUrlParams(); if ("live_room_id" in urlParams) { roomID = urlParams.live_room_id; } if (roomID == "") { // 自动获取失败尝试让用户手动输入房间号 roomID = prompt("获取房间号失败,请手动输入房间号:"); } if (roomID == "") { // 还是空直接终止脚本运行 alert("关键数据获取失败,脚本终止运行"); return; } getData(); } var button = document.createElement("button"); button.className = "ecom-btn ecom-btn-primary ecom-btn-sm reviewButton--DqvEZ"; button.type = "button"; button.textContent = "导出数据"; button.addEventListener("click", main); window.setTimeout(() => { var header = document.getElementsByClassName("center--HdRS4")[0]; header.appendChild(button); }, 3000); })();