// ==UserScript== // @name 小红书批量取消点赞&收藏 // @namespace http://tampermonkey.net/ // @version 1.0 // @icon https://fe-video-qc.xhscdn.com/fe-platform/ed8fe781ce9e16c1bfac2cd962f0721edabe2e49.ico // @author yangshengzhou // @description 进入个人点赞/收藏页面,一键批量取消所有笔记点赞、收藏,自动滚动加载全部内容,内置间隔防限流,支持手动停止批量操作 // @match https://www.xiaohongshu.com/user/profile/*?tab=liked* // @match https://www.xiaohongshu.com/user/profile/*?tab=fav* // @grant GM_addStyle // ==/UserScript== (function(){ 'use strict'; GM_addStyle(` #batchToolPanel{position:fixed;top:100px;right:20px;z-index:99999;background:#fff;border-radius:12px;padding:16px;box-shadow:0 4px 20px rgba(255,36,66,0.15);width:280px;border:1px solid #f5f5f5;font-family:system-ui,-apple-system,sans-serif;user-select:none} #panelDragHead{width:100%;padding:4px 0 8px;margin:-4px 0 10px;cursor:move;font-size:15px;font-weight:600;color:#222;display:flex;align-items:center;gap:6px} #toggleRunBtn{width:100%;padding:10px 0;border:none;border-radius:8px;font-size:14px;font-weight:500;cursor:pointer;transition:all 0.2s ease;margin-top:12px} #toggleRunBtn.start-state{background:linear-gradient(135deg,#ff4757,#ff2442);color:#fff} #toggleRunBtn.start-state:hover{background:linear-gradient(135deg,#ff384a,#e61e3b)} #toggleRunBtn.stop-state{background:#444;color:#fff} #toggleRunBtn.stop-state:hover{background:#2a2a2a} #toggleRunBtn:disabled{opacity:0.6;cursor:not-allowed} #logBox{margin-top:12px;width:100%;height:180px;overflow-y:auto;font-size:12px;border:1px solid #eee;padding:8px;border-radius:6px;background:#fafafa;white-space:pre-wrap;color:#333;line-height:1.5} #logBox::-webkit-scrollbar{width:4px} #logBox::-webkit-scrollbar-thumb{background:#ddd;border-radius:2px} `); // 创建面板容器 const panel=document.createElement('div'); panel.id='batchToolPanel'; panel.innerHTML=`
`; document.body.appendChild(panel); const logBox=document.getElementById('logBox'); const toggleBtn=document.getElementById('toggleRunBtn'); const dragHead=document.getElementById('panelDragHead'); // 全局状态 let running=false; let stopFlag=false; let dragStartX,dragStartY,panelStartX,panelStartY; // 通用延时常量 const CLICK_DELAY = 1300; const SCROLL_WAIT = 1800; const POPUP_WAIT = 900; const ACTION_WAIT = 600; // 判断当前页面类型 const url = location.href; const isLikePage = url.includes('tab=liked'); const isFavPage = url.includes('tab=fav'); // 设置面板标题与图标 if(isLikePage){ dragHead.innerHTML = ` 批量取消点赞工具`; }else if(isFavPage){ dragHead.innerHTML = ` 批量取消收藏工具`; } // 日志输出 function log(text){ const time=new Date().toLocaleTimeString(); logBox.innerHTML+=`[${time}] ${text}\n`; logBox.scrollTop=logBox.scrollHeight; } // 重置按钮状态 function resetButtonState(){ toggleBtn.disabled=false; toggleBtn.textContent="开始批量取消"; toggleBtn.classList.remove("stop-state"); toggleBtn.classList.add("start-state"); } // 延时工具 function sleep(ms){ return new Promise(res=>setTimeout(res,ms)); } // ---------------------- 点赞页面逻辑 ---------------------- async function unlikeAllTask(){ running=true; stopFlag=false; toggleBtn.textContent="终止操作"; toggleBtn.classList.remove("start-state"); toggleBtn.classList.add("stop-state"); // 预加载滚动 window.scrollTo(0,document.body.scrollHeight); await sleep(SCROLL_WAIT); window.scrollTo(0,0); await sleep(SCROLL_WAIT); if(stopFlag){ log('任务手动终止'); resetButtonState(); running=false; return; } const btns=Array.from(document.querySelectorAll('.note-item .like-wrapper.like-active')); if(btns.length===0){ log('未检测到可取消点赞笔记,任务结束'); resetButtonState(); running=false; return; } log(`预加载完成,共检测到${btns.length}条点赞笔记,开始批量取消`); for(let i=0;i{ if(running){ stopFlag=true; return; } toggleBtn.disabled=true; if(isLikePage){ await unlikeAllTask(); }else if(isFavPage){ await cancelFavAllTask(); } }); // 拖拽功能 dragHead.addEventListener('mousedown',e=>{ dragStartX=e.clientX; dragStartY=e.clientY; const rect=panel.getBoundingClientRect(); panelStartX=rect.left; panelStartY=rect.top; document.addEventListener('mousemove',dragMove); document.addEventListener('mouseup',dragEnd); }); function dragMove(e){ const dx=e.clientX-dragStartX; const dy=e.clientY-dragStartY; panel.style.left=(panelStartX+dx)+'px'; panel.style.top=(panelStartY+dy)+'px'; panel.style.right='auto'; } function dragEnd(){ document.removeEventListener('mousemove',dragMove); document.removeEventListener('mouseup',dragEnd); } })();