您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
支持国内主流搜索引擎的搜索结果快速预览(直达网页大纲)。只需点击搜索结果旁的小灯泡按钮,即可在右侧速览窗中快速查看目标网站所含的图片、链接、标题大纲、文本。
当前为
// ==UserScript== // @name 💡WebPreview - 信息直达 // @namespace https://ez118.github.io/ // @version 0.15 // @description 支持国内主流搜索引擎的搜索结果快速预览(直达网页大纲)。只需点击搜索结果旁的小灯泡按钮,即可在右侧速览窗中快速查看目标网站所含的图片、链接、标题大纲、文本。 // @author ZZY_WISU // @match https://*.bing.com/* // @match https://www.google.com/* // @match https://www.baidu.com/* // @match https://www.so.com/* // @match https://www.sogou.com/* // @connect * // @license GNU GPLv3 // @icon https://cn.bing.com/sa/simg/favicon-trans-bg-blue-mg.ico // @run-at document-end // @grant GM_xmlhttpRequest // @grant GM_download // @grant GM_registerMenuCommand // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @require https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js // ==/UserScript== /* ============================================= */ /** * 生成随机数 * @param len 长度 * @constructor */ function randomString(len) { len = len || 32; /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/ var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'; var maxPos = $chars.length; var pwd = ''; for (let i = 0; i < len; i++) { pwd += $chars.charAt(Math.floor(Math.random() * maxPos)); } return pwd; } /** * 标题元素 * @param tag 标签,h1 ==> 1 , h2 ==> 2 * @param title 标题 * @param level 层级 * @param id 随机生成的id * @constructor */ function TitleElement(tag, title, level, id) { this.tag = tag; this.title = title; this.level = level; this.id = id; } /* 是否是标题元素 */ function isTitleTag(tag) { if (tag.is("h1")) { return true } if (tag.is("h2")) { return true } if (tag.is("h3")) { return true } if (tag.is("h4")) { return true } if (tag.is("h5")) { return true } if (tag.is("h6")) { return true } if (tag.is("h7")) { return true } return false } /** * 生成大纲 * @param $articleContent 文章容器 * @constructor */ function getOutline($articleContent) { /** 全部元素 */ var $eles = $articleContent.find("*"); /** 标题元素列表 */ var titleElementArr = new Array(); /** 上一个元素 */ var preTitleElement = null; $.each($eles, function(index, item) { if (isTitleTag($(item))) { var id = randomString(20); var level = 1; var tag = parseInt($(item).get(0).tagName.replace('h', "").replace('H', "")); var title = $(item).text(); if (null != preTitleElement) { var tagPre = preTitleElement.tag; var levelPre = preTitleElement.level; if (tagPre > tag) { level = levelPre - 1; } else if (tagPre < tag) { level = levelPre + 1; } else { level = levelPre; } } if (title.trim().length > 0) { $(item).attr("id", id); var titleElement = new TitleElement(tag, title, level, id); titleElementArr.push(titleElement); preTitleElement = titleElement; } } }) console.log(titleElementArr); return titleElementArr; } /* ============================================= */ var ReaderFlag1 = false; /* 用于存储阅读器元素是否被创建 */ var ReaderFlag2 = false; /* 用于存储阅读器是否为开启状态 */ var VideoSupport = [ ["https://v.youku.com/v_show/*.html", "https://player.youku.com/embed/*"], ["https://v.qq.com/x/page/*.html", "http://v.qq.com/txp/iframe/player.html?vid=*"], ["https://www.bilibili.com/video/BV*/", "https://www.bilibili.com/blackboard/html5mobileplayer.html?bvid=*"], ["https://www.bilibili.com/video/av*/", "https://www.bilibili.com/blackboard/html5mobileplayer.html?aid=*"] ]; /* 用于存储阅读器支持直接播放视频的网站及其嵌入播放器代码 */ function stringToHtml(str) { var parser = new DOMParser(); var doc = parser.parseFromString(str, 'text/html'); return doc; } function mobileDevice(){ var info = navigator.userAgent; var isPhone = /mobile/i.test(info); return isPhone; } function runAsync(url,send_type,data_ry) { var p = new Promise((resolve, reject)=> { GM_xmlhttpRequest({ method: send_type, url: url, headers: {"Content-Type": "application/x-www-form-urlencoded;charset=utf-8"}, data: data_ry, onload: function(response){resolve(response.responseText);}, onerror: function(response){reject("请求失败");} }); }); return p; } function escapeHtml(str) { return str.replace(/[&<>"']/g, function(match) { switch (match) { case '&': //return '&'; return '&'; case '<': return '<'; case '>': return '>'; case '"': return '"'; case '\'': return '''; default: return ''; } }); } function JudgeVideoSupport(url) { var previewFlag = 0; /* 判断是否为支持预览视频的网站 */ for(let i = 0; i < VideoSupport.length; i ++){ if( url.includes( VideoSupport[i][0].split("*")[0] ) ){ return { "state":true, "data":i }; break; } } return { "state":false, "data":-1 }; } function getWebContents(txt) { var links; var images; var content; var outline; /* 获取所有链接 */ /*links = txt.match(/href\=\"(https?|http|ftp|file):\/\/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/g); for(let i = 0; i < links.length; i ++) { links[i] = links[i].replace("href=\"", ""); }*/ links = []; txt.replace(/<a [^>]*href=['"]([^'"]+)[^>]*>/g,function(match, capture){ links.push(capture); }); //console.log(links); /* 获取所有图片 */ //images = txt.match(/<img[^<>]*src=[\"]([^\"]+)[\"][^<>]*>/im); images = []; txt.replace(/<img [^>]*src=['"]([^'"]+)[^>]*>/g,function(match, capture){ images.push(capture); }); //console.log(images); /* 获取文本 */ content = txt.replace(/<\/div>/g, "</div>\n").replace(/<\/table>/g, "</table>\n") content = content.replace(/<\/h3>/g, "</h3>\n").replace(/<\/p>/g, "</p>\n") content = content.replace(/<\/li>/g, "</li>\n").replace(/<br>/g, "\n") content = content.replace(/<br\/>/g, "\n").replace(/<script(.*?)<\/script>/gis, "") content = content.replace(/<style(.*?)<\/style>/gis, "").replace(/<nav(.*?)<\/nav>/gis, ""); // 现在代码: //content = content.replace(/<(?!\/?a\b)[^>]+>/g, ''); /* 删除除了a以外的标签 */ content = content.replace(/<(?!\/?(a|img)\b)[^>]+>/g, ''); /* 删除除了a和img以外的标签 */ // 原先代码: //content = content.replace(/<[^>]+>/g, ""); /* 删除所有标签 */ //content = escapeHtml(content); /* 转义 */ var content_len = content.length; content = content.substring(0, content_len); const search_txt = [" ", " ", "\n\n", "\r\r", "\t\t", "\n\r\n\r", "\r\n\r\n", "\t\r\n"]; const replace_txt = ["", "", "", "", "", "", "", ""]; for (let i = 0; i < search_txt.length; i++) { content = content.split(search_txt[i]).join(replace_txt[i]); } content = content.replace(/\r\n/g,"<br/>").replace(/\n/g,"<br/>").replace(/<br\/><br\/><br\/>/g, ""); //console.log(content); outline = getOutline($(txt)); return {"link":links,"image":images,"content":content,"outline":outline}; } function openReader(url) { /* 打开阅读器 */ /* 判断阅读器元素是否已经被创建过 */ if (ReaderFlag1 != true) { /* 若元素不存在,则创建元素 */ let previewReader = document.createElement("div"); previewReader.setAttribute("class", "userscript-webPreviewReader"); previewReader.setAttribute("style", "display:block;"); previewReader.setAttribute("id", "userscript-webPreviewReader"); document.body.appendChild(previewReader); ReaderFlag1 = true; ReaderFlag2 = true; } else { /* 若存在,则显示元素 */ let previewReader = document.getElementById("userscript-webPreviewReader"); previewReader.setAttribute("style", "display:block;"); ReaderFlag2 = true; } /* 阅读器加载提示 */ var previewReader = document.getElementById("userscript-webPreviewReader"); previewReader.innerHTML = "<p style='font-size:22px;margin-top:33%;' align='center'>加载中...<br/><span>" + url + "</span></p>"; /* 判断当前链接是支持预览的视频网站,并作出对应处理 */ var SoN = JudgeVideoSupport(url); if(SoN.state == true){ /* 被支持的视频网站的处理 */ var origUrl = url; var frameUrl = ""; url = url.replace(VideoSupport[SoN.data][0].split("*")[0], ""); url = url + "?#"; url = url.split("#")[0].split("?")[0]; url = url.replace(VideoSupport[SoN.data][0].split("*")[1], ""); frameUrl = VideoSupport[SoN.data][1].replace("*", url); previewReader.innerHTML = ` <div id="FadeInContainer" style="display:none; height:100%;"> <button class="CloseButton" style="margin:5px;" onclick='this.parentNode.parentNode.setAttribute("style", "display:none;");'>关闭</button> <center style="height: calc(100% - 120px)"> <iframe id="videoFrame" style="min-height:300px;" src="` + frameUrl + `"></iframe> </center> <br> <a href="` + origUrl + `" class="link" id="GoToLink" target="_blank">在原网站中继续 ▶ </a><br/> <a href="` + frameUrl + `" class="link" id="GoToLink" target="_blank">在播放器中继续 🎦 </a> </div> `; /* 淡入 */ $("#FadeInContainer").fadeIn(700); } else { /* 普通网站的处理 */ runAsync(url, "GET", "").then((result)=>{ return result; }).then(function(result){ var rh; if (url.split("/")[2] == "blog.csdn.net"){ try{ result = stringToHtml(result).getElementById("article_content").innerHTML; }catch(e){} }else if (url.split("/")[2] == "zhuanlan.zhihu.com"){ try{ result = stringToHtml(result).getElementsByClass("Post-RichTextContainer")[0].innerHTML; }catch(e){} }else if (url.split("/")[2] == "jingyan.baidu.com"){ try{ result = stringToHtml(result).getElementById("format-exp").innerHTML; }catch(e){} }else if (url.split("/")[2] == "www.bilibili.com"){ try{ result = stringToHtml(result).getElementById("article-content").innerHTML; }catch(e){} } /* 用函数解析网页 */ let reslist = getWebContents(result); let linkhtml = "", imghtml = "", outlinehtml = ""; /* 处理链接列表 */ for(let i = 0; i < reslist.link.length; i ++){ let link_tmp = reslist.link[i]; if(/*link_tmp.includes("https://") || link_tmp.includes("http://")*/link_tmp.includes("//")){ linkhtml += "<a class='link' target='_blank' href='" + link_tmp + "'> 🔗 " + link_tmp + " </a><br>"; } } /* 处理图片列表 */ for(let i = 0; i < reslist.image.length; i ++){ imghtml += "<a href='" + reslist.image[i] + "' target='_blank'><img class='image' src='" + reslist.image[i] + "' onerror='this.remove()'/></a>"; } /* 处理大纲 */ for(let i = 0; i < reslist.outline.length; i ++){ let space = ""; for(let j = 1; j < reslist.outline[i].level; j ++){ space += "  "; } outlinehtml += space + "+ " + reslist.outline[i].title + "<br/>" } /* 将所有结果添加进阅读器,并显示 */ previewReader.innerHTML = ` <div id="FadeInContainer" style="display:none;"> <button class="CloseButton" onclick='this.parentNode.parentNode.setAttribute("style", "display:none;");'>关闭</button> <br> <br> <div class="ImageList" style="max-height:103px;"> <p class='ShowImgList' align='right' style='' onclick='this.parentNode.setAttribute("style", "");'>所有图片</p> ` + imghtml + ` </div> <div class="LinkList" style="max-height:286px;"> <p class='ShowImgList' align='right' style='' onclick='this.parentNode.setAttribute("style", "");'>所有链接</p> ` + linkhtml + ` </div> <div class="ImageList"> <b>大纲: </b><br/> ` + outlinehtml + ` </div> <div class="ContentShow"> <b>文本: </b> ` + reslist.content + ` </div> </div>`; /* 淡入 */ $("#FadeInContainer").fadeIn(250); }); } /* 执行结束 */ } (function() { 'use strict'; var url = window.location.href; var paths = url.split("/"); GM_addStyle(`.userscript-webPreviewBtn{ background:#FFF; padding:3px 13px; margin-left:5px; border-radius:10px; border:2px solid #555; cursor:pointer; } .userscript-webPreviewBtn:active{ background:#111; border:2px solid #AAA; } .userscript-webPreviewReader{ position:fixed; top:8%; right:10px; bottom:0px; z-index:9999; width:35%; height:calc(100% - 8%); min-width:350px; background:#FFF; color:#333; overflow:hidden; box-shadow:0px 2px 5px #000; border-radius:15px 15px 0px 0px; } .userscript-webPreviewReader img.error{ display:none; } .ShowImgList{ margin:0;padding:0;width:100%;cursor:pointer;color:#138AF1;user-select:none; } .image{ height:85px; margin-bottom:8px; margin-right:5px; border-radius:15px; object-fit:contain; max-width:calc(100% - 20px); } .link{ text-decoration:none; color:#001ba0; margin-left: 5px; } .link:hover{ text-decoration:underline; } .ImageList{ padding:10px; margin:5px; border:2px solid #f4effb; background:#f4effb; border-radius:15px; overflow:hidden; } .LinkList{ padding:10px; margin:5px; border:2px solid #f4f1f6; background:#f4f1f6; border-radius:15px; overflow:hidden; } .ContentShow{ padding:10px; margin:5px; border:2px solid #f2f2f2; background:#f2f2f2; border-radius:15px; } .ContentShow img{ max-width:90%!important; position:relative!important; top:0!important; left:0!important; } .ContentShow img::after{ content: ""; display: block; clear: both; } .CloseButton{ position:fixed; top:calc(8% + 5px); right:15px; background:#FFF; color:#000; padding:3px 13px; margin:5px 5px; margin-bottom:0px; border-radius:10px; border:2px solid #555; cursor:pointer; } .CloseButton:hover{ background:#138AF1; border:2px solid #106ebe; color:#FFF; } #videoFrame{ width: calc(100% - 10px); height: calc(100% - 0px); border:1px solid #CCC; border-radius:15px; } #FadeInContainer { overflow-y:auto; overflow-x:hidden; border-radius:15px 15px 0px 0px; width:100%; height:100%; } `); if (paths[2].includes("bing.com") && paths[3].includes("search")) { let resultItems = document.getElementsByClassName("b_algo"); for(let i = 0; i < resultItems.length; i ++) { let resultItemLink = resultItems[i].getElementsByTagName("a")[0].href; let resultItemTitleEle = resultItems[i].getElementsByTagName("h2")[0]; /* 向每一个搜索结果的标题部分添加按钮 */ let previewBtn = document.createElement("button"); let previewBtnTxt = document.createTextNode("💡"); previewBtn.setAttribute("class", "userscript-webPreviewBtn"); previewBtn.setAttribute("link-data", resultItemLink); previewBtn.appendChild(previewBtnTxt); /* 适配必应手机网页 */ if(mobileDevice()){ resultItemTitleEle.parentNode.parentNode.appendChild(previewBtn); } else { resultItemTitleEle.appendChild(previewBtn); } previewBtn.addEventListener("click", function(evt){ let linkData = previewBtn.getAttribute("link-data"); openReader(linkData); }, true); } } else if (paths[2].includes("google.com")) { let resultItems = document.getElementsByClassName("MjjYud"); for(let i = 0; i < resultItems.length; i ++) { try{ let resultItemLink = resultItems[i].getElementsByTagName("a")[1].getAttribute("href"); let resultItemTitleEle = resultItems[i].getElementsByTagName("h3")[0]; if(resultItemLink == null || resultItemLink == "" || resultItemLink == undefined){ continue; } /* 向每一个搜索结果的标题部分添加按钮 */ let previewBtn = document.createElement("button"); let previewBtnTxt = document.createTextNode("💡"); previewBtn.setAttribute("class", "userscript-webPreviewBtn"); previewBtn.setAttribute("link-data", resultItemLink); resultItemTitleEle.parentNode.parentNode.appendChild(previewBtn); previewBtn.appendChild(previewBtnTxt); previewBtn.addEventListener("click", function(evt){ let linkData = previewBtn.getAttribute("link-data"); openReader(linkData); }, true); } catch(e) { console.log("[ERROR] ELE(" + i + ")"); } } } else if (paths[2].includes("baidu.com") && paths[3].includes("s?")) { let resultItems = document.getElementsByClassName("c-container"); //let resultItems = document.getElementsByClassName("c-container new-pmd"); for(let i = 0; i < resultItems.length; i ++) { try{ let resultItemLink = resultItems[i].getAttribute("mu"); let resultItemTitleEle = resultItems[i].getElementsByTagName("h3")[0]; if(resultItemLink == null || resultItemLink == "" || resultItemLink == undefined){ continue; } /* 向每一个搜索结果的标题部分添加按钮 */ let previewBtn = document.createElement("button"); let previewBtnTxt = document.createTextNode("💡"); previewBtn.setAttribute("class", "userscript-webPreviewBtn"); previewBtn.setAttribute("link-data", resultItemLink); resultItemTitleEle.appendChild(previewBtn); previewBtn.appendChild(previewBtnTxt); previewBtn.addEventListener("click", function(evt){ let linkData = previewBtn.getAttribute("link-data"); openReader(linkData); }, true); } catch(e) { console.log("[ERROR] ELE(" + i + ")"); } } } else if (paths[2].includes("so.com") && paths[3].includes("s?")) { let resultItems = document.getElementsByClassName("res-list"); for(let i = 0; i < resultItems.length; i ++) { try{ let resultItemLink = resultItems[i].getElementsByTagName("a")[0].getAttribute("data-mdurl"); let resultItemTitleEle = resultItems[i].getElementsByTagName("h3")[0]; /* 向每一个搜索结果的标题部分添加按钮 */ let previewBtn = document.createElement("button"); let previewBtnTxt = document.createTextNode("💡"); previewBtn.setAttribute("class", "userscript-webPreviewBtn"); previewBtn.setAttribute("link-data", resultItemLink); resultItemTitleEle.appendChild(previewBtn); previewBtn.appendChild(previewBtnTxt); previewBtn.addEventListener("click", function(evt){ let linkData = previewBtn.getAttribute("link-data"); openReader(linkData); }, true); } catch(e) { console.log("[ERROR] ELE(" + i + ") \n" + e); } } } else if (paths[2].includes("sogou.com")) { let resultItems = document.getElementsByClassName("vrwrap"); for(let i = 0; i < resultItems.length; i ++) { try{ let resultItemLink = resultItems[i].getElementsByClassName("ext_query")[0].getAttribute("data-url"); let resultItemTitleEle = resultItems[i].getElementsByTagName("h3")[0]; /* 向每一个搜索结果的标题部分添加按钮 */ let previewBtn = document.createElement("button"); let previewBtnTxt = document.createTextNode("💡"); previewBtn.setAttribute("class", "userscript-webPreviewBtn"); previewBtn.setAttribute("link-data", resultItemLink); resultItemTitleEle.appendChild(previewBtn); previewBtn.appendChild(previewBtnTxt); previewBtn.addEventListener("click", function(evt){ let linkData = previewBtn.getAttribute("link-data"); openReader(linkData); }, true); } catch(e) { console.log("[ERROR] ELE(" + i + ")"); } } } })();