// ==UserScript== // @name batterlink // @namespace http://batterlink.net/ // @version 0.1.2 // @description 从搜索内容中提取第一个URL并直接跳转(忽略其他文本) // @author orangehero // @match https://www.google.com/* // @match https://www.google.com.hk/* // @match https://www.baidu.com/* // @match https://m.baidu.com/* // @match https://cn.bing.com/* // @match https://www.bing.com/* // @match https://duckduckgo.com/* // @match https://www.sogou.com/* // @match https://www.so.com/* // @icon data:image/x-icon;base64,AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAAMMOAADDDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACIAAACeAAAA5QAAAPkAAADWAAAAeQAAAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABDAAAA8QAAAP8AAAD/AAAA/wAAAP8AAAD/AAAAzAAAABUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAPYAAAD/AAAAswAAADIAAAAVAAAAUAAAAN4AAAD/AAAA0wAAABUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAD0AAAA/wAAAJsAAAACAAAAAAAAAAAAAAAAAAAAFgAAANMAAAD/AAAA1wAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEAAAA9gAAAP8AAACXAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFgAAANQAAAD/AAAA0wAAABUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIwAAAPEAAAD/AAAAlwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFgAAANQAAAD/AAAA0wAAABUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAA/wAAALAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFgAAANMAAAD/AAAA0wAAABUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOkAAAD/AAAAKwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFgAAANMAAAD/AAAA0wAAABUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+gAAAP8AAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFgAAANMAAAD/AAAA0wAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADZAAAA/wAAAEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFgAAANMAAAD/AAAARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH4AAAD/AAAA3AAAABUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADDAAAAywAAABYAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAEYAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAM4AAAD/AAAA0wAAABYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMwAAAD/AAAA0wAAABYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFgAAANQAAAD/AAAA0wAAABYAAAAAAAAAAAAAAAAAAAAAAAAAFgAAANMAAAD/AAAA0wAAABYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANwAAAAsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFgAAANQAAAD/AAAA0wAAABYAAAAAAAAAAAAAAAAAAAAAAAAAFgAAANMAAAD/AAAA0wAAABYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEIAAAD/AAAAzAAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFgAAANQAAAD/AAAA0wAAABYAAAAAAAAAAAAAAAAAAAAAAAAAFgAAANMAAAD/AAAA0wAAABYAAAAAAAAAAAAAAAAAAAAAAAAAFAAAANoAAAD/AAAAzAAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFgAAANIAAAD/AAAA1wAAABgAAAAAAAAAAAAAAAAAAAAAAAAAFQAAANIAAAD/AAAA1wAAABgAAAAAAAAAAAAAAAAAAAAAAAAAGAAAANYAAAD/AAAAzgAAABMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFQAAANIAAAD/AAAA1wAAABgAAAAAAAAAAAAAAAAAAAAAAAAAFQAAANIAAAD/AAAA1wAAABgAAAAAAAAAAAAAAAAAAAAAAAAAGAAAANYAAAD/AAAAzgAAABMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFgAAANMAAAD/AAAA0wAAABAAAAAAAAAAAAAAAAAAAAAAAAAAFgAAANMAAAD/AAAA0wAAABYAAAAAAAAAAAAAAAAAAAAAAAAAGwAAANoAAAD/AAAAzAAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFgAAANMAAAD/AAAARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFgAAANMAAAD/AAAA0wAAABYAAAAAAAAAAAAAAAAAAAAAAAAAGwAAANoAAAD/AAAAzAAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAEUAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFgAAANMAAAD/AAAA0wAAABYAAAAAAAAAAAAAAAAAAAAAAAAAGwAAANoAAAD/AAAAzAAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFgAAANMAAAD/AAAAywAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGwAAANoAAAD/AAAAxQAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAsAAAAAAAAAAAAAAAAAAAAAAAAAFgAAAMwAAADDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGwAAAOIAAAD/AAAAdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEIAAAD/AAAAzAAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUQAAAP8AAADSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAANoAAAD/AAAAzAAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAA/wAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGwAAANoAAAD/AAAAzAAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACkAAAD/AAAA6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGwAAANoAAAD/AAAAzAAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqQAAAP8AAACjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGwAAANoAAAD/AAAAzAAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIsAAAD/AAAA9AAAACcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGwAAANoAAAD/AAAAzAAAABEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACLAAAA/wAAAPkAAABNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAANYAAAD/AAAAzgAAABMAAAAAAAAAAAAAAAAAAAAAAAAAhQAAAP8AAAD5AAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGwAAANoAAAD/AAAA1QAAAEEAAAAHAAAAJQAAAKYAAAD/AAAA+QAAAE4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGwAAANUAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAPUAAABNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAIMAAADaAAAA+wAAAOgAAAClAAAAKQAAAAAAAAAAAAAAAAAAAAAAAAAA+A////AH///gA///wcH//4Pg//8H8H//D/g//x/8H/8f/g//H/8P/w/Hj/8Hw///g8H8/8Hg+H/g8Hg/8Hg8H/g8Hg/8Hg8H/h8Hg/8fg8H//8Pg//nj8P/w//j/8H/4//g/+P/8H/j//g/w//8H4f//g8P//8AH///gD///8B97InN0YXR1cyI6MCwibXNnIjoiRXJyb3IiLCJyZWRpcmVjdCI6IiJ9 // @grant none // @run-at document-start // ==/UserScript== (function() { 'use strict'; // URL匹配正则 - 支持多种格式 // 匹配: example.com, www.example.com, https://example.com, http://example.com/path?a=1 const URL_PATTERN = /((?:https?:\/\/)?(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_+.~#?&/=]*))/gi; // 排除纯文件名(无域名后缀的常见情况) const EXCLUDE_EXTENSIONS = /\.(txt|pdf|doc|docx|xls|xlsx|ppt|pptx|jpg|jpeg|png|gif|mp4|mp3|exe|zip|rar|tar|gz|js|css|html|php|py|java|c|cpp|go|rs|ts|json|xml|svg|webp|bmp|ico|woff|ttf)$/i; // 搜索引擎配置 const SEARCH_ENGINES = { google: { inputSelector: 'input[name="q"], textarea[name="q"]', formSelector: 'form[role="search"], form[action="/search"]', getSearchParam: () => new URLSearchParams(location.search).get('q') }, baidu: { inputSelector: '#kw, input[name="wd"]', formSelector: '#form, form[action="/s"]', getSearchParam: () => new URLSearchParams(location.search).get('wd') || new URLSearchParams(location.search).get('word') }, bing: { inputSelector: '#sb_form_q, input[name="q"]', formSelector: '#sb_form, form[action="/search"]', getSearchParam: () => new URLSearchParams(location.search).get('q') }, duckduckgo: { inputSelector: '#search_form_input, input[name="q"]', formSelector: '#search_form, form[action="/"]', getSearchParam: () => new URLSearchParams(location.search).get('q') }, sogou: { inputSelector: '#query, input[name="query"]', formSelector: '#sf, form[action="/web"]', getSearchParam: () => new URLSearchParams(location.search).get('query') }, so: { inputSelector: '#keyword, input[name="q"]', formSelector: '#search, form[action="/s"]', getSearchParam: () => new URLSearchParams(location.search).get('q') } }; // 检测当前搜索引擎 function detectEngine() { const host = location.hostname; if (host.includes('google')) return 'google'; if (host.includes('baidu')) return 'baidu'; if (host.includes('bing')) return 'bing'; if (host.includes('duckduckgo')) return 'duckduckgo'; if (host.includes('sogou')) return 'sogou'; if (host.includes('so.com')) return 'so'; return null; } // 从文本中提取第一个有效URL function extractURL(text) { if (!text) return null; // 重置正则lastIndex URL_PATTERN.lastIndex = 0; let match; while ((match = URL_PATTERN.exec(text)) !== null) { let url = match[1].trim(); // 排除纯文件名(如 file.txt) // 检查是否包含域名特征(至少有一个点,且后缀不是纯文件扩展名) const domainPart = url.replace(/^https?:\/\//, '').split('/')[0]; // 必须包含点(域名格式) if (!domainPart.includes('.')) continue; // 排除看起来像纯文件扩展名的情况(如 "example.txt" 但没有路径) if (EXCLUDE_EXTENSIONS.test(url) && !url.includes('/') && !url.includes(':')) { continue; } return url; } return null; } // 规范化URL(添加协议头) function normalizeURL(url) { url = url.trim(); if (!url.startsWith('http://') && !url.startsWith('https://')) { url = 'https://' + url; } return url; } // 执行跳转 function redirectTo(url) { console.log('[链接提取器] 提取到URL,准备跳转:', url); window.location.replace(url); } // 拦截表单提交 function interceptForm(engine) { const config = SEARCH_ENGINES[engine]; const setup = () => { const form = document.querySelector(config.formSelector); const input = document.querySelector(config.inputSelector); if (!form || !input) { setTimeout(setup, 500); return; } // 拦截表单提交 form.addEventListener('submit', (e) => { const query = input.value; const url = extractURL(query); if (url) { e.preventDefault(); e.stopPropagation(); redirectTo(normalizeURL(url)); return false; } }, true); // 监听回车键 input.addEventListener('keydown', (e) => { if (e.key === 'Enter') { const query = input.value; const url = extractURL(query); if (url) { e.preventDefault(); e.stopPropagation(); redirectTo(normalizeURL(url)); return false; } } }, true); console.log('[链接提取器] 表单拦截已设置:', engine); }; if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', setup); } else { setup(); } } // 处理页面加载时的URL参数 function checkCurrentPage() { const engine = detectEngine(); if (!engine) return; const config = SEARCH_ENGINES[engine]; const query = config.getSearchParam(); if (query) { const url = extractURL(query); if (url) { setTimeout(() => { redirectTo(normalizeURL(url)); }, 100); } } } // 主程序 function init() { const engine = detectEngine(); if (!engine) { console.log('[链接提取器] 未识别的搜索引擎'); return; } console.log('[链接提取器] 已激活,监控搜索引擎:', engine); interceptForm(engine); checkCurrentPage(); } // 启动 init(); // SPA路由变化监听 let lastUrl = location.href; new MutationObserver(() => { const currentUrl = location.href; if (currentUrl !== lastUrl) { lastUrl = currentUrl; checkCurrentPage(); } }).observe(document, { subtree: true, childList: true }); })();