Greasy Fork

Greasy Fork is available in English.

小红书广告数据查询与展示

在当前页面插入悬浮元素,点击展开窗口并发送请求,将结果展示在表格中并提供Excel下载按钮

当前为 2025-03-12 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         小红书广告数据查询与展示
// @namespace    http://tampermonkey.net/
// @version      0.7
// @description  在当前页面插入悬浮元素,点击展开窗口并发送请求,将结果展示在表格中并提供Excel下载按钮
// @author       You
// @match        https://ad.xiaohongshu.com/aurora*
// @grant        GM_xmlhttpRequest
// @connect      ad.xiaohongshu.com
// @license MIT
// ==/UserScript==

(function () {
  "use strict";

  // 存储请求返回的数据
  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", sendRequest);

  // 点击下载按钮
  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);
    } catch (error) {
      console.error("解析响应数据时出错:", 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.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;
      `; // 改成 cssom
      const table = document.createElement('table');
      table.style.cssText = `
        width: 100%; 
        border-collapse: collapse;
      `; // 改成 cssom

      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);
      table.appendChild(thead);

      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(tbody);

      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);
          if (tbody.children.length > 0) {
              tbody.insertBefore(newRow, tbody.children[0]);
          } else {
              tbody.appendChild(newRow);
          }
      };
      table.appendChild(addButton);

      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'; // 点击保存后隐藏当前元素
      };
      table.appendChild(saveButton);

      div.appendChild(table);
      document.body.appendChild(div);
  }
  //======================改名
  // 创建打开卡片的按钮
  const openButton = document.createElement('button');
  addButtonAttributes(openButton, "修改单元内计划字符");

  // 为打开按钮添加点击事件监听器
  openButton.addEventListener('click', function () {
    const sheet = new CSSStyleSheet();
    sheet.replaceSync(`
      #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 #ccc;
        padding: 20px;
        box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
        z-index: 2147483647;
        transform: translate(-50%, -50%);
      }
    `);
    const allSheets = [...document.adoptedStyleSheets, sheet];
    document.adoptedStyleSheets=allSheets
    // 创建遮罩层
    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);
    });

    // 创建第一个输入框及其标签
    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\":\"2025-02-27\",\"endTime\":\"2025-02-27\",\"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;
      }
    `);
    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);
    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"
    });
}

  //======================


  // 创建配置按钮
  const optionButton = document.createElement("button");
    addButtonAttributes(optionButton,"配置")

  optionButton.onclick = option;
  buttonContainer.appendChild(optionButton);
buttonContainer.appendChild(openButton);
})();