// ==UserScript==
// @name 小红书广告数据查询与展示
// @namespace http://tampermonkey.net/
// @version 1.12
// @description 在当前页面插入悬浮元素,点击展开窗口并发送请求,将结果展示在表格中并提供Excel下载按钮
// @author You
// @match https://ad.xiaohongshu.com/aurora*
// @grant GM_xmlhttpRequest
// @connect ad.xiaohongshu.com
// @license MIT
// ==/UserScript==
(function () {
"use strict";
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
//提示==========
// 注入样式
const style = document.createElement("style");
style.textContent = `
.custom-toast {
position: fixed;
left: 50%;
transform: translateX(-50%);
padding: 12px 24px;
border-radius: 4px;
background: #333;
color: white;
box-shadow: 0 2px 8px rgba(0,0,0,0.2);
opacity: 0;
transition: all 0.3s ease;
z-index: 9999;
top: 20px;
margin-top: 0;
}
.custom-toast.show {
opacity: 1;
margin-top: 0 !important;
}
.custom-toast.success { background: #67c23a; }
.custom-toast.warning { background: #e6a23c; }
.custom-toast.error { background: #f56c6c; }
.custom-toast.info { background: #909399; }
`;
document.head.appendChild(style);
// 提示队列管理
const toastStack = {
list: [],
add(toast) {
this.list.push(toast);
this.updatePositions();
},
remove(toast) {
this.list = this.list.filter((t) => t !== toast);
this.updatePositions();
},
updatePositions() {
this.list.forEach((toast, index) => {
const baseTop = 20;
const spacing = 60;
const targetTop = baseTop + index * spacing;
toast.style.top = `${targetTop}px`;
});
},
};
// 提示函数
window.showToast = function (message, type = "info", duration = 3000) {
const toast = document.createElement("div");
toast.className = `custom-toast ${type}`;
toast.textContent = message;
document.body.appendChild(toast);
void toast.offsetHeight; // 触发重绘
toastStack.add(toast);
toast.classList.add("show");
setTimeout(() => {
toast.classList.remove("show");
setTimeout(() => {
toast.remove();
toastStack.remove(toast);
}, 300);
}, duration);
};
// // 使用示例
// showToast('第一个提示', 'success');
// setTimeout(() => showToast('第二个提示在下方', 'error'), 500);
// setTimeout(() => showToast('第三个提示继续下移', 'info'), 1000);
//提示----------
//圆球=====================
const sheet = new CSSStyleSheet();
sheet.replaceSync(`
/* 加载转圈圈 */
.loading {
width: 30px;
height: 30px;
border: 2px solid #000;
border-top-color: transparent;
border-radius: 100%;
animation: circle infinite 0.75s linear;
}
/* 加载转圈圈动画 */
@keyframes circle {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
/* 下面是卡片的样式 */
#overlay {
position: fixed;
top: 50%;
left: 50%;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 999;
transform: translate(-50%, -50%);
}
#card {
position: fixed;
top: 50%;
left: 50%;
width: 500px; /* 设置卡片的宽度 */
height: 300px; /* 设置卡片的高度 */
background-color: white;
border: 1px solid #0057ff ;
padding: 20px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
z-index: 2147483647;
transform: translate(-50%, -50%);
border-radius: 8px
}
/* 下面是卡片中输入框还有下拉框的样式 */
#card select {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
box-sizing: border-box;
border: 2px solid #ccc;
border-radius: 4px;
background-color: #f8f8f8;
font-size: 16px;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background-image: url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%23007CB2%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E');
background-repeat: no-repeat;
background-position: right 10px top 50%;
background-size: 12px 12px;
}
#card label {
display: block;
margin-bottom: 8px;
font-size: 16px;
color: #333;
font-weight: bold;
}
#card input[type="text"],#card textarea {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
box-sizing: border-box;
border: 2px solid #ccc;
border-radius: 4px;
background-color: #f8f8f8;
font-size: 16px;
}
#card button,.card button {
margin-bottom: 10px;
margin-top: 10px;
margin-left: 10px;
margin-right: 10px;
padding: 8px 16px;
background-color: rgb(0, 102, 204);
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
`);
function addStyleSheet(sheet) {
const allSheets = [...document.adoptedStyleSheets, sheet];
document.adoptedStyleSheets = allSheets;
}
addStyleSheet(sheet);
// 存储请求返回的数据
let responseData = [];
function addBallAttributes(ball, text) {
ball.style.cssText = `
position: fixed;
right: 10px;
bottom: 10px;
width: 60px;
height: 60px;
background-color: #0066CC;
border-radius: 50%;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
color: white;
z-index: 9999;
`;
ball.textContent = text;
}
// 创建隐藏的小球元素
const ball = document.createElement("div");
addBallAttributes(ball, "检查链接");
document.body.appendChild(ball);
// 创建悬浮窗口元素
const floatingWindow = document.createElement("div");
floatingWindow.style.cssText = `
position: fixed;
right: 20px;
top: 20px;
width: 50vw;
height: 80vh;
background-color: white;
border: 1px solid #0066CC;
border-radius: 8px;
display: none;
padding: 20px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
z-index: 9999;
`; // 改成 cssom
document.body.appendChild(floatingWindow);
// 创建关闭按钮
const closeButton = document.createElement("div");
closeButton.style.cssText = `
position: absolute;
right: 10px;
top: 10px;
cursor: pointer;
font-size: 20px;
color: #0066CC;
`; // 改成 cssom
closeButton.innerHTML = "×";
floatingWindow.appendChild(closeButton);
// 创建按钮容器
const buttonContainer = document.createElement("div");
buttonContainer.style.cssText = `
margin-bottom: 20px;
`; // 改成 cssom
floatingWindow.appendChild(buttonContainer);
function addButtonAttributes(checkButton, text) {
checkButton.textContent = text; //"检查";
checkButton.style.cssText = `
margin-right: 10px;
padding: 8px 16px;
background-color: #0066CC;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
`; // 改成 cssom
}
// 创建检查按钮
const checkButton = document.createElement("button");
addButtonAttributes(checkButton, "检查");
buttonContainer.appendChild(checkButton);
// 创建下载按钮
const downloadButton = document.createElement("button");
addButtonAttributes(downloadButton, "下载");
buttonContainer.appendChild(downloadButton);
// 创建链接统计文本容器
const linkStatsContainer = document.createElement("div");
linkStatsContainer.style.cssText = `
margin-bottom: 20px;
font-size: 14px;
color: #333333;
`; // 改成 cssom
floatingWindow.appendChild(linkStatsContainer);
// 创建表格容器
const tableContainer = document.createElement("div");
tableContainer.style.cssText = `
height: calc(100% - 100px);
overflow-y: auto;
overflow-x: auto;
`; // 改成 cssom
floatingWindow.appendChild(tableContainer);
// 创建进度条
const progressBar = document.createElement("progress");
progressBar.style.cssText = `
width: 100%;
margin-top: 10px;
display: none;
`; // 改成 cssom
progressBar.value = 0;
progressBar.max = 100;
floatingWindow.appendChild(progressBar);
// 显示小球
ball.style.display = "flex";
// 点击小球展开悬浮窗口
ball.addEventListener("click", function () {
floatingWindow.style.display = "block";
ball.style.display = "none";
});
// 点击关闭按钮
closeButton.addEventListener("click", function () {
floatingWindow.style.display = "none";
ball.style.display = "flex";
tableContainer.innerHTML = "";
linkStatsContainer.innerHTML = "";
responseData = []; // 清空存储的数据
});
// 点击检查按钮发送请求
checkButton.addEventListener("click", function () {
checkButton.disabled = true;
checkButton.style.backgroundColor = "rgb(105, 102, 102)";
const loading = document.createElement("div");
loading.className = "loading";
loading.id = "loading-indicator"; // 添加一个唯一ID
tableContainer.appendChild(loading);
sendRequest().then(() => {
checkButton.disabled = false;
checkButton.style.backgroundColor = "rgb(0, 102, 204)";
// 使用更安全的方式移除loading
const loadingElement = document.getElementById("loading-indicator");
if (loadingElement) {
loadingElement.remove();
}
});
});
// 点击下载按钮
downloadButton.addEventListener("click", function () {
if (responseData.length > 0) {
downloadExcel(responseData);
} else {
alert("没有可下载的数据!");
}
});
// 发送请求
async function sendRequest() {
let maxPageNum = 4;
let pageNum = 1;
let totalPage = 1;
let allData = [];
do {
const response = await fetch(
`https://ad.xiaohongshu.com/api/leona/rtb/creativity/list?pageNum=${pageNum}&pageSize=50`,
{
method: "POST",
headers: {
accept: "application/json, text/plain, */*",
"accept-language":
"zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
"content-type": "application/json;charset=UTF-8",
priority: "u=1, i",
"sec-ch-ua":
'"Not A(Brand";v="8", "Chromium";v="132", "Microsoft Edge";v="132"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"Windows"',
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
},
body: JSON.stringify({
startTime: new Date().toISOString().split("T")[0],
endTime: new Date().toISOString().split("T")[0],
pageNum: pageNum,
pageSize: 50,
}),
}
);
const data = await response.json();
// console.log(data.data.list);
allData = allData.concat(data.data.list);
totalPage = data.data.totalPage;
pageNum++;
} while (pageNum <= totalPage || pageNum <= maxPageNum);
try {
// 保存响应数据
responseData = allData;
// 统计链接重复次数
const clickUrlCounts = {};
const expoUrlCounts = {};
allData.forEach((item) => {
if (item.clickUrls && item.clickUrls[0]) {
const clickUrl = extractUrlParam(item.clickUrls[0]);
clickUrlCounts[clickUrl] = (clickUrlCounts[clickUrl] || 0) + 1;
}
if (item.expoUrls && item.expoUrls[0]) {
const expoUrl = extractUrlParam(item.expoUrls[0]);
expoUrlCounts[expoUrl] = (expoUrlCounts[expoUrl] || 0) + 1;
}
});
// 读取option 本地持久化的存储
const storedOption = localStorage.getItem("data");
const option = JSON.parse(storedOption);
option.forEach((item) => {
const link = item.link;
const relink = link.match(/e=[^&]+/);
if (relink) {
item.relink = relink[0];
} else {
item.relink = link;
}
});
console.log(option);
if (storedOption) {
Object.entries(clickUrlCounts).forEach(([url, count]) => {
if (url) {
const div = document.createElement("div");
div.style.cssText = `
margin-bottom: 5px;
`; // 改成 cssom
div.textContent = `点击链接:${url} 有${count}条`;
const relink = url.match(/e=.*?(&|$)/)[0];
if (option.some((item) => item.relink === relink)) {
div.textContent += ` 配置符合:${
option.find((item) => item.relink === relink).name
}`;
} else {
div.textContent += " 无配置符合";
}
linkStatsContainer.appendChild(div);
}
});
Object.entries(expoUrlCounts).forEach(([url, count]) => {
if (url) {
const div = document.createElement("div");
div.style.cssText = `
margin-bottom: 5px;
`; // 改成 cssom
div.textContent = `曝光链接:${url} 有${count}条`;
const relink = url.match(/e=.*?(&|$)/)[0];
if (option.some((item) => item.relink === relink)) {
div.textContent += ` 配置符合:${
option.find((item) => item.relink === relink).name
}`;
} else {
div.textContent += " 无配置符合";
}
linkStatsContainer.appendChild(div);
}
});
} else {
Object.entries(clickUrlCounts).forEach(([url, count]) => {
if (url) {
const div = document.createElement("div");
div.style.cssText = `
margin-bottom: 5px;
`; // 改成 cssom
div.textContent = `点击链接:${url} 有${count}条`;
div.textContent += " 无配置符合";
linkStatsContainer.appendChild(div);
}
});
Object.entries(expoUrlCounts).forEach(([url, count]) => {
if (url) {
const div = document.createElement("div");
div.style.cssText = `
margin-bottom: 5px;
`; // 改成 cssom
div.textContent = `曝光链接:${url} 有${count}条`;
div.textContent += " 无配置符合";
linkStatsContainer.appendChild(div);
}
});
}
createTable(allData);
showToast("读取成功", "success");
} catch (error) {
console.error("解析响应数据时出错:", error);
showToast("读取报错,可能是没有配置", "error");
}
}
// 提取URL参数
function extractUrlParam(url) {
const match = url.match(/https:\/\/magellan.alimama.com\/(.*?)&/);
return match ? match[1] : "";
}
// 创建表格
function createTable(data) {
const table = document.createElement("table");
table.style.cssText = `
width: 100%;
border-collapse: collapse;
background-color: white;
`; // 改成 cssom
// 创建表头
const thead = document.createElement("thead");
thead.style.cssText = `
background-color: #0066CC;
`; // 改成 cssom
const headerRow = document.createElement("tr");
const headers = ["创建时间", "创意名", "创意ID", "点击链接", "曝光链接"];
headers.forEach((headerText) => {
const th = document.createElement("th");
th.style.cssText = `
border: 1px solid #0066CC;
padding: 12px;
color: white;
font-weight: bold;
`; // 改成 cssom
th.textContent = headerText;
headerRow.appendChild(th);
});
thead.appendChild(headerRow);
table.appendChild(thead);
// 创建表体
const tbody = document.createElement("tbody");
data.forEach((item, index) => {
const row = document.createElement("tr");
row.style.cssText = `
background-color: ${index % 2 === 0 ? "#F5F8FA" : "white"};
`; // 改成 cssom
const createTime = item.creativityCreateTime;
const creativityName = item.creativityName;
const creativityId = item.creativityId;
const clickUrl = item.clickUrls
? JSON.stringify(item.clickUrls.map(extractUrlParam)).replace(
/,/g,
"\n"
)
: "";
const expoUrl = item.expoUrls
? JSON.stringify(item.expoUrls.map(extractUrlParam)).replace(/,/g, "\n")
: "";
const values = [
createTime,
creativityName,
creativityId,
clickUrl,
expoUrl,
];
values.forEach((value) => {
const td = document.createElement("td");
td.style.cssText = `
border: 1px solid #E5E5E5;
padding: 12px;
color: #333333;
`; // 改成 cssom
td.textContent = value;
row.appendChild(td);
});
tbody.appendChild(row);
});
table.appendChild(tbody);
// 清空表格容器并插入新表格
tableContainer.innerHTML = "";
tableContainer.appendChild(table);
}
// 下载Excel
function downloadExcel(data) {
// 添加BOM头,解决中文乱码问题
const BOM = "\uFEFF";
const headers = ["创建时间", "创意名", "创意ID", "点击链接", "曝光链接"];
const csvContent = [headers.join(",")];
data.forEach((item) => {
const createTime = item.creativityCreateTime || "";
const creativityName = item.creativityName || "";
const creativityId = item.creativityId || "";
const clickUrl =
item.clickUrls && item.clickUrls[0]
? JSON.stringify(item.clickUrls.map(extractUrlParam)).replace(
/,/g,
"\n"
)
: "";
const expoUrl =
item.expoUrls && item.expoUrls[0]
? JSON.stringify(item.expoUrls.map(extractUrlParam)).replace(
/,/g,
"\n"
)
: "";
// 处理CSV中的特殊字符
const escapeCsvValue = (value) => {
if (typeof value !== "string") return value;
if (
value.includes(",") ||
value.includes('"') ||
value.includes("\n")
) {
return `"${value.replace(/"/g, '""')}"`;
}
return value;
};
const values = [
createTime,
creativityName,
creativityId,
clickUrl,
expoUrl,
].map(escapeCsvValue);
csvContent.push(values.join(","));
});
const csv = BOM + csvContent.join("\n");
const blob = new Blob([csv], { type: "text/csv;charset=utf-8" });
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
const timestamp = new Date().toLocaleString().replace(/[/:]/g, "-");
link.setAttribute("href", url);
link.setAttribute("download", `data_${timestamp}.csv`);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);
}
function option() {
const div = document.createElement("div");
div.className = "card";
div.style.cssText = `
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 9999;
width: 500px;
height: 300px;
overflow-x: auto;
overflow-y: auto;
background: white;
border: 1px solid rgb(0, 102, 204);
border-radius: 8px;
`;
const table = document.createElement("table");
table.style.cssText = `
width: 100%;
border-collapse: collapse;
`;
const addButton = document.createElement("button");
addButton.textContent = "添加";
addButton.onclick = () => {
const newRow = document.createElement("tr");
const newTd1 = document.createElement("td");
const newLinkInput = document.createElement("input");
newLinkInput.type = "text";
newTd1.appendChild(newLinkInput);
newRow.appendChild(newTd1);
const newTd2 = document.createElement("td");
const newNameInput = document.createElement("input");
newNameInput.type = "text";
newTd2.appendChild(newNameInput);
newRow.appendChild(newTd2);
tbody.insertBefore(newRow, tbody.children[0]);
};
const saveButton = document.createElement("button");
saveButton.textContent = "保存(关闭)";
saveButton.onclick = () => {
const rows = tbody.rows;
const data = [];
for (let i = 0; i < rows.length; i++) {
const link = rows[i].cells[0].children[0].value;
const name = rows[i].cells[1].children[0].value;
data.push({ link, name });
}
localStorage.setItem("data", JSON.stringify(data));
div.style.display = "none";
};
const clearButton = document.createElement("button");
clearButton.textContent = "清空";
clearButton.onclick = () => {
tbody.innerHTML = ""; // 清空tbody中的所有内容
};
div.appendChild(addButton);
div.appendChild(saveButton);
div.appendChild(clearButton);
const thead = document.createElement("thead");
const tr = document.createElement("tr");
const th1 = document.createElement("th");
th1.textContent = "链接";
tr.appendChild(th1);
const th2 = document.createElement("th");
th2.textContent = "名字";
tr.appendChild(th2);
thead.appendChild(tr);
const tbody = document.createElement("tbody");
const storedData = localStorage.getItem("data");
if (storedData) {
const data = JSON.parse(storedData);
data.forEach((item) => {
const row = document.createElement("tr");
const td1 = document.createElement("td");
const linkInput = document.createElement("input");
linkInput.type = "text";
linkInput.value = item.link;
td1.appendChild(linkInput);
row.appendChild(td1);
const td2 = document.createElement("td");
const nameInput = document.createElement("input");
nameInput.type = "text";
nameInput.value = item.name;
td2.appendChild(nameInput);
row.appendChild(td2);
tbody.appendChild(row);
});
} else {
const row = document.createElement("tr");
const td1 = document.createElement("td");
const linkInput = document.createElement("input");
linkInput.type = "text";
td1.appendChild(linkInput);
row.appendChild(td1);
const td2 = document.createElement("td");
const nameInput = document.createElement("input");
nameInput.type = "text";
td2.appendChild(nameInput);
row.appendChild(td2);
tbody.appendChild(row);
}
table.appendChild(thead);
table.appendChild(tbody);
div.appendChild(table);
document.body.appendChild(div);
}
//tools==================
function create_car() {
// 创建遮罩层
const overlay = document.createElement("div");
overlay.id = "overlay";
// 创建卡片
const card = document.createElement("div");
card.id = "card";
// 创建关闭按钮
const closeButton = document.createElement("span");
closeButton.textContent = "x";
closeButton.style.position = "absolute";
closeButton.style.top = "10px";
closeButton.style.right = "10px";
closeButton.style.cursor = "pointer";
closeButton.addEventListener("click", function () {
document.body.removeChild(overlay);
document.body.removeChild(card);
});
card.appendChild(closeButton);
return {
overlay,
card,
closeButton,
};
}
//tools-------------------
//======================改名
// 创建打开卡片的按钮
const openButton = document.createElement("button");
addButtonAttributes(openButton, "修改单元内计划字符");
// 为打开按钮添加点击事件监听器
openButton.addEventListener("click", function () {
const { overlay, card, closeButton } = create_car();
// 创建第一个输入框及其标签
const oldCharLabel = document.createElement("label");
oldCharLabel.textContent = "旧字符";
const oldCharInput = document.createElement("input");
oldCharInput.type = "text";
// 创建第二个输入框及其标签
const newCharLabel = document.createElement("label");
newCharLabel.textContent = "新字符";
const newCharInput = document.createElement("input");
newCharInput.type = "text";
// 创建替换按钮
const replaceButton = document.createElement("button");
replaceButton.textContent = "替换";
replaceButton.addEventListener("click", async function () {
const oldChar = oldCharInput.value;
const newChar = newCharInput.value;
await mainSend(oldChar, newChar);
// 这里可以执行其他脚本,例如替换页面上的文本
console.log(`将 "${oldChar}" 替换为 "${newChar}"`);
});
// 将元素添加到卡片中
card.appendChild(closeButton);
card.appendChild(oldCharLabel);
card.appendChild(oldCharInput);
card.appendChild(newCharLabel);
card.appendChild(newCharInput);
card.appendChild(replaceButton);
// 将遮罩层和卡片添加到页面中
document.body.appendChild(overlay);
document.body.appendChild(card);
});
async function mainSend(old1, new1) {
const n = location.href.match(/[0-9]{1,20}/g);
const r = await fetch(
"https://ad.xiaohongshu.com/api/leona/rtb/creativity/list",
{
headers: {
accept: "application/json, text/plain, */*",
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
"content-type": "application/json;charset=UTF-8",
priority: "u=1, i",
"sec-ch-ua":
'"Not(A:Brand";v="99", "Microsoft Edge";v="133", "Chromium";v="133"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"macOS"',
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"x-b3-traceid": "37e8ffc9e25f798c",
},
referrer:
"https://ad.xiaohongshu.com/aurora/ad/manage/103584356/192658846/creativity",
referrerPolicy: "strict-origin-when-cross-origin",
body: `{\"campaignId\":${n[0]},\"unitId\":${n[1]},\"startTime\":\"${
new Date().toISOString().split("T")[0]
}\",\"endTime\":\"${
new Date().toISOString().split("T")[0]
}\",\"pageNum\":1,\"pageSize\":50}`,
method: "POST",
mode: "cors",
credentials: "include",
}
);
const j = await r.json();
const total = j.data.list.length;
let completed = 0;
const sheet = new CSSStyleSheet();
sheet.replaceSync(`
#progressBar {
width: 0;
height: 20px;
background-color: #54FF9F;
position: fixed;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
z-index: 2147483647;
}
`);
addStyleSheet(sheet);
// document.adoptedStyleSheets = [sheet];
const progressBar = document.createElement("div");
progressBar.id = "progressBar";
progressBar.innerText = "进度";
document.body.appendChild(progressBar);
for (let index = 0; index < j.data.list.length; index++) {
const element = j.data.list[index];
const oldName = element.creativityName;
const regex = new RegExp(old1, "g");
const newName = oldName.replace(regex, new1);
await reanmeSend(element.creativityId, newName);
completed++;
const progress = (completed / total) * 100;
progressBar.style.width = `${progress}%`;
}
document.body.removeChild(progressBar);
showToast("完成", "success");
// alert("完成");
}
async function reanmeSend(id, name) {
return fetch(
"https://ad.xiaohongshu.com/api/leona/rtb/creativity/batch/update/name",
{
headers: {
accept: "application/json, text/plain, */*",
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
"content-type": "application/json;charset=UTF-8",
priority: "u=1, i",
"sec-ch-ua":
'"Not(A:Brand";v="99", "Microsoft Edge";v="133", "Chromium";v="133"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"macOS"',
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"x-b3-traceid": "dee287ce9b6526cc",
},
//"referrer": "https://ad.xiaohongshu.com/aurora/ad/manage/103596579/192712174/creativity",
referrerPolicy: "strict-origin-when-cross-origin",
body: `{\"creativityId\":${id},\"creativityName\":\"${name}\"}`,
method: "POST",
mode: "cors",
credentials: "include",
}
);
}
//调价函数======================
function getCurrentTimestamp() {
return Math.floor(Date.now() / 1000);
}
async function getData(body, bid, result) {
body.removeBind = 0;
body.sourceFlag = "web";
body.pageEnterTime = getCurrentTimestamp() - 10;
body.pageSubmitTime = getCurrentTimestamp();
body.keywordWithBid.map((e) => {
e.bid = bid * 100;
});
const r = await fetch("https://ad.xiaohongshu.com/api/leona/rtb/unit", {
headers: {
accept: "application/json, text/plain, */*",
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
"content-type": "application/json",
priority: "u=1, i",
"sec-ch-ua":
'"Chromium";v="134", "Not:A-Brand";v="24", "Microsoft Edge";v="134"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"Windows"',
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"x-b3-traceid": "631398efd0ea1db1",
},
// "referrer": "https://ad.xiaohongshu.com/aurora/ad/edit/unit/107358958/208378008/4/2?byManage=true&manageLevel=byAccount&AFormGrayFlag=false",
referrerPolicy: "strict-origin-when-cross-origin",
body: JSON.stringify(body),
method: "PUT",
mode: "cors",
credentials: "include",
});
const j = await r.json();
showToast(`单元${body.unitName}调整出价${bid},${j.msg}`, "success");
console.log(`单元${body.unitName}调整出价${bid},${j.msg}`);
result.push(`单元${body.unitName}调整出价${bid},${j.msg}`);
}
async function set_bid(bid) {
const r = await fetch(
"https://ad.xiaohongshu.com/api/leona/rtb/unit/search",
{
headers: {
accept: "application/json, text/plain, */*",
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
"content-type": "application/json",
priority: "u=1, i",
"sec-ch-ua":
'"Chromium";v="134", "Not:A-Brand";v="24", "Microsoft Edge";v="134"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"Windows"',
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"x-b3-traceid": "e900951027b4cc32",
},
referrer: "https://ad.xiaohongshu.com/aurora/ad/manage/creativity",
referrerPolicy: "strict-origin-when-cross-origin",
body: `{\"startTime\":\"${
new Date().toISOString().split("T")[0]
}\",\"endTime\":\"${
new Date().toISOString().split("T")[0]
}\",\"pageNum\":1,\"pageSize\":100}`,
method: "POST",
mode: "cors",
credentials: "include",
}
)
.then((response) => response.json())
.then(async (data) => {
showToast(
`获取数据:当前获取单元${data.data.list.length}条\n开始执行调价`,
"info"
);
const result = [];
for (let index = 0; index < data.data.list.length; index++) {
const element = data.data.list[index];
showToast(`当前执行单元${element.unitName},调整出价为${bid}`, "info");
console.log(`当前执行单元${element.unitName},调整出价为${bid}`);
await getData(element, bid, result);
await sleep(1000);
}
alert(result.join("\n"));
});
}
//调价函数----------------------
// 创意开启关闭创意============================
// 关闭计划
async function closePlan(chunkedA,isColse) {
const text = isColse = 1?"开启创意":"关闭创意";
for (let i = 0; i < chunkedA.length; i++) {
const ids = chunkedA[i];
let retry = true;
while (retry) {
const r = await fetch(
"https://ad.xiaohongshu.com/api/leona/rtb/creativity/batch/status",
{
headers: {
accept: "application/json, text/plain, */*",
"accept-language":
"zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
"content-type": "application/json;charset=UTF-8",
priority: "u=1, i",
"sec-ch-ua":
'"Not(A:Brand";v="99", "Microsoft Edge";v="133", "Chromium";v="133"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"macOS"',
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"x-b3-traceid": "c1adc74c127d40f2",
},
referrer: "https://ad.xiaohongshu.com/aurora/ad/manage/creativity",
referrerPolicy: "strict-origin-when-cross-origin",
// 2是关闭 1是开启
body: JSON.stringify({
ids: ids,
actionType: parseInt(isColse),
}),
method: "PUT",
mode: "cors",
credentials: "include",
}
);
const res = await r.json();
console.log(res.msg);
if (res.msg === "成功") {
showToast(`${text},${res.msg}:${JSON.stringify(ids)}`, "success");
retry = false;
} else {
retry = true;
}
await new Promise((resolve) => setTimeout(resolve, 500));
}
}
}
function split_array(array, number) {
// 将数组a以number个为一组切割
const chunkedA = array.reduce((acc, _, index) => {
const chunkIndex = Math.floor(index / number);
if (!acc[chunkIndex]) {
acc[chunkIndex] = [];
}
acc[chunkIndex].push(_);
return acc;
}, []);
return chunkedA;
}
// 创意开启关闭创意-----------------------------
// 创建配置按钮
const optionButton = document.createElement("button");
addButtonAttributes(optionButton, "配置");
// 开启关闭创意============================
const openOrClose = document.createElement("button");
addButtonAttributes(openOrClose, "关闭/开启创意");
openOrClose.onclick = () => {
const { overlay, card, closeButton } = create_car();
// 创建第一个下拉列表
const creativeIdSelect = document.createElement("select");
creativeIdSelect.options.add(new Option("创意ID", "creativeId"));
creativeIdSelect.options.add(new Option("文字匹配", "textMatch"));
card.appendChild(creativeIdSelect);
// 创建第二个下拉列表
const toggleSelect = document.createElement("select");
toggleSelect.options.add(new Option("关闭", "2"));
toggleSelect.options.add(new Option("开启", "1"));
card.appendChild(toggleSelect);
// 创建多行文本输入框
const textArea = document.createElement("textarea");
card.appendChild(textArea);
// 创建请求按钮
const requestButton = document.createElement("button");
requestButton.textContent = "请求";
requestButton.onclick = async () => {
const chunkedA = split_array(textArea.value.trim().split(/\n|,\n/g).map(e=>e.trim()), 50);
// console.log();
closePlan(chunkedA,toggleSelect.value);
};
card.appendChild(requestButton);
// 将遮罩层和卡片添加到页面中
document.body.appendChild(overlay);
document.body.appendChild(card);
};
// 批量调价搜索词
const modify_the_price = document.createElement("button");
addButtonAttributes(modify_the_price, "批量调整出价");
modify_the_price.onclick = () => {
const bid = prompt("请输入出价");
//判断bid是否是数值 并且就bid转换成小数
if (isNaN(bid)) {
showToast("请输入数字", "error");
return;
}
if (bid) {
var Newbid = parseFloat(bid);
set_bid(Newbid);
}
};
// const download_today = document.createElement("button");
// addButtonAttributes(download_today, "下载今日创建");
// download_today.onclick = () => {
// fetch("https://ad.xiaohongshu.com/api/leona/rtb/creativity/list", {
// "headers": {
// "accept": "application/json, text/plain, */*",
// "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
// "content-type": "application/json",
// "priority": "u=1, i",
// "sec-ch-ua": "\"Chromium\";v=\"134\", \"Not:A-Brand\";v=\"24\", \"Microsoft Edge\";v=\"134\"",
// "sec-ch-ua-mobile": "?0",
// "sec-ch-ua-platform": "\"macOS\"",
// "sec-fetch-dest": "empty",
// "sec-fetch-mode": "cors",
// "sec-fetch-site": "same-origin",
// "x-b3-traceid": "268ef6d4ba91e008"
// },
// "referrer": "https://ad.xiaohongshu.com/aurora/ad/manage/creativity",
// "referrerPolicy": "strict-origin-when-cross-origin",
// "body": "{\"startTime\":\"2025-03-28\",\"endTime\":\"2025-03-28\",\"creativityCreateBeginTime\":\"2025-03-27\",\"creativityCreateEndTime\":\"2025-03-27\",\"pageNum\":1,\"pageSize\":20}",
// "method": "POST",
// "mode": "cors",
// "credentials": "include"
// });
// };
// 加载元素
optionButton.onclick = option;
buttonContainer.appendChild(optionButton);
buttonContainer.appendChild(openButton);
buttonContainer.appendChild(openOrClose);
buttonContainer.appendChild(modify_the_price);
// buttonContainer.appendChild(download_today);
})();