Automatically extract Google search results (Title, URL) and navigate to the next page.
// ==UserScript==
// @name Google Search Result Extractor
// @name:zh-CN 谷歌搜索结果自动提取器
// @namespace http://tampermonkey.net/
// @version 1.1
// @description Automatically extract Google search results (Title, URL) and navigate to the next page.
// @description:zh-CN 自动提取谷歌搜索结果的标题和链接,并消耗自动翻页提取至最后一页。
// @author YourName
// @match https://www.google.com/search*
// @match https://www.google.com.hk/search*
// @match https://www.google.ad/search*
// @match https://www.google.ae/search*
// @match https://www.google.com.tw/search*
// @include /^https:\/\/www\.google\..*\/search.*/
// @grant GM_setClipboard
// @grant GM_notification
// @license MIT
// @run-at document-idle
// ==/UserScript==
(function() {
'use strict';
// 1. UI 面板构建
const createUI = () => {
const panel = document.createElement('div');
panel.id = 'gs-extractor-panel';
panel.style = `
position: fixed; top: 20px; left: 20px; z-index: 10001;
background: #ffffff; border: 1px solid #4285f4;
padding: 15px; border-radius: 12px;
box-shadow: 0 10px 30px rgba(0,0,0,0.15);
width: 210px; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
`;
panel.innerHTML = `
<div style="font-weight: bold; color: #4285f4; margin-bottom: 10px; font-size: 16px; border-bottom: 1px solid #eee; padding-bottom: 5px;">🔍 提取助手</div>
<div style="margin-bottom: 12px; font-size: 13px;">已保存: <b id="gs-count" style="color: #d93025;">0</b> 条数据</div>
<button id="gs-start" style="width: 100%; padding: 10px; background: #4285f4; color: white; border: none; border-radius: 6px; cursor: pointer; font-weight: 600; margin-bottom: 8px; transition: 0.3s;">🚀 开始自动提取</button>
<button id="gs-copy" style="width: 100%; padding: 8px; background: #34a853; color: white; border: none; border-radius: 6px; cursor: pointer; margin-bottom: 8px;">📋 复制 (Excel格式)</button>
<button id="gs-clear" style="width: 100%; padding: 6px; background: #fff; color: #666; border: 1px solid #ccc; border-radius: 6px; cursor: pointer; font-size: 12px;">🗑️ 清空缓存</button>
<div id="gs-loader" style="display:none; color: #ea4335; font-size: 11px; text-align: center; margin-top: 8px; font-style: italic;">正在自动翻页中...</div>
`;
document.body.appendChild(panel);
};
// 2. 数据处理逻辑
const getData = () => JSON.parse(localStorage.getItem('gs_ext_data') || '[]');
const setData = (data) => localStorage.setItem('gs_ext_data', JSON.stringify(data));
const updateUIStatus = () => {
const count = getData().length;
const countEl = document.getElementById('gs-count');
if (countEl) countEl.innerText = count;
};
const extract = () => {
let currentData = getData();
const results = document.querySelectorAll('h3');
let added = 0;
results.forEach(h3 => {
const a = h3.closest('a');
if (a && a.href && !a.href.includes('google.com')) {
const url = a.href;
if (!currentData.some(item => item.url === url)) {
currentData.push({ title: h3.innerText.replace(/\s+/g, ' '), url: url });
added++;
}
}
});
setData(currentData);
updateUIStatus();
return added;
};
const runAuto = () => {
document.getElementById('gs-loader').style.display = 'block';
document.getElementById('gs-start').innerText = "⏹ 停止提取";
localStorage.setItem('gs_is_running', 'true');
extract();
const nextBtn = document.querySelector('a#pnnext');
if (nextBtn) {
// 随机延迟 2.5s - 4.5s 保护账号
const delay = Math.floor(Math.random() * 2000) + 2500;
setTimeout(() => {
if(localStorage.getItem('gs_is_running') === 'true') nextBtn.click();
}, delay);
} else {
stopAuto();
alert("✅ 提取完毕!已到达最后一页。");
}
};
const stopAuto = () => {
localStorage.setItem('gs_is_running', 'false');
const startBtn = document.getElementById('gs-start');
if (startBtn) {
startBtn.innerText = "🚀 开始自动提取";
document.getElementById('gs-loader').style.display = 'none';
}
};
// 3. 事件挂载
const init = () => {
createUI();
updateUIStatus();
document.getElementById('gs-start').onclick = () => {
if (localStorage.getItem('gs_is_running') === 'true') {
stopAuto();
} else {
runAuto();
}
};
document.getElementById('gs-copy').onclick = () => {
const data = getData();
if (data.length === 0) return alert("没有数据可供复制");
const output = data.map(i => `${i.title}\t${i.url}`).join('\n');
// 使用 GM_setClipboard 确保兼容性
navigator.clipboard.writeText(output).then(() => {
alert("已成功复制到剪贴板!");
});
};
document.getElementById('gs-clear').onclick = () => {
if (confirm("确定清除所有本地缓存的数据吗?")) {
localStorage.removeItem('gs_ext_data');
stopAuto();
updateUIStatus();
}
};
// 自动续接逻辑
if (localStorage.getItem('gs_is_running') === 'true') {
setTimeout(runAuto, 1500);
}
};
// 启动
if (document.readyState === 'complete') init();
else window.addEventListener('load', init);
})();