惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

J
Java Code Geeks
月光博客
月光博客
aimingoo的专栏
aimingoo的专栏
Google DeepMind News
Google DeepMind News
Recent Announcements
Recent Announcements
MyScale Blog
MyScale Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
S
SegmentFault 最新的问题
Hugging Face - Blog
Hugging Face - Blog
Martin Fowler
Martin Fowler
WordPress大学
WordPress大学
F
Fortinet All Blogs
小众软件
小众软件
D
Docker
U
Unit 42
博客园 - 聂微东
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
爱范儿
爱范儿
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
IT之家
IT之家
云风的 BLOG
云风的 BLOG
博客园 - 司徒正美
有赞技术团队
有赞技术团队
腾讯CDC

博客园 - jack_Meng

华为手机如何打开工程菜单 2026年AI编程工具大全,33个主流工具 .NET 异常处理的"暗门":代码里被 catch 吃掉的异常,你依然能抓住它——FirstChanceException Visual Studio 插件 Gittoy , 我做了一个 vs 版的 gittoolbox 用 C 语言实现任务栏图标动画,支持使用表情包gif/webp 如何用0预算推广项目 开源的 Windows 桌面整理工具 被罚了500后,整个人都变老实了 从零搭建一个最小 AI Agent:Python 完整示例 + AI调用机制详解 CASIO卡西欧计算器的自检模式——2种自检方式 C#把字符串按每两个字符一组,组之间加空格 C#程序从指定路径或网络加载引用的DLL 设置程序PrivatePath,配置引用程序集的指定路径(分离exe和dll) .NET/WPF 程序密钥加密存储:使用 DPAPI 实现安全兼容 一线大厂的Git规范 一线大厂的数据库规范 Python自动化实战:常用的类库和使用场景 工控生态之展示与交互:怎么让工业软件不再"丑" 一个 Python 项目带你入门AI应用开发课程介绍----系列文章 开源好用的酷狗音乐播放器:VibeMusic PowerShell + C# 实现桌面文字提醒,类似于“激活Windows”的功能 【Python】2026动态文字壁纸,一键让你的桌面加上动态效果 Python 用 tkinter 实现在 Windows 上提示文本消息的实现(模拟安卓手机上的 Toast 效果) 用Python在Windows桌面弹出文字提示 在Windows桌面背景上添加自定义文字 常用AI提示词汇总 chrome浏览器,Google新标签页添加快捷图标 油候脚本中,使用GM_info对象,打印脚本信息 使用油候脚本,移除页面无法选择文字 高中免费电子教辅资料合集
提取网页表格,一键导出 CSV:一个 Bookmarklet 脚本就够了
jack_Meng · 2026-09-02 · via 博客园 - jack_Meng

做数据分析、爬虫或竞品调研时,经常碰到网页上挂着一张现成的表格,手动复制粘贴到 Excel 不仅费时,还会丢掉格式、弄乱列对齐。本文分享一个 Bookmarklet(书签脚本),点击即可提取页面中的所有表格,自动转成 CSV 并写入剪贴板,直接粘贴进 Excel 就能用。

最终效果预览

在任意包含 <table> 的页面上点击书签:

  1. 弹窗告知发现多少个表格,每个表格的行列数
  2. 页面中的表格被蓝色边框高亮,视觉上确认命中范围
  3. CSV 数据自动复制到剪贴板,打开 Excel 直接粘贴即可
  4. 控制台以表格形式输出每个表格的数据结构,方便核对

Bookmarklet 是什么?

Bookmarklet 就是把一段 JavaScript 代码以 javascript: 协议的形式保存在书签中。点击书签时,浏览器会在当前页面上下文中执行这段代码。

优点:无需安装插件、无需 F12 开控制台、不依赖任何框架、所有现代浏览器都支持。


完整代码

以下就是提取表格的 Bookmarklet,新建书签,在"网址"栏粘贴全部内容即可。

javascript:(function () {
    var tables = document.querySelectorAll('table');
    if (!tables.length) {
        alert('当前页面未找到任何表格');
        return;
    }

    function clean(s) {
        if (s == null) return '';
        return String(s).replace(/\s+/g, ' ').trim();
    }

    function parseTable(table) {
        var rows = table.querySelectorAll('tr');
        var data = [];
        var colspans = [];
        rows.forEach(function (tr, r) {
            var cells = tr.querySelectorAll('th,td');
            var row = [];
            var ci = 0;
            while (colspans[ci] && colspans[ci].r > r) {
                row.push(colspans[ci].v);
                ci++;
            }
            cells.forEach(function (cell) {
                while (colspans[ci] && colspans[ci].r > r) {
                    row.push(colspans[ci].v);
                    ci++;
                }
                var txt = clean(cell.innerText);
                var cs = parseInt(cell.getAttribute('colspan') || '1', 10);
                var rs = parseInt(cell.getAttribute('rowspan') || '1', 10);
                for (var k = 0; k < cs; k++) {
                    row.push(txt);
                    if (rs > 1) {
                        colspans[ci] = { v: txt, r: r + rs };
                    }
                    ci++;
                }
            });
            while (colspans[ci] && colspans[ci].r > r) {
                row.push(colspans[ci].v);
                ci++;
            }
            data.push(row);
        });
        return data;
    }

    function toCSV(data) {
        var out = [];
        data.forEach(function (t, idx) {
            if (idx > 0) out.push('');
            out.push('=== Table ' + (idx + 1) + ' ===');
            t.forEach(function (row) {
                out.push(row.map(function (c) {
                    c = String(c == null ? '' : c);
                    if (/[",\n\r]/.test(c)) {
                        return '"' + c.replace(/"/g, '""') + '"';
                    }
                    return c;
                }).join(','));
            });
        });
        return out.join('\n');
    }

    function copy(text) {
        if (navigator.clipboard && navigator.clipboard.writeText) {
            navigator.clipboard.writeText(text).then(
                function () { console.log('✅ 表格已复制到剪贴板'); },
                function () { fallbackCopy(text); }
            );
        } else {
            fallbackCopy(text);
        }
    }
    function fallbackCopy(text) {
        var ta = document.createElement('textarea');
        ta.value = text;
        ta.style.position = 'fixed';
        ta.style.opacity = '0';
        document.body.appendChild(ta);
        ta.select();
        try { document.execCommand('copy'); } catch (e) {}
        document.body.removeChild(ta);
    }

    var all = [];
    tables.forEach(function (t) {
        t.style.outline = '2px solid #1976d2';
        all.push(parseTable(t));
    });
    var csv = toCSV(all);
    copy(csv);
    var summary = '📑 共发现 ' + tables.length + ' 个表格';
    if (tables.length === 1) {
        var rows = all[0].length;
        var cols = all[0][0] ? all[0][0].length : 0;
        summary += '\n行 x 列: ' + rows + ' x ' + cols;
    } else {
        summary += '\n' + all.map(function (d, i) {
            return '  #' + (i + 1) + ': ' + d.length + ' 行 x ' + (d[0] ? d[0].length : 0) + ' 列';
        }).join('\n');
    }
    summary += '\nCSV 已复制到剪贴板,可在控制台查看完整数据';
    alert(summary);
    console.log('🎯 表格提取完成,共 ' + tables.length + ' 个表格');
    all.forEach(function (d, i) {
        console.log('=== Table ' + (i + 1) + ' ===');
        console.table(d);
    });
    console.log('📋 CSV 内容:\n' + csv);
})();

使用方法

  1. 在浏览器中打开书签管理(Chrome 按 Ctrl+Shift+O
  2. 新建书签,名称建议设为 📑 提取表格
  3. 网址一栏粘贴上方完整代码(确保以 javascript: 开头)
  4. 打开任意包含表格的网页(如维基百科的统计页面、官网的价目表等)
  5. 点击该书签
  6. 打开 Excel / Google Sheets / 文本编辑器,按 Ctrl+V 粘贴

运行效果

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述


核心实现思路

1. 定位表格

var tables = document.querySelectorAll('table');

用原生 querySelectorAll 获取页面中所有 <table> 元素,一行搞定表格发现。无表格时提前 return 并提示,避免用户困惑。

2. 解析表格结构:colspan / rowspan 处理

真正的难点在这里。HTML 表格允许单元格跨列(colspan)和跨行(rowspan),解析时需要记录跨行单元格的"占位"信息。

实现方案是维护一个 colspans 数组,索引对应列位置,每个元素记录占位值 v 和有效行号 r

colspans[ci] = { v: '单元格文本', r: rowIndex + rowspan }

每处理新的一行时,先检查 colspans 中是否有仍在生效中的占位(r > 当前行号),有则先填充,再处理该行实际单元格。这样无论表格嵌套多复杂,输出永远是对齐的二维数组。

3. 导出 CSV

a,"b,c",d → a,"b,c",d
a"ba,"b""",d

当单元格内容包含逗号、双引号或换行符时,用双引号包裹并将内部双引号转义为 "",严格遵循 RFC 4180 规范。

4. 复制到剪贴板

优先使用 navigator.clipboard.writeText(现代 API,异步),不支持时降级到传统的 document.execCommand('copy')(通过临时创建不可见 <textarea> 实现)。

5. 可视化反馈

  • 页面:每个命中的表格加上蓝色外框 outline: 2px solid #1976d2
  • 弹窗:表格总数 + 各表行列数
  • 控制台:console.table 输出结构化的表格数据 + 完整 CSV 文本

方案对比

方式便捷度功能完整度适用场景
手动选中 → Ctrl+C → 粘贴 极少量手工操作
本 Bookmarklet ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ 日常快速提取,一劳永逸
浏览器插件 ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ 需要长期使用、批量处理、导出多格式

适当场景举例

  • 维基百科/数据平台:人口统计、经济指标等结构化数据表,一键转 CSV
  • 官网价目表:提取产品列表、套餐对比等定价信息
  • 内部后台页面:管理后台的列表页往往就是 <table>,导出第三方系统的数据
  • 竞品调研:电商搜索结果、招聘列表等,批量结构化采集

总结

网页中的 <table> 数据随处可见,手动复制粘贴的低效远比想象中浪费的时间多。这个不到 100 行的小书签,点一下就能完成"提取 → 结构化 → 复制"全流程,是一个典型的"花 5 分钟配置,省 N 小时重复劳动"的实用工具。


=======================================================================================