您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在小红书笔记页面添加两个悬浮按钮:1. 自动展开所有评论;2. 导出所有评论(包含帖子链接和完整信息)为TXT文件。
// ==UserScript== // @name 小红书评论区助手 // @namespace http://tampermonkey.net/ // @version 0.1 // @description 在小红书笔记页面添加两个悬浮按钮:1. 自动展开所有评论;2. 导出所有评论(包含帖子链接和完整信息)为TXT文件。 // @author Gao + Claude // @match https://www.xiaohongshu.com/explore/* // @grant GM_addStyle // @license MIT // ==/UserScript== (function() { 'use strict'; // --- 样式定义 (与之前相同) --- GM_addStyle(` .xhs-helper-btn-container { position: fixed; bottom: 20px; right: 20px; z-index: 9999; display: flex; flex-direction: column; gap: 10px; } .xhs-helper-btn { padding: 10px 15px; background-color: #ff2442; color: white; border: none; border-radius: 8px; cursor: pointer; font-size: 14px; font-weight: 500; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); transition: background-color 0.3s, transform 0.2s; width: 150px; text-align: center; } .xhs-helper-btn:hover { background-color: #e01f38; } .xhs-helper-btn:disabled { background-color: #cccccc; cursor: not-allowed; transform: none; } .xhs-helper-btn:active:not(:disabled) { transform: scale(0.98); } `); // --- 创建按钮 (与之前相同) --- const container = document.createElement('div'); container.className = 'xhs-helper-btn-container'; const expandButton = document.createElement('button'); expandButton.id = 'expand-comments-btn'; expandButton.className = 'xhs-helper-btn'; expandButton.innerText = '自动展开评论'; const exportButton = document.createElement('button'); exportButton.id = 'export-comments-btn'; exportButton.className = 'xhs-helper-btn'; exportButton.innerText = '导出全部评论'; container.appendChild(expandButton); container.appendChild(exportButton); document.body.appendChild(container); // --- 核心功能实现 (大部分与之前相同) --- const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)); async function handleExpandComments() { let clickCount = 0; expandButton.disabled = true; expandButton.innerText = '展开中...'; try { while (true) { const moreButtons = document.querySelectorAll('.show-more, .bottom-bar .loading.active'); if (moreButtons.length === 0) { console.log('未找到可展开的按钮,任务完成。'); expandButton.innerText = '全部已展开'; break; } console.log(`找到 ${moreButtons.length} 个展开按钮,正在点击...`); moreButtons.forEach(btn => { btn.click(); clickCount++; expandButton.innerText = `展开中... (${clickCount})`; }); await sleep(1500); } } catch (error) { console.error('展开评论时发生错误:', error); expandButton.innerText = '出现错误'; } } function handleExportComments() { exportButton.disabled = true; exportButton.innerText = '正在导出...'; console.log('开始提取评论内容...'); let exportText = ''; // --- 新增功能:获取并添加帖子链接 --- const postUrl = window.location.href; exportText += `帖子链接: ${postUrl}\n\n`; const noteTitle = document.querySelector('#detail-title')?.textContent.trim() || '未知标题'; const authorName = document.querySelector('.author-wrapper .name .username')?.textContent.trim() || '未知作者'; const noteDesc = document.querySelector('#detail-desc')?.textContent.trim() || '无'; exportText += `笔记标题: ${noteTitle}\n`; exportText += `作者: ${authorName}\n\n`; exportText += `笔记内容:\n${noteDesc}\n\n`; exportText += "==================== 评论区 ====================\n\n"; const comments = document.querySelectorAll('.parent-comment'); if (comments.length === 0) { exportText += "当前页面没有评论。"; } comments.forEach((comment, index) => { const mainCommentInfo = extractCommentInfo(comment); exportText += `【${index + 1}楼】 ${mainCommentInfo.userName} (点赞: ${mainCommentInfo.likes})\n`; exportText += `时间: ${mainCommentInfo.time} ${mainCommentInfo.location}\n`; exportText += `内容: ${mainCommentInfo.content}\n`; const replies = comment.querySelectorAll('.reply-container .comment-item'); if (replies.length > 0) { exportText += "--- 回复 ---\n"; replies.forEach(reply => { const replyInfo = extractCommentInfo(reply); exportText += ` -> ${replyInfo.userName} (点赞: ${replyInfo.likes}): ${replyInfo.content}\n`; if(replyInfo.time || replyInfo.location){ exportText += ` 时间: ${replyInfo.time} ${replyInfo.location}\n`; } }); } exportText += '----------------------------------------\n\n'; }); console.log('评论提取完成,准备下载...'); downloadTextFile(exportText, `${noteTitle}_评论区.txt`); exportButton.innerText = '导出完成!'; setTimeout(() => { exportButton.disabled = false; exportButton.innerText = '导出全部评论'; }, 3000); } function extractCommentInfo(element) { const userElement = element.querySelector('.name'); const contentElement = element.querySelector('.content'); const timeElement = element.querySelector('.info .date'); const locationElement = element.querySelector('.info .location'); const likeCountElement = element.querySelector('.like-wrapper .count'); const userName = userElement?.textContent.trim().replace(/\s*回复\s*.*/, '') || '未知用户'; const content = contentElement?.textContent.trim() || '(无文本内容)'; const time = timeElement?.textContent.trim() || ''; const location = locationElement ? `IP属地: ${locationElement.textContent.trim()}` : ''; let likes = '0'; if (likeCountElement) { const likeText = likeCountElement.textContent.trim(); if (likeText && !isNaN(parseInt(likeText, 10))) { likes = likeText; } } return { userName, content, time, location, likes }; } function downloadTextFile(text, filename) { const blob = new Blob([text], { type: 'text/plain;charset=utf-8' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = filename; document.body.appendChild(a); a.click(); setTimeout(() => { document.body.removeChild(a); URL.revokeObjectURL(url); }, 100); } // --- 绑定事件监听 --- expandButton.addEventListener('click', handleExpandComments); exportButton.addEventListener('click', handleExportComments); })();