[SNOLAB] Alt + 123... Searching Results Links List Batch Open

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.

  1. // ==UserScript==
  2. // @name [SNOLAB] Alt + 123... Searching Results Links List Batch Open
  3. // @name:zh [雪星实验室] Alt + 123... 一键批量打开谷歌必应搜索的前2的n次方项搜索结果
  4. // @namespace snomiao@gmail.com
  5. // @version 1.0.3
  6. // @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.
  7. // @description:zh 快速了解一个领域用,在谷歌或必应的搜索页面 按 Alt+1 ...2,3,4... Alt+5 将会打开前2的n次方项的搜索结果,并复制打开的链接。目前支持:谷歌、必应、知乎。
  8. // @author snomiao
  9. // @match *://google.com/*
  10. // @match *://bing.com/*
  11. // @match *://youtube.com/*
  12. // @match *://zhihu.com/*
  13. // @match *://and-all-searching-results.com/*
  14. // @match *://*/*
  15. // @grant none
  16. // ==/UserScript==
  17.  
  18. const 最长共列阵输出 = (矩阵, a, b, x, y) =>
  19. !x || !y
  20. ? ''
  21. : a[x - 1] === b[y - 1]
  22. ? 最长共列阵输出(矩阵, a, b, x - 1, y - 1) + a[x - 1]
  23. : 矩阵[y][x - 1] > 矩阵[y - 1][x]
  24. ? 最长共列阵输出(矩阵, a, b, x - 1, y)
  25. : 最长共列阵输出(矩阵, a, b, x, y - 1);
  26. const 最长共列 = (a, b) => {
  27. const w = a.length,
  28. h = b.length;
  29. const m = Array(1 + h)
  30. .fill(0)
  31. .map(() => Array(1 + w).fill(0));
  32. for (let y = 0; y < h; y++)
  33. for (let x = 0; x < w; x++)
  34. m[1 + y][1 + x] =
  35. a[x] === b[y]
  36. ? m[y][x] + 1
  37. : Math.max(m[y][1 + x], m[1 + y][x]);
  38. false && console.table(m);
  39. return 最长共列阵输出(m, a, b, w, h);
  40. };
  41. const 元素特征列取 = (e) =>
  42. [...e.querySelectorAll('*')].map((e) => e?.tagName + e?.className);
  43. const 特征元素筛函数 = (e) =>
  44. !'style script span'.toUpperCase().split(' ').includes(e.tagName);
  45. const 元素列表强度 = (e) =>
  46. e.textContent.length *
  47. (e.children.length - 1) *
  48. [...e.children]
  49. .filter(特征元素筛函数)
  50. .map(元素特征列取)
  51. .map((_, i, a) => 最长共列(a[i], a[i + 1] || []))
  52. .reduce((前, 后) => + 后.length, 0);
  53. const 列元素列提取 = () =>
  54. [...document.querySelectorAll('div,dl,ul,ol,tbody,table,td')]
  55. .filter((e) => e.children.length > 1)
  56. .map((元素) => ({
  57. 元素,
  58. 强度: 元素列表强度(元素),
  59. 特征列: [...元素.children]
  60. .filter(特征元素筛函数)
  61. // .filter((e) => !["style", "script", "span"].includes(e.tagName))
  62. .map(元素特征列取),
  63. }))
  64. .sort((a, b) => -(a.强度 - b.强度));
  65. const 标链元素提取 = (e) =>
  66. e?.querySelector('dd,dt,h1,h2,h3,h4,h5,h6')?.querySelector('a') ||
  67. [...e?.querySelectorAll('a')]?.filter((e) =>
  68. e.querySelector('dd,dt,h1,h2,h3,h4,h5,h6')
  69. )?.[0] ||
  70. e?.querySelector('a');
  71. const 标链提取 = (元素) => ({
  72. 元素,
  73. 标题: 元素?.textContent?.replace(/\s+/g, ' ').trim(),
  74. 链接: 元素?.href,
  75. });
  76. const 子列父亲节点筛函数 = (eFa, i, a) =>
  77. !a.some((eSon, j) => i != j && eFa.元素.contains(eSon.元素));
  78. const 页主标链列提取 = () =>
  79. 列元素列提取()
  80. .filter(子列父亲节点筛函数)
  81. .filter((e, _, a) => e.强度 > a[0].强度 * 0.1) // 按最强者 10% 筛选
  82. .sort((a, b) => a.元素.offsetTop - b.元素.offsetTop) // 按垂直位置对比
  83. .filter(({ 元素, 强度, 特征列 }) => !console.log(元素, 强度, 特征列)) // 元素提取debug
  84. .map(({ 元素 }) => 元素) // 元素提取
  85. .flatMap((e) => [...e?.children]?.map?.(标链元素提取) || [])
  86. .filter((e) => e)
  87. .map(标链提取)
  88. .filter(({ 标题, 链接 }) => 标题)
  89. .filter(({ 标题, 链接 }) => 链接?.match?.(/^http/));
  90. const 文本复制 = (内容) => {
  91. const input = document.createElement('textarea');
  92. input.setAttribute('readonly', 'readonly');
  93. input.setAttribute('value', 内容);
  94. input.innerHTML = 内容;
  95. input.setAttribute('style', 'position: fixed; top:0; left:0;z-index: 9999');
  96. document.body.appendChild(input);
  97. input.select();
  98. input.setSelectionRange(0, input.value.length);
  99. if (document.execCommand('copy')) {
  100. document.execCommand('copy');
  101. console.log(`长度为${内容.length}的内容已复制`);
  102. } else {
  103. // alert(`长度为${内容.length}的内容复制失败,请检查浏览器配置,或在页面上先按一下键盘任意键解除剪贴板保护`);
  104. }
  105. document.body.removeChild(input);
  106. };
  107. const 已打开过的链接 = {};
  108. const 链接打开 = (链接) => {
  109. if (!已打开过的链接[链接]) {
  110. window.open(链接);
  111. }
  112. 已打开过的链接[链接] = 1;
  113. };
  114. const 链接列获取 = (数量 = undefined) => 页主标链列提取().slice(0, 数量);
  115. const md格式链接生成 = ({ 标题, 链接 }) => `- [${标题}](${链接})`;
  116. const 打开一定数量链接 = (数量) => {
  117. const 链接列 = 链接列获取(数量).reverse(); //在 chrome 下需要反过来才能让第1个链接先打开。。;
  118. 文本复制(链接列.map(md格式链接生成).join('\n\n'));
  119. 链接列.map(({ 链接 }) => 链接).map(链接打开);
  120. };
  121. window.addEventListener('keydown', (e) => {
  122. if (!e.ctrlKey && !e.shiftKey && e.altKey && e.key.match(/[1-9]/)) {
  123. const 打开数量 = 2 ** parseInt(e.key);
  124. 打开一定数量链接(打开数量);
  125. }
  126. });
  127. console.log('[谷歌一键打开前N项搜索结果] LOADED');
  128. // 链接列获取();