一、安装Tampermonkey篡改猴
二、加入代码
// ==UserScript==
// @name WMX 表格采集助手
// @namespace local.wmx.capture
// @version 1.0.0
// @description 一键采集当前页表格数据并累积,最后导出 Excel。翻页需手动点。
// @match https://*.wmxpro.com/*
// @run-at document-idle
// @grant none
// ==/UserScript==
(function () {
'use strict';
var KEY = 'wmx_capture_v1';
var CELL = 'th,td,[role="columnheader"],[role="cell"],[role="gridcell"]';
/* ---------- 找表格:穿透同源 iframe 与 Shadow DOM ---------- */
function collectRoots() {
var out = [document];
var frames = document.querySelectorAll('iframe');
for (var i = 0; i < frames.length; i++) {
try {
var d = frames[i].contentDocument;
if (d && d.body) out.push(d);
} catch (e) { /* 跨域 iframe 跳过 */ }
}
function pierce(root) {
var els = root.querySelectorAll('*');
for (var j = 0; j < els.length; j++) {
if (els[j].shadowRoot) {
out.push(els[j].shadowRoot);
pierce(els[j].shadowRoot);
}
}
}
for (var k = 0; k < out.length; k++) pierce(out[k]);
return out;
}
/* ---------- 单元格处理:Title 与 URL 同格时拆成两格 ---------- */
function cellOut(c) {
var lines = (c.innerText || '').replace(/\u00a0/g, ' ')
.split('\n')
.map(function (s) { return s.trim(); })
.filter(function (s) { return s; });
if (!lines.length) return [''];
var idx = -1;
for (var i = 0; i < lines.length; i++) {
if (/^https?:\/\//i.test(lines[i])) { idx = i; break; }
}
if (idx !== -1 && lines.length > 1) {
var url = lines[idx];
if (/…|\.\.\.$/.test(url)) {
var a = c.querySelector('a[href]');
if (a && /^https?:/i.test(a.href)) url = a.href;
}
var title = lines.filter(function (_, k) { return k !== idx; }).join(' ');
return [title, url];
}
return [lines.join(' ')];
}
/* ---------- 抓当前页的行 ---------- */
function grabRows() {
var best = [];
var roots = collectRoots();
var sels = ['tr', '[role="row"]'];
for (var i = 0; i < roots.length; i++) {
for (var j = 0; j < sels.length; j++) {
var rows;
try { rows = roots[i].querySelectorAll(sels[j]); } catch (e) { continue; }
var good = [];
for (var k = 0; k < rows.length; k++) {
if (rows[k].querySelectorAll(CELL).length >= 3) good.push(rows[k]);
}
if (good.length > best.length) best = good;
}
}
return best;
}
/* ---------- 存储 ---------- */
function load() {
try { return JSON.parse(localStorage.getItem(KEY) || '{"rows":[]}'); }
catch (e) { return { rows: [] }; }
}
function save(s) { localStorage.setItem(KEY, JSON.stringify(s)); }
/* ---------- 动作 ---------- */
function capture() {
var rows = grabRows();
if (rows.length < 2) {
return say('没找到数据行,等表格加载完再点', true);
}
var store = load();
var seen = new Set(store.rows);
var added = 0;
for (var i = 0; i < rows.length; i++) {
var cells = rows[i].querySelectorAll(CELL);
var parts = [];
for (var j = 0; j < cells.length; j++) {
var out = cellOut(cells[j]);
for (var m = 0; m < out.length; m++) parts.push(out[m].replace(/\t/g, ' ').trim());
}
var line = parts.join('\t');
if (line.replace(/\t/g, '').trim() && !seen.has(line)) {
seen.add(line);
store.rows.push(line);
added++;
}
}
save(store);
say('本页 ' + rows.length + ' 行,新增 ' + added + ',累计 ' + store.rows.length);
}
function esc(s) {
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
}
function exportXls() {
var store = load();
if (!store.rows.length) return say('还没有数据', true);
var html = '<html><head><meta charset="utf-8"></head><body><table border="1" cellspacing="0">';
for (var i = 0; i < store.rows.length; i++) {
var cells = store.rows[i].split('\t');
html += '<tr>';
for (var j = 0; j < cells.length; j++) html += '<td>' + esc(cells[j]) + '</td>';
html += '</tr>';
}
html += '</table></body></html>';
var blob = new Blob(['\ufeff' + html], { type: 'application/vnd.ms-excel;charset=utf-8' });
var a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = 'wmx_data_' + new Date().toISOString().slice(0, 10) + '.xls';
document.body.appendChild(a);
a.click();
a.remove();
say('已导出 ' + store.rows.length + ' 行');
}
function clearAll() {
localStorage.removeItem(KEY);
say('已清空,累计 0');
}
/* ---------- 界面 ---------- */
var infoEl, panel;
function say(msg, warn) {
if (!infoEl) return;
infoEl.textContent = msg;
infoEl.style.color = warn ? '#fca5a5' : '#9ae6b4';
var store = load();
infoEl.textContent = msg + '(累计 ' + store.rows.length + ' 行)';
}
function makeBtn(text, bg, fn) {
var b = document.createElement('button');
b.textContent = text;
b.style.cssText = 'flex:1;cursor:pointer;border:0;border-radius:6px;' +
'padding:6px 8px;font-size:12px;color:#fff;background:' + bg;
b.addEventListener('click', fn);
return b;
}
function buildUI() {
panel = document.createElement('div');
panel.id = 'wmx-capture-panel';
panel.style.cssText = [
'position:fixed', 'right:16px', 'bottom:16px', 'z-index:2147483647',
'background:#1f2937', 'color:#f3f4f6', 'padding:10px 12px', 'border-radius:10px',
'box-shadow:0 6px 24px rgba(0,0,0,.3)', 'min-width:200px', 'opacity:.95',
'font:12px/1.5 system-ui,-apple-system,"Microsoft YaHei",sans-serif',
'user-select:none'
].join(';');
var title = document.createElement('div');
title.textContent = 'WMX 采集助手';
title.style.cssText = 'font-weight:600;margin-bottom:6px;';
infoEl = document.createElement('div');
infoEl.style.cssText = 'margin-bottom:8px;color:#9ae6b4;min-height:18px;';
var row = document.createElement('div');
row.style.cssText = 'display:flex;gap:6px;';
row.appendChild(makeBtn('采集本页', '#2563eb', capture));
row.appendChild(makeBtn('导出', '#059669', exportXls));
row.appendChild(makeBtn('清空', '#4b5563', clearAll));
panel.appendChild(title);
panel.appendChild(infoEl);
panel.appendChild(row);
document.body.appendChild(panel);
infoEl.style.color = '#9ae6b4';
infoEl.textContent = '累计 ' + load().rows.length + ' 行';
}
/* ---------- 启动 ---------- */
function start() {
if (document.getElementById('wmx-capture-panel')) return;
console.log('[WMX] 脚本已注入:' + location.href);
try { buildUI(); } catch (e) { console.error('[WMX] 面板创建失败', e); }
}
if (document.body) start();
else document.addEventListener('DOMContentLoaded', start);
/* 页面局部重渲染 / 单页路由切换后,确保面板还在 */
setInterval(function () {
if (!document.body) return;
if (!document.getElementById('wmx-capture-panel')) {
try { buildUI(); console.log('[WMX] 面板已重新挂载'); }
catch (e) { console.error('[WMX] 重新挂载失败', e); }
}
}, 2000);
})();
四、之前的手工导出的代码
原来无法导出的数据,现在可以导出了
(一)代码
(() => {
// 收集主文档 + 同源 iframe + Shadow DOM 里所有可访问的根
const roots = [document];
for (const f of document.querySelectorAll('iframe')) {
try { if (f.contentDocument && f.contentDocument.body) roots.push(f.contentDocument); } catch (e) {}
}
const pierce = (root) => {
for (const el of root.querySelectorAll('*')) {
if (el.shadowRoot) { roots.push(el.shadowRoot); pierce(el.shadowRoot); }
}
};
for (const r of [...roots]) pierce(r);
const cellSel = 'th,td,[role="columnheader"],[role="cell"],[role="gridcell"]';
let best = [];
for (const root of roots) {
for (const sel of ['tr', '[role="row"]']) {
const good = [...root.querySelectorAll(sel)]
.filter(r => r.querySelectorAll(cellSel).length >= 3); // 只要真数据行
if (good.length > best.length) best = good;
}
}
if (best.length < 2) return console.warn('仍然只有表头:表格在跨域 iframe 里,看办法 2');
const tsv = best.map(tr =>
[...tr.querySelectorAll(cellSel)].map(c => (c.innerText || '').replace(/\s+/g, ' ').trim()).join('\t')
).join('\n');
try { copy(tsv); console.log('已复制 ' + best.length + ' 行,直接去 Excel 粘贴'); }
catch (e) { console.log(tsv); }
})();
(二)使用方法
在页面上按 F12 → 切到 Console(控制台),粘下面这段回车:


