您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Press Shift+Alt+Q to batch open links in the main list in a page.
// ==UserScript== // @name Page Flood // @namespace [email protected] // @match http://*/* // @match https://*/* // @grant none // @version 1.0 // @author [email protected] // @description Press Shift+Alt+Q to batch open links in the main list in a page. // ==/UserScript== main(); function main() { globalThis.PageFloodController?.abort(); const ac = (globalThis.PageFloodController = new AbortController()); window.addEventListener( "keydown", async (e) => { // e.altKey && getMainListLinks() if (e.shiftKey && e.altKey && e.code == "KeyQ") await openLinksInList(); }, { signal: ac.signal } ); } function openDeduplicatedUrl(url) { const opened = (globalThis.openDeduplicatedUrl_opened ??= new Set()); return opened.has(url) || (window.open(url, "_blank") && opened.add(url)); } async function openLinksInList() { return await openLinks(getMainListLinks()); } function $$(...args) { return [...document.querySelectorAll(...args)]; } function maxRect(rects) { return { left: Math.min(...rects.map((e) => e.left)), top: Math.min(...rects.map((e) => e.top)), right: Math.max(...rects.map((e) => e.right)), bottom: Math.max(...rects.map((e) => e.bottom)), }; } function area({ left, right, top, bottom }) { return (right - left) * (bottom - top); } function elpath(e, path = "") { return !e ? path.trim() : e.tagName.match(/^h\d$/i) ? e.tagName : elpath( e.parentElement, e.tagName + [...e.classList] .filter((e) => e.match(/^[a-z-]+$/)) .map((e) => "." + e) .join("") + " " + path ); } // const elpath = function elpath(e){return !e?'': (elpath(e.parentElement) + ' ' + e.tagName).trim('')} function getDuplicates(list) { return new Set( Object.entries(Object.groupBy(list, (e) => e)).flatMap(([text, list]) => text && list.length > 1 ? [text] : [] ) ); } function getExcludeFilter(set, fn) { return (elem) => !set.has(fn(elem)); } function removeDuplicateLinks(links) { return links.filter( getExcludeFilter( getDuplicates(links.map((e) => e.textContent)), (e) => e.href ) ); } function getLinkGroups() { return Object.groupBy( removeDuplicateLinks( $$("a").map((e) => (false && (e.style.background = "green"), e)) ), (e) => elpath(e) ); } function peekLog(e) { return console.log(e), e; } function groupEncolor([path, links]) { return ( ((color) => links.map((a) => false && (a.style.background = color)))( "#" + Math.random().toString(16).slice(2, 8).padStart(6, "0") + Math.floor(256 * 0.995 ** path.length) .toString(16) .padStart(2, "0") ), peekLog([path, links]) ); } function getLinksLists() { const compareFn = (fn) => (a, b) => fn(a) - fn(b); return [getLinkGroups()] .flatMap(Object.entries) .map(groupEncolor) .map(([path, list]) => ({ path, list, area: area(maxRect(list.map((a) => a.getBoundingClientRect()))), })) .toSorted(compareFn((e) => -e.area)); } function getMainListLinks() { return getLinksLists()[0].list.map( (e) => (false && (e.style.background = "yellow"), e) ); } async function openLinks(links) { // max 8 page on 1 origin once batch // max 16 page on all origin once batch const urlss = Object.values( Object.groupBy(links, (url, i) => String(Math.floor(i / 8))) ); for await (const urls of urlss) { urls.toReversed().map(openDeduplicatedUrl); await new Promise((r) => setTimeout(r, 1e3)); // 1s cd await new Promise((r) => document.addEventListener("visibilitychange", r, { once: true }) ); // wait for page visible } // await Promise.all(Object.entries(Object.groupBy(links, e => e.origin)).map(async ([origin, links]) => { // const urls = links.map(e => e.href) // const urlss = Object.values(Object.groupBy(urls, (url, i) => String(Math.floor(i / 8)))) // for await (const urls of urlss) { // urls.toReversed().map(openUrl) // await new Promise(r => setTimeout(r, 1e3)) // 1s cd // await new Promise(r => document.addEventListener("visibilitychange", r, { once: true })) // wait for page visible // } // })) } // getMainListLinks()