您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
To quickly understand a field, press Alt+1 ...2,3,4...Alt+5 on the search page of Google or Bing to open the search results of the first 2 nth power items and copy the opened ones link. Currently supports: Google, Bing, Zhihu.
// ==UserScript== // @name [SNOLAB] Alt + 123... Searching Results Links List Batch Open // @name:zh [雪星实验室] Alt + 123... 一键批量打开谷歌必应搜索的前2的n次方项搜索结果 // @namespace https://userscript.snomiao.com/ // @version 1.1.0 // @description To quickly understand a field, press Alt+1 ...2,3,4...Alt+5 on the search page of Google or Bing to open the search results of the first 2 nth power items and copy the opened ones link. Currently supports: Google, Bing, Zhihu. // @description:zh 快速了解一个领域用,在谷歌或必应的搜索页面 按 Alt+1 ...2,3,4... Alt+5 将会打开前2的n次方项的搜索结果,并复制打开的链接。目前支持:谷歌、必应、知乎。 // @author [email protected] // @match *://google.com/* // @match *://bing.com/* // @match *://youtube.com/* // @match *://zhihu.com/* // @match *://and-all-searching-results.com/* // @match *://*/* // @grant none // @contributionURL https://snomiao.com/donate // @supportURL https://github.com/snomiao/userscript.js/issues // ==/UserScript== "use strict"; (() => { // ../node_modules/hotkey-mapper/dist/index.mjs var { keys } = Object; function mapObject(fn, obj) { if (arguments.length === 1) { return (_obj) => mapObject(fn, _obj); } let index = 0; const objKeys = keys(obj); const len = objKeys.length; const willReturn = {}; while (index < len) { const key = objKeys[index]; willReturn[key] = fn( obj[key], key, obj ); index++; } return willReturn; } var mapObjIndexed = mapObject; function hotkeyMapper(mapping, options) { const handler = (event) => { if (!event.key) throw new Error("Invalid KeyboardEvent"); if (!event.code) throw new Error("Invalid KeyboardEvent"); const key = event.key?.toLowerCase(); const code = event.code?.toLowerCase(); const simp = event.code?.replace(/^(?:Key|Digit|Numpad)/, "").toLowerCase(); const map = new Proxy(event, { get: (target2, p) => Boolean( { [`${key}Key`]: true, [`${code}Key`]: true, [`${simp}Key`]: true }[p] ?? target2[p] ) }); const mods = "meta+alt+shift+ctrl"; mapObjIndexed((fn, hotkey) => { const conds = `${mods}+${hotkey.toLowerCase()}`.replace(/win|command|search/, "meta").replace(/control/, "ctrl").split("+").map((key2) => key2.toLowerCase().trim()).map((k, i) => [k, i >= 4 === map[`${k}Key`]]); if (!Object.entries(Object.fromEntries(conds)).every(([, ok]) => ok)) return; event.stopPropagation?.(); event.preventDefault?.(); return fn(event); }, mapping); }; const target = options?.target ?? globalThis; target.addEventListener(options?.on ?? "keydown", handler, options); return function unload() { target.removeEventListener(options?.on ?? "keydown", handler, options); }; } // ../ts/$$.ts function $$(sel, el = document) { return [...el.querySelectorAll(sel)]; } // ../ts/LinksListBatchOpen.user.ts globalThis.llboUnload?.(); globalThis.llboUnload = main(); function main() { console.log("[Links List Batch Open] LOADED"); const linkAlreadyOpened = /* @__PURE__ */ new Set(); return hotkeyMapper( { "alt+1": () => openLinkByCount(2 ** 1), "alt+2": () => openLinkByCount(2 ** 2), "alt+3": () => openLinkByCount(2 ** 3), "alt+4": () => openLinkByCount(2 ** 4), "alt+5": () => openLinkByCount(2 ** 5), "alt+6": () => openLinkByCount(2 ** 6), "alt+7": () => openLinkByCount(2 ** 7), "alt+8": () => openLinkByCount(2 ** 8), "alt+9": () => openLinkByCount(2 ** 9), "alt+shift+1": () => tryCopyLinkByCount(2 ** 1), "alt+shift+2": () => tryCopyLinkByCount(2 ** 2), "alt+shift+3": () => tryCopyLinkByCount(2 ** 3), "alt+shift+4": () => tryCopyLinkByCount(2 ** 4), "alt+shift+5": () => tryCopyLinkByCount(2 ** 5), "alt+shift+6": () => tryCopyLinkByCount(2 ** 6), "alt+shift+7": () => tryCopyLinkByCount(2 ** 7), "alt+shift+8": () => tryCopyLinkByCount(2 ** 8), "alt+shi ft+9": () => tryCopyLinkByCount(2 ** 9) }, { capture: true, on: "keydown" } ); function linkOpen(link) { if (!linkAlreadyOpened.has(link)) { window.open(link); } linkAlreadyOpened.add(link); } function openLinkByCount(count = 1) { console.log("openLinkByCount", count); const links = getLinks(count); copyLinks(links); links.map((e) => e.link).reverse().map(linkOpen); } } function tryCopyLinkByCount(count = 1) { const links = getLinks(count); copyLinks(links); return links; } async function copyLinks(links) { const md = links.map(markdownLinksGenerate).join("\n\n"); alert("copied links: " + md); await navigator.clipboard.writeText(md); } function longestCommonSequenceMatrix(m, a, b, x, y) { const lcs = longestCommonSequenceMatrix; return !x || !y ? "" : a[x - 1] === b[y - 1] ? lcs(m, a, b, x - 1, y - 1) + a[x - 1] : m[y][x - 1] > m[y - 1][x] ? lcs(m, a, b, x - 1, y) : lcs(m, a, b, x, y - 1); } function longestCommonSequence(a, b) { const w = a.length, h = b.length; const m = Array(1 + h).fill(0).map(() => Array(1 + w).fill(0)); for (let y = 0; y < h; y++) for (let x = 0; x < w; x++) m[1 + y][1 + x] = a[x] === b[y] ? m[y][x] + 1 : Math.max(m[y][1 + x], m[1 + y][x]); return longestCommonSequenceMatrix(m, a, b, w, h); } function elementFeatureList(ele) { return [...ele.querySelectorAll("*")].map((e) => e?.tagName + e?.className); } function featureElementAsk(ele) { return !"style script span".toUpperCase().split(" ").includes(ele.tagName); } function elementListStrengh(ele) { return Math.log(1 + (ele.textContent || "").length) * (ele.children.length - 1) * [...ele.children].filter(featureElementAsk).map(elementFeatureList).map((_, i, a) => longestCommonSequence(a[i], a[i + 1] || [])).reduce((\u524D, \u540E) => \u524D + \u540E.length, 0); } function listElementList() { const elements = $$("div,dl,ul,ol,tbody,table,td"); const sorted = elements.filter((e) => e.children.length > 1).map((element) => { const children = [...element.children]; return { element, strength: elementListStrengh(element), featureList: children.filter(featureElementAsk).map(elementFeatureList) }; }); return sortBy((a) => -a.strength, sorted); } function titleLinkElementExtract(e) { return e?.querySelector("dd,dt,h1,h2,h3,h4,h5,h6")?.querySelector("a") || [...e?.querySelectorAll("a")]?.filter( (e2) => e2.querySelector("dd,dt,h1,h2,h3,h4,h5,h6") )?.[0] || e?.querySelector("a"); } function titleLinkExtract(element) { return { element, title: element?.textContent?.replace(/\s+/g, " ").trim(), link: element?.href }; } function pageMainTitleLinkListExtract() { const list = listElementList(); const filteredList = list.flatMap( (father, i, a) => a.some( (son, j) => i != j && father.element.contains(son.element) && son.strength > father.strength ) ? [] : [father] ).flatMap((e, _i, a) => e.strength > a[0].strength * 0.1 ? [e] : []); const sortedList = sortBy( (a) => a.element.offsetTop * window.outerWidth + a.element.offsetLeft, filteredList ); const result = sortedList.map(({ element }) => element).flatMap((e) => [...e?.children]?.map?.(titleLinkElementExtract) || []).flatMap((e) => e ? [e] : []).map(titleLinkExtract).flatMap((e) => e.title ? [e] : []).flatMap((e) => e.link?.match?.(/^http/) ? [e] : []); return result; } function getLinks(\u6570\u91CF = Infinity) { return pageMainTitleLinkListExtract().slice(0, \u6570\u91CF); } function markdownLinksGenerate({ title, link }) { return `- [${title}](${link})`; } function sortBy(sortFn, list) { if (arguments.length === 1) return (_list) => sortBy(sortFn, _list); const clone = [...list]; return clone.sort((a, b) => { const aSortResult = sortFn(a); const bSortResult = sortFn(b); if (aSortResult === bSortResult) return 0; return aSortResult < bSortResult ? -1 : 1; }); } })();