Greasy Fork is available in English.

美团券搜索

页面请求手机页面,先登录账户后,获取列表,建议使用移动网络,定位否则不准确

// ==UserScript==
// @name         美团券搜索
// @license      MIT
// @version      1.1
// @description  页面请求手机页面,先登录账户后,获取列表,建议使用移动网络,定位否则不准确
// @author       Bingo95
// @match        https://offsiteact.meituan.com/web/hoae/collection_waimai_v7/index.html
// @grant        none
// @namespace https://greasyfork.org/users/1312821
// ==/UserScript==

(function () {
  ('use strict');
  var timeStart = '';

  // 获取数据
  function myMethod() {
    timeStart = setInterval(() => {
      // 获取文档的总高度
      var totalHeight = document.body.scrollHeight;

      // 获取视窗的宽度
      var windowWidth = window.innerWidth;

      // 滚动到页面底部
      window.scrollTo(windowWidth, totalHeight);
    }, 1000);
  }

  // 检查是否登录
  function checkLogin() {
    const targetNode = document.getElementById('searchBar');
    // 获取第一个包含 'style_name' 前缀的元素
    const nameElement = targetNode.querySelector(
      '[class^="style_login-content-btn"]'
    );
    // 提取并打印该元素的文本内容
    if (nameElement && nameElement.textContent.includes('登录')) {
      nameElement.click();
    } else {
      myMethod();
    }
  }

  // 创建一个获取数据按钮
  function createGetDataButton() {
    // 创建一个新的input元素
    let button = document.createElement('button');
    // 设置按钮的文本内容
    let buttonText = document.createTextNode('获取数据');
    // 设置元素的类型
    button.appendChild(buttonText);
    // 设置input元素的内联样式
    button.style.width = '40vw';
    button.style.height = '10vw';
    button.style.padding = '5px';
    button.style.margin = '10px';
    button.style.border = '1px solid #ccc';
    button.style.borderRadius = '5px';
    button.style.boxSizing = 'border-box';
    button.style.position = 'fixed';
    button.style.zIndex = '10000';
    button.style.right = '0';
    button.style.top = '10.667vw';

    // 将元素插入到body中
    document.body.appendChild(button);

    button.addEventListener('click', checkLogin);
  }

  function checkCharactersInText(sourceText, targetText) {
    // 使用正则表达式将sourceText拆分为单个字符(包括中文字符)
    const sourceChars = sourceText.match(/[\u4e00-\u9fa5]|[^\x00-\xff]/g) || []; // 匹配中文字符或单字节字符

    // 检查每个字符是否在targetText中出现
    for (let char of sourceChars) {
      if (targetText.indexOf(char) === -1) {
        console.log(`字符'${char}'未在目标文本中出现`);
        return false; // 如果找到未出现的字符,则返回false
      }
    }

    console.log('所有字符都在目标文本中出现');
    return true; // 所有字符都出现,返回true
  }

  // 搜索逻辑
  function searchQuery(params) {
    const elementsArray = Array.from(document.getElementsByClassName('mb16'));
    elementsArray.forEach((dom) => {
      // 获取第一个包含 'style_name' 前缀的元素
      const nameElement = dom.querySelector('[class^="style_name"]');
      // 没找到关键字的元素就隐藏
      if (!checkCharactersInText(params, nameElement.textContent)) {
        dom.setAttribute('hidden', 'true');
      } else {
        if (dom.hasAttribute('hidden')) {
          // 删除属性
          dom.removeAttribute('hidden');
        }
      }
    });
  }

  // 创建一个获取数据按钮
  function createSearchInput() {
    // 创建一个新的form元素 为了按钮显示搜索
    let form = document.createElement('form');
    // action="javascript: void(0);"
    form.setAttribute('action', 'javascript: void(0);');

    // 创建一个新的input元素
    let input = document.createElement('input');

    // 设置input元素的类型
    input.type = 'search';
    input.placeholder = '输入店名或店名关键字筛选';
    // 设置input元素的内联样式
    input.style.width = '95vw';
    input.style.height = '15vw';
    input.style.padding = '5px';
    input.style.margin = '10px';
    input.style.border = '1px solid #ccc';
    input.style.borderRadius = '5px';
    input.style.boxSizing = 'border-box';
    input.style.position = 'fixed';
    input.style.left = '0';
    input.style.bottom = '0';

    form.appendChild(input);
    // 将input元素插入到body中
    document.body.appendChild(form);

    // 为input元素添加keydown事件监听器
    input.addEventListener('keydown', function (event) {
      // 检查是否是回车键(Enter键)
      if (event.key === 'Enter' || event.code === 13) {
        // 阻止表单默认的提交行为(如果有的话)
        event.preventDefault();

        // 执行搜索逻辑
        searchQuery(input.value);
      }
    });
  }

  // 监听列表获取全部数据停止定时器函数
  function observerElement() {
    const observerParent = new MutationObserver(function (mutationsList) {
      for (let mutationp of mutationsList) {
        if (mutationp.type === 'childList') {
          let targetNode = document.getElementById(
            'bottom_tip_cpsSelfCouponAll'
          );
          if (targetNode) {
            // 目标节点现在存在,开始观察它
            observerParent.disconnect(); // 停止观察父节点

            // 绑定MutationObserver到目标节点
            let targetObserver = new MutationObserver(function (mutations) {
              // 处理目标节点的变动
              for (let mutation of mutations) {
                if (mutation.type === 'childList') {
                  const text = targetNode.textContent;
                  if (text === '亲,没有更多啦~') {
                    clearInterval(timeStart);
                    console.log('stop');
                    // 停止观察
                    targetObserver.disconnect();
                  }
                }
              }
            });

            // 配置观察选项
            let configc = { attributes: true, childList: true, subtree: true };
            // 开始观察目标节点
            targetObserver.observe(targetNode, configc);
            break; // 找到目标节点后停止循环
          }
        }
      }
    });

    // 选择一个父节点来观察,这个父节点会在目标节点被添加之前存在
    const parentNode = document.body;

    // 配置观察选项
    const config = { childList: true, subtree: true };

    // 开始观察父节点
    observerParent.observe(parentNode, config);
  }

  window.onload = function () {
    observerElement();
    createSearchInput();
    createGetDataButton();
  };
})();