搜索引擎一键切换 soTab

在常用的搜索引擎页面中添加互相切换的按钮,包括图片、视频、知道、学术搜索。

  1. // ==UserScript==
  2. // @name soTab - Search Engine Switcher
  3. // @name:zh-CN 搜索引擎一键切换 soTab
  4. // @name:zh-TW 搜索引擎壹鍵切換 soTab
  5. // @description Add links to each other in search engines. Including multiple search modes.
  6. // @description:zh-CN 在常用的搜索引擎页面中添加互相切换的按钮,包括图片、视频、知道、学术搜索。
  7. // @description:zh-TW 在常用的搜索引擎頁面中添加互相切換的按鈕,包括圖片、視頻、知道、學術搜索。
  8.  
  9. // @author Moshel
  10. // @namespace http://hzy.pw
  11. // @homepageURL http://hzy.pw/p/1849
  12. // @supportURL https://github.com/h2y/link-fix
  13. // @icon http://q.qlogo.cn/qqapp/100229475/F1260A6CECA521F6BE517A08C4294D8A/100
  14. // @license GPL-3.0
  15.  
  16. // @match *.baidu.com/*
  17. // @exclude *.baidu.com/link?*
  18. // @match *.so.com/*
  19. // @match *.bing.com/*
  20. // @match *.zhihu.com/search?*
  21. // @match *.soku.com/*
  22. // @match *.sogou.com/*
  23. // @match https://*.google.com/*
  24. // @match https://*.google.com.hk/*
  25. // @grant GM_addStyle
  26. // @grant window.onurlchange
  27. // @run-at document_end
  28.  
  29.  
  30. // @date 11/25/2022
  31. // @modified 12/18/2022
  32. // @version 1.5.2.00
  33. // ==/UserScript==
  34. (function () {
  35. function soTabInit() {
  36. if (top !== window) {
  37. console.log('soTab! not top window');
  38. return;
  39. }
  40.  
  41. // 判断搜索引擎,将仅使用hostname适配
  42. const sites = [
  43. 'baidu',
  44. 'bing',
  45. 'so.com',
  46. '',
  47. 'zhihu',
  48. 'google',
  49. 'soku',
  50. 'sogou',
  51. ];
  52. const sitesName = [
  53. '百度',
  54. '必应',
  55. '好搜',
  56. 'ALLSO',
  57. '知乎',
  58. '谷歌',
  59. '搜库',
  60. '搜狗',
  61. ];
  62. let siteID = -1;
  63.  
  64. for (const site of sites) {
  65. if (site && location.hostname.includes(site)) {
  66. siteID = sites.indexOf(site);
  67. break;
  68. }
  69. }
  70.  
  71. if (siteID === -1) {
  72. console.log("soTab can't match site.");
  73. return;
  74. }
  75.  
  76. // 判断搜索类型,使用href适配
  77. let kind = [];
  78. // eslint-disable-next-line default-case
  79. switch (siteID) {
  80. case 0:
  81. kind = [
  82. 'www.baidu',
  83. 'image.baidu',
  84. 'zhidao.baidu.com/search',
  85. 'v.baidu',
  86. 'xueshu.baidu.com/s',
  87. ];
  88. break;
  89. case 1: // bing
  90. kind = [
  91. '.com/search',
  92. '.com/images',
  93. '.com/knows/search',
  94. '.com/videos',
  95. '/academic/search',
  96. ];
  97. break;
  98. case 2:
  99. kind = [
  100. 'www.so',
  101. 'image.so',
  102. 'wenda.so.com/search',
  103. 'video.so',
  104. ];
  105. break;
  106. case 4: // zhihu
  107. kind = ['', '', '.com/search'];
  108. break;
  109. case 5: // google
  110. kind = ['', 'tbm=isch', '', 'tbm=vid', 'scholar.google'];
  111. break;
  112. case 6:
  113. // kind[3] = "soku";
  114. break;
  115. case 7: // sogou
  116. kind = [
  117. ['/web?', '/sogou?', 'weixin.sogou', 'english.sogou'],
  118. 'pic.sogou',
  119. [
  120. 'interation=196636',
  121. 'mingyi.sogou',
  122. 'wenwen.sogou',
  123. '.com/zhihu',
  124. ],
  125. 'v.sogou',
  126. '.com/xueshu',
  127. ];
  128. break;
  129. }
  130. // 0:normal 1:pic 2:zhidao 3:video 4:xueshu
  131. let kindID = -1;
  132. for (let i = 0; i < kind.length; i++) {
  133. if (Array.isArray(kind[i])) {
  134. // 数组形式
  135. for (let j = 0; j < kind[i].length; j++) {
  136. if (location.href.includes(kind[i][j])) {
  137. kindID = i;
  138. break;
  139. }
  140. }
  141. if (kindID !== -1) break;
  142. } else if (location.href.indexOf(kind[i]) >= 0) {
  143. kindID = i;
  144. break;
  145. }
  146. }
  147. // 谷歌特殊处理
  148. if (siteID === 5 && kindID === -1) {
  149. if (location.href.indexOf('q=') >= 0) kindID = 0;
  150. }
  151. if (kindID === -1) {
  152. console.log('soTab! no kind found');
  153. return;
  154. }
  155.  
  156. // 初始化搜索路径
  157. // "百度", "必应", "好搜", "ALLSO", "知乎", "谷歌", "搜库", "搜狗"
  158. let links = []; // link[siteID]
  159. if (kindID === 0) {
  160. // normal
  161. links = [
  162. 'https://www.baidu.com/s?wd=',
  163. 'https://cn.bing.com/search?q=',
  164. 'https://www.so.com/s?q=',
  165. 'http://h2y.github.io/allso/#',
  166. '',
  167. 'https://www.google.com/search?q=',
  168. '',
  169. 'https://www.sogou.com/web?query=',
  170. ];
  171. } else if (kindID === 1) {
  172. // pic
  173. links = [
  174. 'https://image.baidu.com/search/index?tn=baiduimage&word=',
  175. 'https://cn.bing.com/images/search?q=',
  176. 'https://image.so.com/i?q=',
  177. '',
  178. '',
  179. 'https://www.google.com/search?tbm=isch&q=',
  180. ];
  181. } else if (kindID === 2) {
  182. // zhidao
  183. links = [
  184. 'https://zhidao.baidu.com/search?word=',
  185. 'https://cn.bing.com/knows/search?q=',
  186. '',
  187. '',
  188. 'https://www.zhihu.com/search?q=',
  189. '',
  190. '',
  191. 'http://www.sogou.com/sogou?interation=196636&query=',
  192. ];
  193. } else if (kindID === 3) {
  194. // video
  195. links = [
  196. 'https://v.baidu.com/v?ie=utf-8&word=',
  197. '',
  198. 'https://video.so.com/v?q=',
  199. '',
  200. '',
  201. 'https://www.google.com/search?tbm=vid&q=',
  202. 'https://www.soku.com/v?keyword=',
  203. ];
  204. } else if (kindID === 4) {
  205. // xueshu
  206. links = [
  207. 'https://xueshu.baidu.com/s?wd=',
  208. 'https://cn.bing.com/academic/search?q=',
  209. '',
  210. '',
  211. '',
  212. 'https://scholar.google.com/scholar?q=',
  213. ];
  214. }
  215.  
  216. // 从url的searchParams中获取搜索关键词
  217. const searchParams = new URLSearchParams(location.search);
  218. const searchKeyWords = ['wd', 'word', 'w', 'q', 'query', 'search'];
  219. let searchWords = '';
  220. searchKeyWords.forEach((keyWord) => {
  221. if (searchParams.has(keyWord)) {
  222. let initialWords = searchParams.get(keyWord);
  223. searchWords = encodeURIComponent(initialWords);
  224. }
  225. });
  226.  
  227. // 加载css
  228.  
  229. const styleText = `
  230. .soTab {
  231. position: fixed;
  232. background-color: #000;
  233. opacity: 0.3;
  234. border-radius: 40px;
  235. color: #fff;
  236. padding: 15px 20px;
  237. bottom: 100px;
  238. height: 40px;
  239. left: -320px;
  240. width: 300px;
  241. z-index: 9999999;
  242. transition: all 400ms;
  243. font-size: 14px;
  244. }
  245. .soTab:hover {
  246. left: 0px;
  247. opacity: 1;
  248. border-radius: 10px;
  249. box-shadow: 5px -5px 10px #777;
  250. }
  251. .soTab p {
  252. margin: 0;
  253. }
  254. p.soTab_title {
  255. font-weight: bold;
  256. margin-bottom: 3px;
  257. }
  258. .soTab a {
  259. color: #0cf;
  260. margin-right: 25px;
  261. }
  262.  
  263. `;
  264. // 生成切换框
  265. const bodyDOM = document.getElementsByTagName('body')[0];
  266. const soTabPanelDOM = document.createElement('div');
  267. soTabPanelDOM.id = 'soTab';
  268. let str = "<p class='soTab_title'>soTab 一键切换引擎:</p><p>";
  269. for (const link of links) {
  270. if (link && links.indexOf(link) !== siteID) {
  271. str += `<a href='${link}${searchWords}' target='_blank'>${sitesName[links.indexOf(link)]}</a>`;
  272. }
  273. }
  274.  
  275. soTabPanelDOM.innerHTML = `${str}</p>`;
  276. soTabPanelDOM.className = `b_soTab soTab soTab_site${siteID} soTab_kind${kindID}`;// b_必须放在className首位,否则bing会监听增加的DOM并删除增加的元素
  277. const oldSoTabDOM = document.getElementById('soTab');
  278. if (oldSoTabDOM) {
  279. oldSoTabDOM.remove();
  280. }
  281. const style = GM_addStyle(styleText);
  282. style.dataset.for = "result"; // 给style标签加上data-for= "result"属性,防止被百度删除
  283. bodyDOM.prepend(soTabPanelDOM);// 将dom添加到body前面,防止被百度和BING删除
  284. }
  285. if (window.onurlchange === null) {
  286. // feature is supported
  287. window.addEventListener('urlchange', () => {
  288. console.log('url has changed');
  289. soTabInit();
  290. });
  291. }
  292. if (top === window) {
  293. console.log('init sotab here');
  294. soTabInit();
  295. }
  296. }()); // end userScript

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址