日常够用,但是 过客 https://www.yingdao.com/community/userCenter?userUuid=687223449269694466 用户有1600条回答,恐怖如斯ᔪ꒰꒪ω꒪|||꒱,原有的就不够用了,10条10条得加载到什么时候.
于是通过修改请求,每次请求返回最大500条文章,来解决.应该有办法更快,不过懒得弄了,正常来讲不至于超过500条回答
吧.....................................
篡改猴脚本:
// ==UserScript==
// @name 影刀社区文章自动加载与搜索器
// @namespace http://tampermonkey.net/
// @version 1.6
// @description 优化影刀社区页面,支持大量文章自动加载(每次500条)和搜索功能,修复回答栏目搜索显示问题和收藏栏目搜索功能
// @author You
// @match *://www.yingdao.com/community/userCenter?userUuid*
// @grant none
// ==/UserScript==
(function() {
'use strict';
// 全局变量
let currentSection = 'PUBLISH'; // 默认栏目:发布
let currentSubSection = '提问'; // 默认子栏目:提问
let loadedCount = 0; // 已加载的内容数量
let totalCount = 0; // 当前栏目总内容数量
let isLoading = false; // 加载状态标志
let loadInterval = null; // 自动加载的定时器
let retryCount = 0; // 重试次数计数
let maxRetries = 10; // 最大重试次数
// XPath常量定义
const XPATHS = {
// 发布栏目子栏目按钮
publishQuestion: "//div[@id=\"rc-tabs-0-panel-PUBLISH\"]//div[contains(@class, \"btn___N0geJ\")]//div//button[contains(text(),\"提问\")]",
publishAnswer: "//div[@id=\"rc-tabs-0-panel-PUBLISH\"]//div[contains(@class, \"btn___N0geJ\")]//div//button[contains(text(),\"回答\")]",
publishArticle: "//div[@id=\"rc-tabs-0-panel-PUBLISH\"]//div[contains(@class, \"btn___N0geJ\")]//div//button[contains(text(),\"文章\")]",
// 收藏栏目子栏目按钮
collectQa: "//div[@id=\"rc-tabs-0-panel-COLLECT\"]//div[contains(@class, \"btn___N0geJ\")]//div//button[contains(text(),\"问答\")]",
collectArticle: "//div[@id=\"rc-tabs-0-panel-COLLECT\"]//div[contains(@class, \"btn___N0geJ\")]//div//button[contains(text(),\"文章\")]",
// 查看更多按钮
viewMore: "//span[normalize-space(text())=\"查看更多\"]"
};
// 配置常量
const 配置 = {
每页加载数量: 500,
初始延时: 2000, // 栏目切换后初始等待时间
回答栏目初始延时: 4000, // 回答栏目特殊处理,给予更长时间加载
重试间隔: 2000, // 按钮检测失败后的重试间隔
检查间隔: 3000 // 常规检查间隔
};
// API请求监控对象
const API请求监控 = {
最后请求时间: 0,
请求计数: 0,
最后响应数据: null
};
// 初始化函数
function 初始化() {
console.log('影刀社区文章自动加载与搜索器v1.3初始化');
// 添加搜索框
添加搜索框();
// 设置栏目监听
设置栏目监听();
// 初始化当前栏目信息
更新栏目信息();
// 设置MutationObserver监听页面变化
设置页面变化监听();
// 注入API拦截器
注入API拦截器();
// 开始自动加载
开始自动加载();
// 添加全局错误处理
添加全局错误处理();
}
// 获取当前栏目信息函数
function 获取当前栏目信息() {
let 栏目标识 = '';
let 大栏目 = currentSection;
let 子栏目 = currentSubSection;
if (currentSection === 'PUBLISH') {
if (currentSubSection.includes('提问')) {
栏目标识 = '发布提问';
} else if (currentSubSection.includes('回答')) {
栏目标识 = '发布回答';
} else if (currentSubSection.includes('文章')) {
栏目标识 = '发布文章';
}
} else if (currentSection === 'COLLECT') {
if (currentSubSection.includes('问答')) {
栏目标识 = '收藏问答';
} else if (currentSubSection.includes('文章')) {
栏目标识 = '收藏文章';
}
}
return {
栏目标识: 栏目标识,
大栏目: 大栏目,
子栏目: 子栏目
};
}
// 优化版API拦截器 - 借鉴废弃版实现
function 注入API拦截器() {
try {
console.log('开始注入API拦截器...');
const 原始Fetch = window.fetch;
// 重写fetch函数
window.fetch = function(url, options) {
// 检查是否是目标API请求 - 使用废弃版的精确匹配模式
if (typeof url === 'string' &&
(url.includes('queryUserPublishList') ||
url.includes('queryUserAnswerList') ||
url.includes('queryUserQuestionList') ||
url.includes('queryUserFavoriteList'))) {
console.log(`拦截到用户内容加载请求: ${url}`);
// 更新API请求监控
API请求监控.最后请求时间 = Date.now();
API请求监控.请求计数++;
try {
// 解析请求选项
const 修改选项 = options || {};
// 如果有请求体,尝试解析并修改
if (修改选项.body) {
const 请求体 = JSON.parse(修改选项.body);
// 智能判断:只有当当前栏目是目标栏目时才修改数量
const 栏目信息 = 获取当前栏目信息();
if ((栏目信息.栏目标识 === '发布文章' && url.includes('queryUserPublishList')) ||
(栏目信息.栏目标识 === '发布回答' && (url.includes('queryUserPublishList') || url.includes('queryUserAnswerList'))) ||
(栏目信息.栏目标识 === '发布提问' && url.includes('queryUserQuestionList')) ||
(栏目信息.栏目标识 === '收藏问答' || 栏目信息.栏目标识 === '收藏文章') && url.includes('queryUserFavoriteList')) {
// 修改size或pageSize参数为500
if (请求体.size !== undefined) {
const 原始数量 = 请求体.size;
请求体.size = 配置.每页加载数量;
修改选项.body = JSON.stringify(请求体);
console.log(`修改size参数: ${原始数量} -> ${配置.每页加载数量}`);
} else if (请求体.pageSize !== undefined) {
const 原始数量 = 请求体.pageSize;
请求体.pageSize = 配置.每页加载数量;
修改选项.body = JSON.stringify(请求体);
console.log(`修改pageSize参数: ${原始数量} -> ${配置.每页加载数量}`);
}
}
// 确保请求包含正确的用户ID
const 用户ID = 获取URL参数('userUuid');
if (用户ID) {
if (请求体.userUuid) {
请求体.userUuid = 用户ID;
}
}
}
// 处理URL参数
if (url.includes('?')) {
const urlParts = url.split('?');
const queryParams = new URLSearchParams(urlParts[1]);
// 更新size或pageSize参数为500
if (queryParams.has('size')) {
queryParams.set('size', 配置.每页加载数量.toString());
url = `${urlParts[0]}?${queryParams.toString()}`;
console.log(`修改URL size参数为: ${配置.每页加载数量}`);
} else if (queryParams.has('pageSize')) {
queryParams.set('pageSize', 配置.每页加载数量.toString());
url = `${urlParts[0]}?${queryParams.toString()}`;
console.log(`修改URL pageSize参数为: ${配置.每页加载数量}`);
}
}
console.log(`API请求已修改: ${url}`);
} catch (e) {
console.error('修改请求参数失败:', e);
}
}
// 执行原始fetch并返回Promise
return 原始Fetch(url, options).then(response => {
// 克隆响应以解析其内容
const 克隆的响应 = response.clone();
// 尝试解析JSON响应
克隆的响应.json().then(data => {
API请求监控.最后响应数据 = data;
// 验证是否成功加载了500条数据
if (data.data && data.data.records) {
console.log(`成功加载 ${data.data.records.length} 条记录`);
}
}).catch(e => {
// 非JSON响应,忽略错误
});
return response;
}).catch(error => {
console.error('API请求错误:', error);
throw error;
});
};
console.log('API拦截器注入成功,已配置为每次加载500条数据');
} catch (error) {
console.error('注入API拦截器失败:', error);
}
}
// 获取URL参数函数
function 获取URL参数(参数名) {
const URL参数 = new URLSearchParams(window.location.search);
return URL参数.get(参数名);
}
// 添加全局错误处理
function 添加全局错误处理() {
// 全局错误处理
window.addEventListener('error', function(event) {
console.error('全局错误:', event.message, event.error);
// 不阻止默认行为,让错误继续传播
});
// Promise拒绝处理
window.addEventListener('unhandledrejection', function(event) {
console.error('Promise拒绝:', event.reason);
// 不阻止默认行为,让错误继续传播
});
}
// 添加搜索框
function 添加搜索框() {
// 创建搜索容器
const searchContainer = document.createElement('div');
searchContainer.style.cssText = `
position: fixed;
top: 10px;
right: 20px;
z-index: 9999;
background: white;
padding: 10px;
border-radius: 6px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
display: flex;
align-items: center;
`;
// 创建搜索输入框
const searchInput = document.createElement('input');
searchInput.type = 'text';
searchInput.placeholder = '搜索内容...';
searchInput.style.cssText = `
padding: 8px 32px 8px 12px;
border: 1px solid #d9d9d9;
border-radius: 4px;
width: 250px;
margin-right: 8px;
font-size: 14px;
box-sizing: border-box;
`;
// 创建搜索按钮
const searchButton = document.createElement('button');
searchButton.textContent = '搜索';
searchButton.style.cssText = `
padding: 8px 16px;
background: #1890ff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
margin-right: 8px;
`;
// 创建清除按钮
const clearButton = document.createElement('button');
clearButton.textContent = '清除';
clearButton.style.cssText = `
padding: 8px 16px;
background: #f0f0f0;
color: #333;
border: 1px solid #d9d9d9;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
`;
// 添加搜索事件
searchButton.addEventListener('click', () => 执行搜索(searchInput.value));
clearButton.addEventListener('click', () => {
searchInput.value = '';
执行搜索('');
});
// 回车键搜索
searchInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') 执行搜索(searchInput.value);
});
// 监听输入变化,添加防抖
let searchTimeout;
searchInput.addEventListener('input', () => {
clearTimeout(searchTimeout);
// 搜索框为空时立即恢复所有内容显示
if (searchInput.value.trim() === '') {
执行搜索('');
}
});
// 组装搜索框
searchContainer.appendChild(searchInput);
searchContainer.appendChild(searchButton);
searchContainer.appendChild(clearButton);
document.body.appendChild(searchContainer);
// 定位搜索框到页面顶部右侧
searchContainer.style.position = 'fixed';
searchContainer.style.top = '10px';
searchContainer.style.right = '10px';
searchContainer.style.zIndex = '9999';
searchContainer.style.background = 'white';
searchContainer.style.padding = '10px';
searchContainer.style.borderRadius = '6px';
searchContainer.style.boxShadow = '0 2px 8px rgba(0, 0, 0, 0.15)';
searchContainer.style.display = 'flex';
searchContainer.style.alignItems = 'center';
}
// UI提示函数 - 替代浏览器弹窗
function 显示搜索结果提示(message, isSuccess = true) {
try {
// 创建或获取提示容器
let 提示容器 = document.getElementById('搜索提示容器');
if (!提示容器) {
提示容器 = document.createElement('div');
提示容器.id = '搜索提示容器';
提示容器.style.cssText = `
position: fixed;
top: 20px;
left: 50%;
transform: translateX(-50%);
z-index: 99999;
background: ${isSuccess ? '#52c41a' : '#ff7875'};
color: white;
padding: 12px 24px;
border-radius: 6px;
font-size: 14px;
font-weight: 500;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
max-width: 400px;
text-align: center;
line-height: 1.4;
transition: all 0.3s ease;
`;
document.body.appendChild(提示容器);
}
// 更新提示内容和样式
提示容器.textContent = message;
提示容器.style.background = isSuccess ? '#52c41a' : '#ff7875';
提示容器.style.display = 'block';
// 3秒后自动隐藏
setTimeout(() => {
提示容器.style.opacity = '0';
setTimeout(() => {
提示容器.style.display = 'none';
}, 300);
}, 3000);
console.log(`搜索提示: ${message}`);
} catch (e) {
console.error('显示搜索提示失败:', e);
// 如果UI提示失败,回退到控制台输出
console.log(`搜索结果: ${message}`);
}
}
// 执行搜索 - 优化版,参考废弃版方法修复搜索问题,保留1.5版本API和栏目检测功能
function 执行搜索(keyword) {
const 搜索关键词 = keyword.trim().toLowerCase();
let 匹配数量 = 0;
console.log(`开始搜索关键词: ${搜索关键词}`);
console.log(`当前栏目: ${currentSection}-${currentSubSection}(${totalCount})`);
// 首先清除所有高亮
清除所有高亮();
// 获取当前激活的标签面板 - 参考废弃版的直接DOM查找方式
let 活动面板 = null;
// 使用更直接的方式查找活动面板,参考废弃版代码
const 标签页区域 = document.querySelector('.ant-tabs-nav, .tabs-nav, [role="tablist"]');
if (标签页区域) {
// 找到活动标签
const 活动标签 = 标签页区域.querySelector('.ant-tabs-tab-active, [aria-selected="true"]');
if (活动标签) {
const 标签文本 = 活动标签.textContent.trim();
console.log(`当前活动标签: ${标签文本}`);
// 根据标签文本查找对应的面板
if (标签文本.includes('发布') || 标签文本.includes('文章')) {
活动面板 = document.querySelector('#rc-tabs-0-panel-PUBLISH, [data-tab="PUBLISH"]');
} else if (标签文本.includes('回答')) {
活动面板 = document.querySelector('#rc-tabs-0-panel-ANSWER, [data-tab="ANSWER"]');
} else if (标签文本.includes('提问') || 标签文本.includes('问题')) {
活动面板 = document.querySelector('#rc-tabs-0-panel-QUESTION, [data-tab="QUESTION"]');
} else if (标签文本.includes('收藏')) {
活动面板 = document.querySelector('#rc-tabs-0-panel-COLLECT, [data-tab="COLLECT"]');
}
}
}
// 如果通过标签找不到面板,尝试直接查找可见的面板
if (!活动面板) {
const 所有面板 = document.querySelectorAll('[role="tabpanel"], .ant-tabs-panel, [id*="panel"]');
for (const 面板 of 所有面板) {
const 样式 = window.getComputedStyle(面板);
if (样式.display !== 'none' && 面板.offsetParent !== null) {
活动面板 = 面板;
break;
}
}
}
// 如果还是找不到面板,使用fallback方法
if (!活动面板) {
活动面板 = document.querySelector('[role="main"], .user-center-content, .content-area') || document.body;
}
// 获取所有文章项 - 参考废弃版的有效选择器策略
let 所有文章项 = [];
// 如果搜索关键词为空,恢复显示所有内容
if (搜索关键词 === '') {
// 尝试多种选择器找到所有项目并显示
const 候选选择器 = [
'.list___18bDQ > div',
'.list_item___nmNeS',
'a[href*="/community/"]',
'div[role="tabpanel"] a',
'.qa-item, .article-item, .answer-item',
'[class*="item"]',
'[class*="list"] > div'
];
for (const 选择器 of 候选选择器) {
const 找到的项目 = 活动面板.querySelectorAll(选择器);
if (找到的项目.length > 0) {
找到的项目.forEach(item => {
item.style.display = '';
});
console.log(`使用选择器 ${选择器} 恢复了 ${找到的项目.length} 个项目`);
}
}
console.log('已显示所有内容');
显示搜索结果提示('已显示所有内容', true);
return;
}
// 使用废弃版的策略:优先使用高效的选择器
const 有效选择器 = [
'.list___18bDQ > div',
'.list_item___nmNeS'
];
for (const 选择器 of 有效选择器) {
所有文章项 = [...活动面板.querySelectorAll(选择器)];
if (所有文章项.length > 0) {
console.log(`使用选择器 ${选择器} 找到 ${所有文章项.length} 个项目`);
break;
}
}
// 如果主要选择器找不到,使用备用选择器
if (所有文章项.length === 0) {
const 备用选择器 = [
'a[href*="/community/"]',
'div[role="tabpanel"] a',
'.qa-item, .article-item, .answer-item',
'[class*="item"]',
'[class*="list"] > div'
];
for (const 选择器 of 备用选择器) {
所有文章项 = [...活动面板.querySelectorAll(选择器)];
if (所有文章项.length > 0) {
console.log(`备用选择器 ${选择器} 找到 ${所有文章项.length} 个项目`);
break;
}
}
}
console.log(`总共找到 ${所有文章项.length} 个内容项,开始搜索...`);
// 遍历所有内容项 - 参考废弃版的直接处理方式
所有文章项.forEach((item) => {
try {
// 先隐藏所有项,稍后显示匹配项
item.style.display = 'none';
// 获取内容项中的文本内容 - 使用更直接的方式
const 项内容 = item.textContent.toLowerCase();
// 搜索匹配项
if (项内容.includes(搜索关键词)) {
// 显示匹配项
item.style.display = '';
// 高亮匹配的关键词
高亮关键词(item, 搜索关键词);
匹配数量++;
} else {
// 清除高亮
清除高亮(item);
}
} catch (e) {
console.error('搜索处理单个项目失败:', e);
}
});
// 更新搜索结果计数和提示
console.log(`搜索完成,找到 ${匹配数量} 个匹配项`);
if (匹配数量 > 0) {
// 滚动到第一个结果
const 第一个可见结果 = 所有文章项.find(item => item.style.display !== 'none');
if (第一个可见结果) {
第一个可见结果.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
显示搜索结果提示(`找到 ${匹配数量} 条包含关键词 "${keyword}" 的内容`, true);
} else {
// 提供更详细的调试信息
const 调试信息 = {
活动面板: 活动面板 ? 活动面板.tagName + (活动面板.className ? '.' + 活动面板.className.split(' ').join('.') : '') : '未找到',
选择器尝试: 'list___18bDQ > div, list_item___nmNeS',
找到项目数: 所有文章项.length,
搜索关键词: 搜索关键词,
当前URL: window.location.href
};
console.log('搜索失败调试信息:', 调试信息);
显示搜索结果提示(`未找到包含关键词 "${keyword}" 的内容。\n\n调试信息:\n- 活动面板: ${调试信息.活动面板}\n- 找到项目数: ${调试信息.找到项目数}\n- 当前URL: ${调试信息.当前URL}`, false);
}
}
// 清除单个元素的高亮函数
function 清除高亮(element) {
try {
// 查找该元素内所有高亮span并清除
const highlightSpans = element.querySelectorAll('span[style*="background-color: rgb(255, 235, 59)"]');
highlightSpans.forEach(span => {
const parent = span.parentNode;
if (parent) {
// 将span的文本内容替换为文本节点
const textNode = document.createTextNode(span.textContent);
parent.replaceChild(textNode, span);
// 合并相邻的文本节点
parent.normalize();
}
});
} catch (e) {
console.error('清除单个元素高亮失败:', e);
}
}
// 高亮关键词函数 - 优化版,确保保留原有DOM结构和链接
function 高亮关键词(element, keyword) {
try {
// 先清除之前的高亮
清除高亮(element);
const 关键词转义 = 转义正则字符(keyword);
const 正则表达式 = new RegExp(`(${关键词转义})`, 'gi');
// 递归处理节点,只处理文本节点,保留原有DOM结构
function processNode(node) {
if (node.nodeType === 3) { // 文本节点
const text = node.textContent;
if (正则表达式.test(text)) {
const parent = node.parentNode;
const parts = text.split(正则表达式);
// 移除原文本节点
parent.removeChild(node);
// 重新构建节点内容
parts.forEach((part, index) => {
if (index % 2 === 1) { // 匹配的关键词部分
const highlightSpan = document.createElement('span');
highlightSpan.style.backgroundColor = 'rgb(255, 235, 59)';
highlightSpan.textContent = part;
parent.appendChild(highlightSpan);
} else if (part) { // 非关键词部分
parent.appendChild(document.createTextNode(part));
}
});
}
} else if (node.nodeType === 1 && node.tagName !== 'SPAN') { // 元素节点且不是高亮span
// 处理子节点
const children = Array.from(node.childNodes);
for (let i = 0; i < children.length; i++) {
processNode(children[i]);
}
}
}
// 开始处理
processNode(element);
} catch (e) {
console.error('高亮关键词失败:', e);
}
}
// 清除所有高亮函数 - 全局清除页面上所有的高亮元素
function 清除所有高亮() {
try {
// 获取页面上所有的高亮元素并清除
document.querySelectorAll('span[style*="background-color: rgb(255, 235, 59)"]').forEach(el => {
const 父节点 = el.parentNode;
if (父节点) {
父节点.replaceChild(document.createTextNode(el.textContent), el);
父节点.normalize();
}
});
console.log('已清除所有搜索高亮');
} catch (e) {
console.error('清除所有高亮失败:', e);
}
}
// 转义正则字符函数
function 转义正则字符(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
// 设置栏目监听
function 设置栏目监听() {
// 监听大栏目切换(发布/收藏)
const tabElements = document.querySelectorAll('.rc-tabs-tab');
tabElements.forEach(tab => {
tab.addEventListener('click', function() {
// 延迟执行,等待DOM更新
setTimeout(() => {
const tabKey = this.getAttribute('data-tab-key');
if (tabKey === 'PUBLISH' || tabKey === 'COLLECT') {
currentSection = tabKey;
// 立即更新控制台显示,提示用户已切换到哪个大栏目
console.log(`切换到大栏目: ${currentSection}`);
// 获取当前激活的子栏目
setTimeout(() => {
获取当前激活的子栏目();
更新栏目信息();
重置加载状态();
开始自动加载();
}, 500); // 额外延迟,确保子栏目已经渲染
}
}, 300);
});
});
// 添加MutationObserver监听大栏目切换,作为点击事件的补充
const tabsContent = document.querySelector('.rc-tabs-content');
if (tabsContent) {
const observer = new MutationObserver(mutations => {
for (const mutation of mutations) {
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
// 检查当前激活的面板
const activePanel = document.querySelector('.rc-tabs-tabpane-active');
if (activePanel) {
const panelId = activePanel.id;
if (panelId.includes('PUBLISH')) {
if (currentSection !== 'PUBLISH') {
currentSection = 'PUBLISH';
console.log(`检测到大栏目切换: ${currentSection}`);
获取当前激活的子栏目();
更新栏目信息();
}
} else if (panelId.includes('COLLECT')) {
if (currentSection !== 'COLLECT') {
currentSection = 'COLLECT';
console.log(`检测到大栏目切换: ${currentSection}`);
获取当前激活的子栏目();
更新栏目信息();
}
}
}
}
}
});
// 监听所有选项卡内容面板的class变化
const tabPanes = document.querySelectorAll('.rc-tabs-tabpane');
tabPanes.forEach(pane => {
observer.observe(pane, { attributes: true });
});
}
// 获取当前激活的子栏目
function 获取当前激活的子栏目() {
try {
// 查找所有可能的子栏目按钮
const allButtons = [];
// 发布栏目按钮
const publishButtons = document.evaluate(XPATHS.publishQuestion + ' | ' +
XPATHS.publishAnswer + ' | ' +
XPATHS.publishArticle,
document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
// 收藏栏目按钮
const collectButtons = document.evaluate(XPATHS.collectQa + ' | ' +
XPATHS.collectArticle,
document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
// 收集发布栏目按钮
for (let i = 0; i < publishButtons.snapshotLength; i++) {
allButtons.push(publishButtons.snapshotItem(i));
}
// 收集收藏栏目按钮
for (let i = 0; i < collectButtons.snapshotLength; i++) {
allButtons.push(collectButtons.snapshotItem(i));
}
// 查找激活状态的按钮
for (const button of allButtons) {
// 检查按钮是否有激活状态的样式或类
const classList = button.classList;
const parentClassList = button.parentNode ? button.parentNode.classList : [];
// 通常激活的按钮会有特定的样式或类名标记
if (classList.contains('active') ||
parentClassList.contains('active') ||
classList.contains('selected') ||
parentClassList.contains('selected') ||
button.style.color === 'rgb(59, 130, 246)' || // 假设激活状态是蓝色
button.style.fontWeight === 'bold') {
currentSubSection = button.textContent.trim();
console.log(`检测到当前激活子栏目: ${currentSubSection}`);
return;
}
}
// 如果没有找到激活的按钮,尝试根据当前显示的内容推断
if (document.querySelector('.answer-item')) {
currentSubSection = '回答';
} else if (document.querySelector('.qa-item')) {
currentSubSection = currentSection === 'PUBLISH' ? '提问' : '问答';
} else if (document.querySelector('.article-item')) {
currentSubSection = '文章';
}
console.log(`推断当前子栏目: ${currentSubSection}`);
} catch (e) {
console.error('获取当前激活子栏目失败:', e);
}
}
// 监听子栏目切换 - 优化版,确保覆盖所有栏目并正确显示当前状态
function 监听子栏目按钮() {
const buttons = [];
// 尝试获取所有可能的子栏目按钮
try {
// 发布栏目按钮
if (currentSection === 'PUBLISH') {
const questionBtn = document.evaluate(XPATHS.publishQuestion, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
const answerBtn = document.evaluate(XPATHS.publishAnswer, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
const articleBtn = document.evaluate(XPATHS.publishArticle, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
if (questionBtn) buttons.push(questionBtn);
if (answerBtn) buttons.push(answerBtn);
if (articleBtn) buttons.push(articleBtn);
}
// 收藏栏目按钮
else if (currentSection === 'COLLECT') {
const qaBtn = document.evaluate(XPATHS.collectQa, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
const articleBtn = document.evaluate(XPATHS.collectArticle, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
if (qaBtn) buttons.push(qaBtn);
if (articleBtn) buttons.push(articleBtn);
}
// 添加全局查找,确保不会遗漏任何子栏目按钮
const allSubSectionButtons = document.querySelectorAll('.menu-item___397g0');
allSubSectionButtons.forEach(btn => {
if (!buttons.includes(btn)) {
buttons.push(btn);
}
});
// 再次添加全局兜底方案,查找所有可能的按钮
const sectionButtons = document.querySelectorAll('.btn___N0geJ button, .btn-group button, .submenu button');
sectionButtons.forEach(btn => {
if (btn.textContent &&
(btn.textContent.includes('提问') ||
btn.textContent.includes('回答') ||
btn.textContent.includes('文章') ||
btn.textContent.includes('问答')) &&
!buttons.includes(btn)) {
buttons.push(btn);
}
});
} catch (e) {
console.error('获取子栏目按钮失败:', e);
}
// 为按钮添加点击事件
buttons.forEach(button => {
// 避免重复添加事件
if (!button.hasAttribute('data-listener-added')) {
button.setAttribute('data-listener-added', 'true');
button.addEventListener('click', function() {
const buttonText = this.textContent.trim();
currentSubSection = buttonText;
// 立即在控制台显示切换到的子栏目,使用明确的格式
console.log(`当前栏目: ${currentSection}-${currentSubSection}`);
// 根据不同栏目设置不同的初始延时
const 延时时间 = currentSubSection.includes('回答') ? 配置.回答栏目初始延时 : 配置.初始延时;
console.log(`栏目切换后等待 ${延时时间}ms 再开始加载`);
// 延迟执行,等待DOM更新
setTimeout(() => {
// 再次确认当前栏目信息
获取当前激活的子栏目();
// 确保在控制台显示最新的完整栏目信息,包括总数
更新栏目信息();
// 重置搜索状态,清除之前的搜索高亮
清除所有高亮();
// 重置加载状态
重置加载状态();
// 开始自动加载
开始自动加载();
}, 延时时间);
});
}
});
}
// 定期检查子栏目按钮
setInterval(监听子栏目按钮, 1000);
监听子栏目按钮(); // 立即执行一次
}
// 更新栏目信息
function 更新栏目信息() {
try {
let targetButton;
let sectionText = '';
// 根据当前栏目获取对应的按钮
if (currentSection === 'PUBLISH') {
sectionText = '发布';
if (currentSubSection.includes('提问')) {
targetButton = document.evaluate(XPATHS.publishQuestion, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
} else if (currentSubSection.includes('回答')) {
targetButton = document.evaluate(XPATHS.publishAnswer, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
} else if (currentSubSection.includes('文章')) {
targetButton = document.evaluate(XPATHS.publishArticle, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
}
} else if (currentSection === 'COLLECT') {
sectionText = '收藏';
if (currentSubSection.includes('问答')) {
targetButton = document.evaluate(XPATHS.collectQa, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
} else if (currentSubSection.includes('文章')) {
targetButton = document.evaluate(XPATHS.collectArticle, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
}
}
// 提取数量
if (targetButton) {
const text = targetButton.textContent;
const match = text.match(/\((\d+)\)/);
if (match && match[1]) {
totalCount = parseInt(match[1], 10);
// 确保控制台显示完整的栏目信息,使用统一格式
console.log(`当前栏目: ${currentSection}-${currentSubSection}(${totalCount})`);
return;
}
}
// 备用方案:尝试从其他位置获取总数
if (currentSection === 'COLLECT') {
// 对于收藏栏目,尝试查找其他可能包含总数的元素
const collectCountElements = document.querySelectorAll('.rc-tabs-tab[data-tab-key="COLLECT"]');
if (collectCountElements.length > 0) {
const text = collectCountElements[0].textContent;
const match = text.match(/\((\d+)\)/);
if (match && match[1]) {
totalCount = parseInt(match[1], 10);
// 确保控制台显示完整的栏目信息,使用统一格式
console.log(`当前栏目: ${currentSection}-${currentSubSection}(${totalCount})`);
return;
}
}
// 收藏栏目特定处理:尝试从当前活动的子栏目按钮获取数量
const activeSubSectionButtons = document.querySelectorAll(`#rc-tabs-0-panel-COLLECT .btn___N0geJ button`);
for (const button of activeSubSectionButtons) {
const text = button.textContent;
const match = text.match(/\((\d+)\)/);
if (match && match[1]) {
// 检查这个按钮是否是激活状态
if (button.classList.contains('active') ||
button.parentNode.classList.contains('active') ||
button.style.color === 'rgb(59, 130, 246)' ||
button.style.fontWeight === 'bold') {
totalCount = parseInt(match[1], 10);
console.log(`当前栏目: ${currentSection}-${currentSubSection}(${totalCount})`);
return;
}
}
}
}
// 如果无法获取数量,设置默认值
totalCount = 100; // 默认值
console.log(`无法获取栏目数量,使用默认值: ${totalCount}`);
// 仍然显示当前栏目信息,即使无法获取精确数量
console.log(`当前栏目: ${currentSection}-${currentSubSection}(~${totalCount})`);
} catch (e) {
console.error('更新栏目信息失败:', e);
totalCount = 100;
// 即使出错,也要确保控制台显示当前栏目信息
console.log(`当前栏目: ${currentSection}-${currentSubSection}(~${totalCount})`);
}
}
// 设置页面变化监听
function 设置页面变化监听() {
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
// 检查是否有新内容加载
if (mutation.addedNodes.length > 0) {
// 更新已加载数量
更新已加载数量();
// 检查是否需要继续加载
if (!isLoading && loadedCount < totalCount) {
检查并点击查看更多();
}
}
});
});
// 监听页面主体内容变化
const contentArea = document.querySelector('.rc-tabs-content');
if (contentArea) {
observer.observe(contentArea, {
childList: true,
subtree: true
});
}
}
// 更新已加载数量 - 优化版,确保与当前栏目正确绑定
function 更新已加载数量() {
try {
// 构建选择器,确保只统计当前活动面板中的内容
let selector = '';
if (currentSection === 'PUBLISH') {
// 只统计发布面板中的内容
selector = '#rc-tabs-0-panel-PUBLISH .article-item, ' +
'#rc-tabs-0-panel-PUBLISH .qa-item, ' +
'#rc-tabs-0-panel-PUBLISH .answer-item, ' +
'#rc-tabs-0-panel-PUBLISH .list_item___nmNeS, ' +
'#rc-tabs-0-panel-PUBLISH .list___18bDQ > div';
// 特别为回答栏目添加更精确的选择器
if (currentSubSection.includes('回答')) {
selector += ', #rc-tabs-0-panel-PUBLISH .answer-item, ' +
'#rc-tabs-0-panel-PUBLISH [class*="answer"].item, ' +
'#rc-tabs-0-panel-PUBLISH [data-type="answer"]';
}
} else if (currentSection === 'COLLECT') {
// 只统计收藏面板中的内容
selector = '#rc-tabs-0-panel-COLLECT .article-item, ' +
'#rc-tabs-0-panel-COLLECT .qa-item, ' +
'#rc-tabs-0-panel-COLLECT .answer-item, ' +
'#rc-tabs-0-panel-COLLECT .list_item___nmNeS, ' +
'#rc-tabs-0-panel-COLLECT .fav-item, ' +
'#rc-tabs-0-panel-COLLECT .collect-item, ' +
'#rc-tabs-0-panel-COLLECT .list___18bDQ > div';
}
// 获取当前面板中所有匹配的项目
const items = document.querySelectorAll(selector);
// 更新已加载数量
loadedCount = items.length;
// 在控制台显示详细信息,包括当前栏目和已加载数量
console.log(`当前栏目: ${currentSection}-${currentSubSection} | 已加载数量: ${loadedCount}/${totalCount}`);
} catch (e) {
console.error('更新已加载数量失败:', e);
}
}
// 重置加载状态
function 重置加载状态() {
isLoading = false;
loadedCount = 0;
retryCount = 0; // 重置重试计数
// 清除之前的定时器
if (loadInterval) {
clearInterval(loadInterval);
loadInterval = null;
}
}
// 开始自动加载
function 开始自动加载() {
// 重置重试计数
retryCount = 0;
// 先立即执行一次加载检查
检查并点击查看更多();
// 设置定时加载
loadInterval = setInterval(() => {
检查并点击查看更多();
}, 配置.检查间隔); // 使用配置的检查间隔
console.log(`开始自动加载,检查间隔:${配置.检查间隔}ms`);
}
// 检查并点击查看更多
function 检查并点击查看更多() {
// 如果已经在加载中,不重复触发
if (isLoading) return;
// 检查是否已达到总数量
if (loadedCount >= totalCount) {
console.log('已达到总数量,停止加载');
if (loadInterval) {
clearInterval(loadInterval);
loadInterval = null;
}
return;
}
try {
// 查找查看更多按钮 - 尝试多种选择器
let viewMoreButton = null;
// 1. 使用XPath选择器(原方案)
try {
viewMoreButton = document.evaluate(XPATHS.viewMore, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
} catch (xpathError) {
console.warn('XPath查找失败:', xpathError);
}
// 2. 备选方案:使用CSS选择器
if (!viewMoreButton) {
viewMoreButton = document.querySelector(".rc-tabs-tabpane-active span:contains('查看更多')") ||
document.querySelector("span:contains('查看更多')");
}
// 3. 备选方案:查找所有文本包含'查看更多'的元素
if (!viewMoreButton) {
const allSpans = document.querySelectorAll('span');
for (const span of allSpans) {
if (span.textContent && span.textContent.trim() === '查看更多') {
viewMoreButton = span;
break;
}
}
}
if (viewMoreButton) {
// 重置重试计数,因为找到了按钮
retryCount = 0;
isLoading = true;
console.log('点击"查看更多"按钮,加载更多内容...');
// 点击查看更多按钮
viewMoreButton.click();
// 设置智能延迟,避免服务器繁忙
setTimeout(() => {
isLoading = false;
// 点击后强制更新已加载数量
更新已加载数量();
}, 2000 + Math.random() * 1000); // 2-3秒随机延迟
} else {
// 增加重试计数
retryCount++;
// 根据当前栏目调整重试逻辑
const isAnswerSection = currentSubSection.includes('回答');
const maxRetriesForSection = isAnswerSection ? maxRetries * 2 : maxRetries;
console.log(`未找到"查看更多"按钮 (重试 ${retryCount}/${maxRetriesForSection})`);
// 对于回答栏目,增加更多的重试机会
if (retryCount >= maxRetriesForSection) {
console.log('达到最大重试次数,停止自动重试');
// 注意:不清除定时器,让定期检查继续运行
} else {
console.log(`将在 ${配置.重试间隔}ms 后再次尝试查找`);
}
}
} catch (e) {
console.error('点击查看更多失败:', e);
isLoading = false;
}
}
// 修改请求参数 - 保留此函数以确保兼容性
function 修改请求参数() {
try {
console.log('修改请求参数被调用,但已通过API拦截器处理');
// 获取当前栏目信息
const 栏目信息 = 获取当前栏目信息();
console.log('当前栏目信息:', 栏目信息);
// 这里可以添加特定栏目的处理逻辑
} catch (error) {
console.error('修改请求参数失败:', error);
}
}
// 启动脚本
setTimeout(() => {
初始化();
// 初始加载时获取当前激活的子栏目
setTimeout(() => {
获取当前激活的子栏目();
更新栏目信息();
}, 500);
}, 1000);
})();