美人图 - 秀人
https://meirentu.club
分享者: tangle122 (12293)发布时间: 02/10 19:32
有三处修改
1.将原本滑动到最底部再加载下一页改为持续加载下一页
2.修复部分封面抓取失败的问题
3.增添实时搜索功能
感谢原作者:jianghubailei
{
"articleStyle": 2,
"customOrder": 0,
"enableJs": true,
"enabled": true,
"enabledCookieJar": true,
"header": "{\n \"User-Agent\": \"Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/120.0.0.0 Safari\/537.36\",\n \"Referer\": \"https:\/\/meirentu.club\/\"\n}",
"lastUpdateTime": 1769069467887,
"loadWithBaseUrl": true,
"ruleArticles": "li.i_list",
"ruleContent": "<!doctype html>\n<html lang=\"zh-CN\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n<title>{{@@h1@text}}<\/title>\n<style>\nbody {\n margin: 0;\n background: #000;\n color: #eee;\n font-family: sans-serif;\n}\n\n#statusBar {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n z-index: 999;\n background: rgba(0, 0, 0, 0.7);\n color: #aaa;\n padding: 4px 10px;\n font-size: 12px;\n text-align: center;\n backdrop-filter: blur(2px);\n pointer-events: none;\n}\n\n#imgList img {\n display: block;\n width: 100%;\n height: auto;\n margin: 0;\n}\n<\/style>\n<\/head>\n<body>\n\n<div id=\"statusBar\">加载中…<\/div>\n\n\n{{@@h1@all}}\n\n<div id=\"detail\">\n{{@@article@all}}\n{{@@class.item_info@all}}\n<\/div>\n\n\n<div id=\"imgList\"><\/div>\n\n<script>\n\/\/ === 配置 ===\nconst pageUrls = `{{@@class.page@a:not(.current)@href}}`\n .split('\\n')\n .map(s => s.trim())\n .filter(Boolean);\n\nlet allImages = []; \/\/ 所有已加载的图片URL\nlet pageImageCounts = []; \/\/ 每页图片数量,用于定位页码\nlet isLoading = false;\nlet currentPageIndex = 0; \/\/ 当前正在加载的页面索引\nconst maxRetry = 2;\nconst loadDelay = 100; \/\/ 页面组间的加载延迟(毫秒)\nconst batchSize = 5; \/\/ 每次加载的页面数量\n\n\/\/ === DOM ===\nconst imgList = document.getElementById('imgList');\nconst statusBar = document.getElementById('statusBar');\n\n\/\/ === 工具函数 ===\nfunction showStatus(text) {\n if (statusBar) statusBar.textContent = text;\n}\n\n\/\/ 获取某页图片(简化版,优先 iframe)\nasync function fetchPageImages(url) {\n return new Promise((resolve, reject) => {\n const iframe = document.createElement('iframe');\n iframe.style.display = 'none';\n const timeout = setTimeout(() => {\n cleanup();\n reject(new Error('超时'));\n }, 5000); \/\/ 缩短超时时间\n \n function cleanup() {\n clearTimeout(timeout);\n if (iframe.parentNode) iframe.parentNode.removeChild(iframe);\n }\n \n iframe.onload = () => {\n try {\n const doc = iframe.contentDocument;\n let imgs = doc.querySelectorAll('.content_left img') ||\n doc.querySelectorAll('.content img') ||\n doc.querySelectorAll('img');\n const urls = Array.from(imgs).map(i => i.src).filter(Boolean);\n cleanup();\n resolve(urls);\n } catch (e) {\n cleanup();\n reject(e);\n }\n };\n iframe.onerror = () => { cleanup(); reject(new Error('加载失败')); };\n iframe.src = url;\n document.body.appendChild(iframe);\n });\n}\n\n\/\/ 追加一页图片\nfunction appendPage(images) {\n images.forEach(src => {\n const img = document.createElement('img');\n img.src = src;\n img.loading = 'lazy';\n imgList.appendChild(img);\n });\n allImages.push(...images);\n pageImageCounts.push(images.length);\n}\n\n\/\/ 计算当前可视区域的图片索引\nfunction getCurrentImageIndex() {\n const imgs = imgList.querySelectorAll('img');\n if (imgs.length === 0) return -1;\n\n \/\/ 优先选\"中心点最接近视口垂直中心\"的图片\n let bestIndex = 0;\n let minDistance = Infinity;\n\n for (let i = 0; i < imgs.length; i++) {\n const rect = imgs[i].getBoundingClientRect();\n const centerY = rect.top + rect.height \/ 2;\n const viewportCenter = window.innerHeight \/ 2;\n const distance = Math.abs(centerY - viewportCenter);\n\n \/\/ 如果图片完全不可见,跳过(可选)\n if (rect.bottom < 0 || rect.top > window.innerHeight) {\n continue;\n }\n\n if (distance < minDistance) {\n minDistance = distance;\n bestIndex = i;\n }\n }\n\n return bestIndex;\n}\n\n\/\/ 根据图片索引计算所在页码\nfunction getPageInfo(imageIndex) {\n if (imageIndex < 0) return { pageNum: 0, imageInPage: 0 };\n let count = 0;\n for (let i = 0; i < pageImageCounts.length; i++) {\n if (imageIndex < count + pageImageCounts[i]) {\n return {\n pageNum: i + 1,\n imageInPage: imageIndex - count + 1\n };\n }\n count += pageImageCounts[i];\n }\n return { pageNum: pageImageCounts.length, imageInPage: pageImageCounts.at(-1) || 0 };\n}\n\n\/\/ 更新状态栏\nfunction updateStatusBar() {\n const idx = getCurrentImageIndex();\n if (idx === -1) return;\n \n const { pageNum, imageInPage } = getPageInfo(idx);\n const totalPages = pageUrls.length;\n const totalImages = allImages.length;\n \n showStatus(`[图片: ${idx + 1} \/ ${totalImages} | 页码: ${pageNum} \/ ${totalPages}]`);\n}\n\n\/\/ 批量加载多个页面\nasync function loadBatchPages(startIndex, count) {\n const endIndex = Math.min(startIndex + count, pageUrls.length);\n let successfulPages = 0;\n \n for (let i = startIndex; i < endIndex; i++) {\n const pageIndex = i;\n let retry = 0;\n let success = false;\n \n \/\/ 重试机制\n while (retry < maxRetry && !success) {\n try {\n showStatus(`正在加载 ${pageIndex + 1} \/ ${pageUrls.length} 页…`);\n const urls = await fetchPageImages(pageUrls[pageIndex]);\n if (urls.length === 0) {\n throw new Error('无图片');\n }\n appendPage(urls);\n successfulPages++;\n updateStatusBar(); \/\/ 每页加载后更新状态\n success = true;\n } catch (e) {\n retry++;\n if (retry >= maxRetry) {\n showStatus(`❌ 跳过第 ${pageIndex + 1} 页`);\n pageImageCounts.push(0); \/\/ 占位\n break;\n }\n await new Promise(r => setTimeout(r, 500)); \/\/ 重试延迟\n }\n }\n }\n \n return successfulPages;\n}\n\n\/\/ 自动加载所有页面(分批)\nasync function loadAllRemainingPages() {\n if (isLoading || currentPageIndex >= pageUrls.length) {\n return;\n }\n \n isLoading = true;\n \n try {\n \/\/ 分批加载页面\n while (currentPageIndex < pageUrls.length) {\n const remainingPages = pageUrls.length - currentPageIndex;\n const currentBatchSize = Math.min(batchSize, remainingPages);\n \n showStatus(`批量加载 ${currentPageIndex + 1}-${currentPageIndex + currentBatchSize} 页…`);\n \n \/\/ 加载当前批次\n await loadBatchPages(currentPageIndex, currentBatchSize);\n \n currentPageIndex += currentBatchSize;\n \n \/\/ 如果不是最后一页,添加短暂延迟\n if (currentPageIndex < pageUrls.length) {\n await new Promise(r => setTimeout(r, loadDelay));\n }\n }\n \n showStatus(`✅ 全部页面加载完成,共 ${allImages.length} 张图片`);\n } catch (error) {\n showStatus('❌ 加载过程中出现错误');\n console.error(error);\n } finally {\n isLoading = false;\n }\n}\n\n\/\/ === 初始化 ===\n(async () => {\n if (pageUrls.length === 0) {\n showStatus('⚠️ 未获取到分页');\n return;\n }\n \n try {\n showStatus(`开始加载,共 ${pageUrls.length} 页…`);\n \n \/\/ 立即加载第一页(不等待)\n showStatus('加载第 1 页…');\n const urls = await fetchPageImages(pageUrls[0]);\n appendPage(urls);\n currentPageIndex = 1; \/\/ 第一页已加载\n \n showStatus(`✅ 首页加载完成 (${urls.length}张图片)`);\n updateStatusBar();\n \n \/\/ 启动滚动监听(仅更新状态栏)\n window.addEventListener('scroll', updateStatusBar, { passive: true });\n \n \/\/ 立即开始加载剩余所有页面(分批)\n loadAllRemainingPages();\n \n } catch (e) {\n showStatus('❌ 首页加载失败');\n console.error(e);\n }\n})();\n<\/script>\n<\/body>\n<\/html>",
"ruleImage": "img@data-src||img@src",
"ruleLink": "a.0@href",
"ruleNextPage": ".current+a@href||a[aria-label=\"Next\"]@href",
"rulePubDate": "{{@@span.0@text}} {{@@span.1@text}}",
"ruleTitle": ".meta-title@text",
"singleUrl": false,
"sortUrl": "搜索::https:\/\/meirentu.club\/s\/{{source.getVariable()}}-1.html\n首页::\/\n热门精选::\/hots.html\nXiuRen秀人网::\/group\/XiuRen-1.html\nMFStar模范学院::\/group\/MFStar-1.html\nMiStar魅妍社::\/group\/MiStar-1.html\nMyGirl美媛馆::\/group\/MyGirl-1.html\nImiss爱蜜社::\/group\/Imiss-1.html\nBoLoli兔几盟::\/group\/BoLoli-1.html\nYouWu尤物馆::\/group\/YouWu-1.html\nUxing优星馆::\/group\/Uxing-1.html\nMiiTao蜜桃社::\/group\/MiiTao-1.html\nFeiLin嗲囡囡::\/group\/FeiLin-1.html\nWingS影私荟::\/group\/WingS-1.html\nTaste顽味生活::\/group\/Taste-1.html\nLeYuan星乐园::\/group\/LeYuan-1.html\nHuaYan花の颜::\/group\/HuaYan-1.html\nDKGirl御女郎::\/group\/DKGirl-1.html\nMintYe薄荷叶::\/group\/MintYe-1.html\nYouMi尤蜜荟::\/group\/YouMi-1.html\nCandy糖果画报::\/group\/Candy-1.html\nMTMeng模特联盟::\/group\/MTMeng-1.html\nMicat猫萌榜::\/group\/Micat-1.html\nHuaYang花漾::\/group\/HuaYang-1.html\nXingYan星颜社::\/group\/XingYan-1.html\nXiaoYu画语界::\/group\/XiaoYu-1.html",
"sourceGroup": "图",
"sourceIcon": "https:\/\/meirentu.club\/static\/img\/logo.png",
"sourceName": "美人图 - 秀人",
"sourceUrl": "https:\/\/meirentu.club "
}