您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
导出小红书列表数据,方便做数据分析
// ==UserScript== // @name 小红书笔记导出 // @namespace http://www.junxiaopang.com/ // @version 1.3.1 // @description 导出小红书列表数据,方便做数据分析 // @author 俊小胖 // @match https://www.xiaohongshu.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=xiaohongshu.com // @license GPL // @require https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js // ==/UserScript== (function () { 'use strict'; let data = []; let itemNum = 0 //当前加载笔记的数量 let excel_title = '小红书数据' let likeNumLimit = 100 //导出的数据点赞数要求 let keywords = ''//过滤的关键词 // 定义一个函数来抓取数据 function fetchData() { var itemNumElement = document.getElementById('itemNum'); // 假设列表数据在某个具有特定类名的元素中 const listElements = document.querySelectorAll('.note-item'); // 需要根据实际页面结构调整选择器 const domain = 'https://www.xiaohongshu.com' listElements.forEach(item => { const linkElement = item.querySelector('a.cover.ld.mask'); //console.log(item.querySelector('.title')); if (linkElement) { const link = domain + linkElement.getAttribute('href'); // 拼接完整链接 let title = item.querySelector('.title').textContent; // 需要根据实际页面结构调整选择器 let author = item.querySelector('.author').textContent; // 需要根据实际页面结构调整选择器 let likeCount = item.querySelector('.like-wrapper').textContent; // 需要根据实际页面结构调整选择器 let links = item.querySelector('a').getAttribute('href'); // 需要根据实际页面结构调整选择器 let itemIndex = item.dataset.index ? item.dataset.index : 0 likeCount = convertToNumber(likeCount ? likeCount : 0) let itemData = [title, author, likeCount, link] data[itemIndex] = itemData } }); itemNum = data.length if (itemNumElement) { itemNumElement.textContent = itemNum; // 更新文本内容 } } //过滤点赞数限制的数据 function filterArrayByLikeNum(arr, limit) { var newArray = []; arr.forEach(function (subArray) { if (subArray[2] > limit) { newArray.push(subArray); } }); return newArray; } function containsAnyKeyword(str, keywords) { const regexPattern = `(${keywords.join('|')})`; const regex = new RegExp(regexPattern, 'i'); // 'i' 表示不区分大小写 return regex.test(str); } //过滤指定关键词 function filterArrayByTitle(arr, keywords) { var newArray = []; arr.forEach(function (subArray) { if (!containsAnyKeyword(subArray[0], keywords)) { newArray.push(subArray); } }); return newArray; } // 定义点击按钮时执行的函数 function onButtonClick() { // 在这里添加你想要执行的代码 exportArrayToExcel(data, excel_title); // fetchData() } //自定义页面样式 function addStyle() { var style = document.createElement('style'); style.type = 'text/css'; style.innerHTML = '.export-note{margin: 6px 0 12px 0;}.group-header-title{font-size: 16px;border-bottom: 1px solid #eee;padding: 10px 0;margin-bottom: 10px;color: rgba(51, 51, 51, 0.6);}.group-header-title a{float: right;color: #f6333b;}#itemNum{font-weight: bold;color: red;}.export-data {margin: 6px 0;display: flex;flex-wrap: wrap;flex-direction: row-reverse;border:solid 1px #eee;border-radius: 16px;padding:6px;line-height: 25px;}.export-button{text-align: center;padding:6px;border:border: 1px solid transparent;background-color:#ff2442;color:#ffffff;border-radius:5px;cursor:pointer}.input{margin: 0 4px;padding:2px 4px;border: 1px solid #ccc;border-radius: 4px;background-color: #eee;width: 60px;}'; document.head.appendChild(style); } // 动态插入<script>标签 function loadScript(url, callback) { // 创建script元素 var script = document.createElement('script'); script.type = 'text/javascript'; script.src = url; // 绑定事件处理程序 script.onreadystatechange = script.onload = function () { var state = this.readyState; if (!callback.done && (!state || /loaded|complete/.test(state))) { callback.done = true; callback(); } }; // 插入到DOM中 document.getElementsByTagName('head')[0].appendChild(script); } // export-to-excel.js function exportArrayToExcel(dataArray, fileName) { var newDataArray = dataArray var keywordArray = [] var limit = parseFloat(document.getElementById("likeNumLimit").value); var keywords_value = document.getElementById("keywords").value; if (limit > 0) { newDataArray = filterArrayByLikeNum(dataArray, limit) if (keywords_value && keywords_value != '') { keywordArray = keywords_value.split(","); // 使用逗号作为分隔符 newDataArray = filterArrayByTitle(newDataArray, keywordArray) } } newDataArray.unshift(['标题', '作者', '点赞数', '链接']); // 创建一个工作簿 const workbook = XLSX.utils.book_new(); // 将数组转换为工作表 const worksheet = XLSX.utils.aoa_to_sheet(newDataArray); // 将工作表添加到工作簿 XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1"); // 导出工作簿 XLSX.writeFile(workbook, fileName + ".xlsx"); } //转换点赞数为数字 function convertToNumber(text) { // 移除空格 text = text.replace(/\s+/g, ''); // 检测单位 if (text.endsWith('w')) { // 移除单位并转换为数字 return parseFloat(text.slice(0, -1)) * 10000; } else { // 如果没有单位,直接返回转换后的数字 return parseFloat(text); } } //监听鼠标滑动更新数据 document.addEventListener('mousemove', function (event) { fetchData() }); // 创建按钮元素 const button = document.createElement('button'); button.textContent = '导出excel'; button.className = 'export-button' // 为按钮添加点击事件监听器 button.addEventListener('click', onButtonClick); //载入导出按钮 function loadExportButton() { addStyle() // 导出函数到全局 window.exportArrayToExcel = exportArrayToExcel; // 创建一个 URL 对象 var url = new URL(window.location.href); // 使用 URLSearchParams 获取参数 var keyword = url.searchParams.get('keyword'); if (keyword) { keyword = decodeURIComponent(keyword) excel_title = keyword + ' - 小红书数据' } else if (document.title) { excel_title = document.title; } // 找到具有特定类名的元素 var targetElement = document.querySelector('.channel-list'); // 创建一个新的 div 元素 var exportDiv = document.createElement('div'); // 设置 div 的内容 exportDiv.innerHTML = '<div class="export-note"><div class="group-header-title">红薯笔记导出<a href="http://shang.junxiaopang.com" target="_blank">💰打赏开发者</a></div>支持导出页面上加载过的笔记列表<br>方便运营人员做数据分析提高工作效率<br>当前已加载<span id="itemNum">0</span>条数据<br>上下滑动鼠标可以加载更多<div class="group-header-title">导出设置</div>只导出点赞大于<input name="like-num" id="likeNumLimit" value="' + likeNumLimit + '" class="input" type="number"/>的数据<br>过滤标题中带有<input name="keywords" id="keywords" value="' + keywords + '" class="input" type="text"/>的内容</div>'; // 添加类名或者样式 exportDiv.className = 'export-data'; // 如果要插入到特定位置,比如body的开头,可以直接使用以下代码: targetElement.appendChild(exportDiv); exportDiv.appendChild(button); //页面加载完以后,初始化读取 fetchData() } // 等待页面加载完毕再执行 window.addEventListener('load', loadExportButton); })();