// ==UserScript==
// @name Google搜索增强
// @namespace http://tampermonkey.net/
// @version 6.3
// @description 采用Google原生风格在左侧显示中文语言过滤、时间过滤和文件类型过滤,优化显示条件
// @author You
// @match https://www.google.com/search*
// @match https://www.google.com.hk/search*
// @match https://www.google.cn/search*
// @grant none
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// 等待页面元素加载
function waitForElement(selector, callback) {
const element = document.querySelector(selector);
if (element) {
callback(element);
} else {
setTimeout(() => waitForElement(selector, callback), 100);
}
}
// 生成过滤后的URL
function generateFilterUrl(langFilter = null, timeFilter = null, fileFilter = null) {
const currentUrl = new URL(window.location.href);
const urlParams = currentUrl.searchParams;
let query = urlParams.get('q') || '';
if (langFilter !== null) {
if (langFilter === 'all') {
urlParams.delete('lr');
} else {
urlParams.set('lr', langFilter);
}
}
if (timeFilter !== null) {
if (timeFilter === 'all') {
urlParams.delete('tbs');
} else {
urlParams.set('tbs', timeFilter);
}
}
if (fileFilter !== null) {
query = query.replace(/\s*filetype:\w+/g, '');
if (fileFilter !== '' && fileFilter !== 'all') {
query = (query.trim() + ' filetype:' + fileFilter).trim();
}
urlParams.set('q', query);
}
return currentUrl.toString();
}
// 生成高级搜索URL
function generateAdvancedSearchUrl() {
const urlParams = new URLSearchParams(window.location.search);
const currentQuery = urlParams.get('q') || '';
const currentHost = window.location.host;
// 构建高级搜索URL,保持当前搜索词
const advancedUrl = `https://${currentHost}/advanced_search`;
const advancedParams = new URLSearchParams();
if (currentQuery) {
advancedParams.set('q', currentQuery);
}
return `${advancedUrl}?${advancedParams.toString()}`;
}
// 获取当前过滤状态
function getCurrentStatus() {
const urlParams = new URLSearchParams(window.location.search);
const currentLang = urlParams.get('lr') || 'all';
const currentTime = urlParams.get('tbs') || 'all';
const query = urlParams.get('q') || '';
const fileTypeMatch = query.match(/filetype:(\w+)/);
const currentFileType = fileTypeMatch ? fileTypeMatch[1] : '';
let normalizedLang = currentLang;
if (currentLang.includes('lang_zh-CN|lang_zh-TW') || currentLang.includes('lang_zh-TW|lang_zh-CN')) {
normalizedLang = 'lang_zh-CN|lang_zh-TW';
}
return { currentLang: normalizedLang, currentTime, currentFileType };
}
// 检查是否有足够空间显示
function hasEnoughSpace() {
return window.innerWidth >= 300;
}
// 创建纯原生风格左侧过滤器
function createNativeLeftFilter() {
const { currentLang, currentTime, currentFileType } = getCurrentStatus();
const container = document.createElement('div');
container.id = 'native-left-filter';
container.style.cssText = `
position: fixed;
left: 20px;
top: 160px;
width: 150px;
background: transparent;
font-family: arial,sans-serif;
font-size: 13px;
color: #3c4043;
z-index: 1000;
`;
const languageOptions = [
{ value: 'all', label: '全部结果', current: currentLang === 'all' },
{ value: 'lang_zh-CN|lang_zh-TW', label: '所有中文', current: currentLang === 'lang_zh-CN|lang_zh-TW' },
{ value: 'lang_zh-CN', label: '简体中文', current: currentLang === 'lang_zh-CN' },
{ value: 'lang_zh-TW', label: '繁体中文', current: currentLang === 'lang_zh-TW' }
];
const timeOptions = [
{ value: 'all', label: '不限时间', current: currentTime === 'all' },
{ value: 'qdr:d', label: '一天内', current: currentTime.includes('qdr:d') },
{ value: 'qdr:w', label: '一周内', current: currentTime.includes('qdr:w') },
{ value: 'qdr:m', label: '一月内', current: currentTime.includes('qdr:m') && !currentTime.includes('qdr:m6') },
{ value: 'qdr:m6', label: '半年内', current: currentTime.includes('qdr:m6') },
{ value: 'qdr:y', label: '一年内', current: currentTime.includes('qdr:y') }
];
function generateNativeSection(title, options, filterType) {
const links = options.map(option => {
const url = filterType === 'lang' ? generateFilterUrl(option.value, null, null) :
generateFilterUrl(null, option.value, null);
const isActive = option.current;
const style = isActive
? 'color: #1a73e8; text-decoration: none; font-weight: 400; border-left: 3px solid #1a73e8; padding-left: 8px; background: #f8f9fa;'
: 'color: #5f6368; text-decoration: none; padding-left: 11px;';
return `
<div style="margin-bottom: 1px;">
<a href="${url}" style="${style} display: block; padding-top: 4px; padding-bottom: 4px; padding-right: 8px; line-height: 18px;">
${option.label}
</a>
</div>
`;
}).join('');
return `
<div style="margin-bottom: 24px;">
<div style="color: #3c4043; font-size: 14px; font-weight: 400; margin-bottom: 8px; padding-left: 11px;">
${title}
</div>
${links}
</div>
`;
}
// 文件类型清除链接
const clearFileUrl = generateFilterUrl(null, null, '');
const fileTypeSection = currentFileType ? `
<div style="margin-bottom: 24px;">
<div style="color: #3c4043; font-size: 14px; font-weight: 400; margin-bottom: 8px; padding-left: 11px;">
文件类型
</div>
<div style="margin-bottom: 1px;">
<div style="color: #1a73e8; display: block; padding: 4px 8px 4px 11px; line-height: 18px; border-left: 3px solid #1a73e8; background: #f8f9fa;">
${currentFileType.toUpperCase()} 文件
</div>
</div>
<div style="margin-bottom: 1px;">
<a href="${clearFileUrl}" style="color: #5f6368; text-decoration: none; display: block; padding: 4px 8px 4px 11px; line-height: 18px;">
所有文件类型
</a>
</div>
</div>
` : '';
// 生成高级搜索URL
const advancedSearchUrl = generateAdvancedSearchUrl();
container.innerHTML = `
<style>
#native-left-filter a:hover {
color: #1a73e8 !important;
text-decoration: underline;
}
#native-left-filter .file-input {
width: 100%;
border: none;
border-bottom: 1px solid #dadce0;
padding: 6px 0;
font-size: 14px;
outline: none;
background: transparent;
color: #3c4043;
margin-left: 11px;
box-sizing: border-box;
width: calc(100% - 11px);
}
#native-left-filter .file-input:focus {
border-bottom: 2px solid #1a73e8;
}
#native-left-filter .file-input::placeholder {
color: #5f6368;
}
#native-left-filter .advanced-search-link {
color: #1a73e8;
text-decoration: none;
display: block;
padding: 4px 8px 4px 11px;
line-height: 18px;
font-size: 13px;
border-left: 3px solid transparent;
transition: all 0.2s ease;
}
#native-left-filter .advanced-search-link:hover {
border-left: 3px solid #1a73e8;
background: #f8f9fa;
text-decoration: underline;
}
</style>
${generateNativeSection('语言', languageOptions, 'lang')}
${generateNativeSection('时间', timeOptions, 'time')}
${fileTypeSection}
<div style="margin-bottom: 20px;">
<div style="color: #3c4043; font-size: 14px; font-weight: 400; margin-bottom: 8px; padding-left: 11px;">
${currentFileType ? '搜索其他文件' : '文件类型'}
</div>
<input type="text" class="file-input" id="file-ext-input" placeholder="按回车搜索" value="">
<div style="font-size: 11px; color: #5f6368; margin-top: 6px; padding-left: 11px; line-height: 1.4;">
例如:pdf, doc
</div>
</div>
<div style="margin-bottom: 16px;">
<div style="color: #3c4043; font-size: 14px; font-weight: 400; margin-bottom: 8px; padding-left: 11px;">
更多选项
</div>
<div style="margin-bottom: 1px;">
<a href="${advancedSearchUrl}" target="_blank" class="advanced-search-link">
🔧 高级搜索
</a>
</div>
</div>
`;
return container;
}
// 设置事件处理器
function setupEventHandlers(container) {
const fileInput = container.querySelector('#file-ext-input');
if (fileInput) {
fileInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
const fileType = fileInput.value.trim();
const url = generateFilterUrl(null, null, fileType);
window.location.href = url;
}
});
// 输入框失去焦点时也可以搜索
fileInput.addEventListener('blur', (e) => {
const fileType = fileInput.value.trim();
if (fileType && fileType !== getCurrentStatus().currentFileType) {
setTimeout(() => {
const url = generateFilterUrl(null, null, fileType);
window.location.href = url;
}, 200);
}
});
}
}
// 初始化过滤器
function initializeFilter() {
// 移除现有元素
const existingFilter = document.getElementById('native-left-filter');
if (existingFilter) existingFilter.remove();
// 检查是否有足够空间显示
if (!hasEnoughSpace()) {
return;
}
// 创建并添加过滤器
const filter = createNativeLeftFilter();
setupEventHandlers(filter);
document.body.appendChild(filter);
}
// 主函数
function main() {
if (!window.location.pathname.includes('/search')) {
return;
}
waitForElement('#search, #center_col, #main', () => {
setTimeout(initializeFilter, 500);
});
// 监听窗口大小变化
window.addEventListener('resize', () => {
setTimeout(initializeFilter, 100);
});
}
// 页面加载时执行
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', main);
} else {
main();
}
// 监听页面导航变化
let currentUrl = location.href;
const observer = new MutationObserver(() => {
if (location.href !== currentUrl) {
currentUrl = location.href;
setTimeout(main, 500);
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
})();