您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Collect titles for page links and download as CSV
// ==UserScript== // @name Simple Link Title Grabber // @namespace https://greasyfork.org/en/users/you // @version 0.1 // @description Collect titles for page links and download as CSV // @match *://*/* // @grant GM_xmlhttpRequest // @connect * // @license MIT // ==/UserScript== (function () { 'use strict'; const MAX = 30; // limit requests // tiny button const btn = document.createElement('button'); btn.textContent = 'Get Titles'; Object.assign(btn.style, { position: 'fixed', right: '12px', bottom: '12px', zIndex: 99999, padding: '8px 10px', borderRadius: '8px', border: '1px solid #ccc', background: '#fff', cursor: 'pointer', font: '12px system-ui' }); document.body.appendChild(btn); btn.onclick = async () => { btn.disabled = true; btn.textContent = 'Working...'; // collect unique http(s) links const urls = [...new Set([...document.querySelectorAll('a[href]')] .map(a => a.href) .filter(u => /^https?:\/\//i.test(u)) )].slice(0, MAX); if (!urls.length) { alert('No links found.'); reset(); return; } const results = []; let done = 0; for (const url of urls) { await request(url).then(({ title, status }) => { results.push({ url, title, status }); btn.textContent = `Working... ${++done}/${urls.length}`; }); } downloadCSV(results); reset(); }; function reset() { btn.disabled = false; btn.textContent = 'Get Titles'; } function request(url) { return new Promise((resolve) => { GM_xmlhttpRequest({ method: 'GET', url, headers: { 'Accept': 'text/html,application/xhtml+xml' }, timeout: 15000, onload: (r) => { const ok = r.status >= 200 && r.status < 300; const title = ok ? extractTitle(r.responseText) : ''; resolve({ title, status: `HTTP ${r.status}` }); }, onerror: () => resolve({ title: '', status: 'error' }), ontimeout: () => resolve({ title: '', status: 'timeout' }) }); }); } function extractTitle(html) { const m = /<title[^>]*>([\s\S]*?)<\/title>/i.exec(html); if (m) return decode(m[1]).trim().replace(/\s+/g, ' '); const og = /<meta[^>]+property=["']og:title["'][^>]+content=["']([^"']+)["']/i.exec(html); return og ? decode(og[1]).trim() : ''; } function decode(s) { const t = document.createElement('textarea'); t.innerHTML = s; return t.value; } function csvEscape(s) { return /[",\n]/.test(s) ? `"${String(s).replace(/"/g, '""')}"` : String(s); } function downloadCSV(rows) { const lines = [['URL', 'Title', 'Status'], ...rows.map(r => [r.url, r.title, r.status])] .map(cols => cols.map(csvEscape).join(',')).join('\n'); const blob = new Blob([lines], { type: 'text/csv;charset=utf-8' }); const a = Object.assign(document.createElement('a'), { href: URL.createObjectURL(blob), download: 'link-titles.csv' }); document.body.appendChild(a); a.click(); URL.revokeObjectURL(a.href); a.remove(); } })();