可设置翻页数。已适配起点小说、小说狂人、自我小说、全本小说、17k小说、纵横小说。暂未适配:刺猬猫、番茄、69书吧、独阅读、百度读书、晋江、有毒、少年梦、不可能文学。陆续添加支持(咕咕咕)。
当前为
// ==UserScript==
// @name 小说自动翻页
// @version 1.0
// @description 可设置翻页数。已适配起点小说、小说狂人、自我小说、全本小说、17k小说、纵横小说。暂未适配:刺猬猫、番茄、69书吧、独阅读、百度读书、晋江、有毒、少年梦、不可能文学。陆续添加支持(咕咕咕)。
//
//
// @match *://www.qidian.com/chapter/*
// @match *://czbooks.net/n/*
// @match *://www.uuzw.cc/*
// @match *://www.quanben-xiaoshuo.com/*
// @match *://www.quanben.io/n/*
// @match *://www.17k.com/chapter/*
// @match *://read.zongheng.com/chapter/*
//
//
//
//
// @match1 *://www.qidiantu.com/booklists/*
// @match1 *://fanqienovel.com/reader/*
// @match1 *://www.ciweimao.com/chapter/*
// @match1 *://www.69shuba.com/txt/*
// @match1 *://dushu.baidu.com/pc/reader?gid=*
// @match1 *://www.cddaoyue.cn/chapter/book_chapter_detail/*
// @match1 *://www.jjwxc.net/onebook.php?novelid=*
// @match1 *://*:1122/*
// @match1 *://github.com/*
// @match1 *://www.google.com/*
// @match1 *://www.youdubook.com/bookread
// @match1 *://www.shaoniandream.com/readchapter/*
// @match1 *://wenxue.bkneng.com/www/book/read/*
//
// @namespace https://greatest.deepsurf.us/users/1171320
// @author yzcjd
// @author 1 ChatGPT4辅助
// @grant GM_registerMenuCommand
// @grant GM_getValue
// @grant GM_setValue
// @run-at document-end
// @license MIT
// ==/UserScript==
(function () {
'use strict';
// ====== 配置项 ======
const contentSelector = 'main, article, .content, .post, #content, .article, .article-content';
const includeKeywords = ['下一页', '下页', '下一章', '后页', 'continue', 'next', 'more', '›', '>>'];
const excludeKeywords = ['首页', '尾页', 'first', 'last', 'top', 'bottom', '1'];
const defaultPreloadPages = 10;
let preloadPages = GM_getValue('preloadCount', defaultPreloadPages);
const loadedURLs = new Set();
let isLoading = false;
let lastChapterURL = null;
let originalTitle = document.title;
const queue = []; // 明确按顺序推进的队列
// ====== 菜单 ======
GM_registerMenuCommand('页数', async () => {
const val = prompt('预加载页数(建议≤20):', preloadPages);
const n = parseInt(val);
if (n > 0 && n <= 100) {
GM_setValue('preloadCount', n);
alert('设置成功,刷新页面生效');
} else {
alert('超100!不会崩溃,但还是警告一下。');
}
});
// ====== 工具函数 ======
const sleep = ms => new Promise(res => setTimeout(res, ms));
const rand = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
const getContentContainer = () => document.querySelector(contentSelector);
const getScrollRatio = () => (window.scrollY + window.innerHeight) / document.documentElement.scrollHeight;
function isNextPageElement(el) {
const text = (el.textContent || '').trim().toLowerCase();
return includeKeywords.some(k => text.includes(k)) &&
!excludeKeywords.some(k => text.includes(k));
}
function findNextPageUrl(doc) {
const all = Array.from(doc.querySelectorAll('a'));
for (const a of all) {
if (a.href && isNextPageElement(a)) {
return new URL(a.href, location.href).href;
}
}
const match = doc.URL.match(/([?&\/\-_\.](page|p)?[=\/\-_]?)(\d{1,4})(?=[^\d]|$)/i);
if (match) {
const prefix = match[1];
const pageNum = parseInt(match[3]);
return doc.URL.replace(match[0], prefix + (pageNum + 1));
}
return null;
}
async function fetchAndInsertPage(url) {
if (!url || loadedURLs.has(url)) return null;
try {
isLoading = true;
console.log('[FETCH]', url);
const res = await fetch(url, { credentials: 'include' });
const html = await res.text();
const doc = new DOMParser().parseFromString(html, 'text/html');
const content = doc.querySelector(contentSelector);
if (content) {
const wrapper = document.createElement('div');
wrapper.style.opacity = '0';
wrapper.style.transition = 'opacity 0.6s';
wrapper.appendChild(content.cloneNode(true));
const container = getContentContainer();
if (container) {
container.appendChild(document.createElement('hr'));
container.appendChild(wrapper);
requestAnimationFrame(() => (wrapper.style.opacity = '1'));
}
loadedURLs.add(url);
lastChapterURL = url;
document.title = originalTitle;
return findNextPageUrl(doc);
} else {
console.warn('[未找到正文]', url);
}
} catch (e) {
console.warn('[加载失败]', url, e);
} finally {
isLoading = false;
}
return null;
}
// ====== 队列顺序推进加载 ======
async function processQueue() {
while (queue.length > 0 && queue.length <= preloadPages && !isLoading) {
const next = queue[0]; // 只取第一个,保证顺序
await sleep(rand(1000, 1200));
const nextUrl = await fetchAndInsertPage(next);
queue.shift(); // 当前加载完成后移除
if (nextUrl && !loadedURLs.has(nextUrl)) {
queue.push(nextUrl); // 按顺序推进
}
}
}
// ====== 滚动触发检查队列是否需要推进 ======
function handleScroll() {
if (getScrollRatio() > 0.9 && queue.length < preloadPages) {
processQueue();
}
}
// ====== 主程序入口 ======
async function main() {
const firstUrl = findNextPageUrl(document);
if (firstUrl) queue.push(firstUrl);
window.addEventListener('scroll', handleScroll);
processQueue();
window.addEventListener('beforeunload', () => {
if (lastChapterURL) {
localStorage.setItem('autopager:lastURL', lastChapterURL);
console.log('[保存记录]', lastChapterURL);
}
});
}
main();
})();