跳到主内容

网页正文批量提取 - 免费把网页文章正文抓成 Markdown 或纯文本(爬虫工具)

免费下载网页正文批量提取 v1.0.0
平台:Windows 10/11 (64位)大小:11.8 MB版本:v1.0.0更新:2026-10-15
提取码:34d7(如提示需要,请输入)
下载地址 ▾
解压后双击即可运行,无需安装任何运行环境;只在执行任务时访问你自己填写的地址,其余处理都在本机完成。
把网页文章存成自己的资料时,全选复制必然把导航栏、广告、相关推荐和评论区一起带走,一篇篇手工清理要花掉一整天

网页正文批量提取 运行界面

软件名称网页正文批量提取
版本v1.0.0
授权免费(可自由使用与转发)
运行方式本地运行,仅执行任务时访问你自己填写的地址
所属分类爬虫工具

这个工具解决什么问题

做内容整理、写行业报告、收集选题素材的人,几乎每天都在重复同一件事:看到一篇有用的文章,Ctrl+A 全选、Ctrl+C、切到 Word 或笔记软件、Ctrl+V。粘进去之后才发现,正文前后裹着一大堆和内容无关的东西——顶部的站点导航、右侧的热门推荐、文末的读者评论、底部的版权声明和备案信息,有的站点还会在正文中间插一段推广文案。于是你得一段一段往下拉,判断哪一段该删,删完还要检查有没有把正文误删掉。收集三五篇还好说,一旦要攒几十篇资料,光清理这些附属内容就是大半天,而且越到后面越容易走神删错。更麻烦的是有些页面把正文和推荐区放在同一个容器里,人工根本分不清边界在哪,只能凭感觉。其实网页的 HTML 结构里,正文和附属信息本来就是分开的容器,这些结构信息一直都在,只是「全选复制」这个动作会把它一并丢掉。

  • 原来的做法:在浏览器里 Ctrl+A 全选 → Ctrl+C → 粘到 Word 或笔记里 → 手工把导航、广告、推荐、评论、页脚一段段删掉,遇到正文与推荐混在同一块时只能凭感觉判断;几十篇下来就是大半天
  • 用这个工具:把一批网址粘进窗口,点一次「开始提取并导出」,程序按文本密度、标点密度和链接密度定位每页的主体内容区,自动丢掉导航、广告、评论与相关推荐,按标题/段落/列表/引用/表格还原成结构化文本并导出成文件
  • 省下来的:一篇资料从「复制—粘贴—逐段清理」的几分钟缩短到一秒内,且清理规则是统一的,不会出现「这一篇删多了、那一篇没删干净」

技术实现

运行期只用 Python 标准库,打包后是单个 exe,双击即用,不需要装 Python、不需要 pip 安装任何东西。整体是一条单向数据流:地址规范化 → robots.txt 检查 → 抓取解压 → 编码嗅探 → 解析成轻量 DOM → 打分定位正文容器 → 抽成结构化块 → 渲染成 Markdown 或纯文本 → 落盘。为了做到零第三方依赖,主动放弃了 requests 与 BeautifulSoup:requests 换来的是更省事的重定向与解压处理,BeautifulSoup 换来的是更宽容的解析,但两者加上 lxml 会让打包体积增加十几 MB,而且 lxml 是 C 扩展,在 PyInstaller 下容易出现找不到 DLL 的问题。改用手写的 urllib + html.parser 之后,整个 exe 依然很小,行为完全可控,任何装了 Python 3.8 以上的机器都能直接跑源码。抽成「结构化块」(标题/段落/列表/引用/代码块/表格/图片)这个中间层是刻意的:同一份内容要出两种格式(.md 给笔记软件、.txt 给检索),有中间层就只解析一遍 DOM,两种渲染各自遍历块列表,不会出现两种格式内容对不上的情况。

  • 正文定位四因子打分,并且把噪声字数从分子里扣掉:候选容器是 article / main / div / section / td / body,对每一个算:score =(有效字数 + 标点数 × 40)×(1 − 链接密度)× 关键词权重。链接密度超过 0.6 的容器直接淘汰——那是导航栏、标签云或者文章列表页的典型特征。关键词权重按 class 与 id 的词元匹配,content / article / 正文 / 内容 这类加权 1.6 倍,comment / sidebar / 相关 / 推荐 / 页脚 这类降到 0.25 倍。最关键的一步是「有效字数 = 子树可见字数 − 噪声子树字数」:如果不扣噪声,一个「正文 1200 字 + 页脚 800 字」的页面,body 会以 2000 分压过正文容器本身的 1200 分,结果把页脚也抓进来。扣掉噪声后两者打平,再按「分数相同取更深」的规则,就能稳定选中真正的正文容器。
  • 列表项被降级成段落的那个 bug:递归入口不能乱用:第一版把 <ul> 里的每个 <li> 直接丢进「从容器的孩子开始遍历」的递归函数,结果 li 这个身份丢了——它只遍历了 li 内部的文本孩子,于是列表项被当成普通段落输出,前面的「- 」编号全部消失。这是自测里 C 组断言抓出来的:断言「- 无序一\n- 无序二」必须连续出现,实际输出是两段中间夹着空行。修法是单独抽出 _emit_li(),由它负责「输出这个列表项 + 继续处理嵌套列表」,ul/ol 分支与裸 li 分支共用。同时行内元素渲染函数里显式跳过 ul/ol/table/pre/blockquote,避免嵌套列表被压成一行、还被重复输出两遍。
  • 编码嗅探的顺序不能乱,尤其 UTF-8 必须排在字节特征之前:顺序是:HTTP 响应头 charset → BOM → meta 声明 → 严格试解 UTF-8 → 字节特征 / gb18030 / big5 → latin-1 兜底。BOM 见到即确定;meta 声明必须排在字节猜测之前,因为国内大量政府与学校的老站只在 HTML 里写 GB2312 而响应头不带 charset,只读响应头会把中文全解成乱码;gb2312 与 gbk 一律升级成 gb18030,超集解子集永远安全还能多解出生僻字;latin-1 永不失败,保证函数不抛异常。这里踩过一个很隐蔽的坑:最初的字节特征启发式统计「首字节 0x81-0xFE、次字节 0x40-0xFE」的双高字节占比,而 UTF-8 的「中文」是 E4 B8 AD E6 96 87 —— E4 与 B8 恰好落在这个定义里,于是每个 UTF-8 汉字都被算成一对,占比逼近 50%,好页面被误判成 GBK。修法有两条:严格试解 UTF-8 提到字节特征之前,并且启发式函数先做一次「合法 UTF-8 就直接否定」的短路。
  • 不依赖 requests 与 BeautifulSoup 的取舍,以及 html.parser 的坑:标准库的 html.parser 是流式回调,不自动闭合标签,也不建树。真实网页大量省略 </p>、</li>、</td>,直接按回调拼出来的结构会完全错乱。所以自己实现了一套隐式闭合规则:新块级标签出现时自动闭合未结束的 <p>,<li> 遇到下一个 <li> 自动闭合,<td>/<th>/<tr> 依次同理,<a> 不允许嵌套。另外 <script>/<style> 的内容不参与解析,空元素(br、img、hr、meta…)不压栈。<title> 的站点名后缀专门写了一个保守的裁剪规则:只认带空格的连字符与全角竖线,且后半段不能以数字开头、不能含句读标点、不超过 12 字——这样既能把「文章标题 - 某某网」裁成「文章标题」,又不会把「AI-驱动的内容生产」裁成「AI」、也不会把「2026 - 2027 年度报告」裁成「2026」。
  • robots.txt 按 RFC 9309 实现,而不是凭感觉放行:匹配规则三条:命中模式最长的规则优先;长度相同时 Allow 优先(这比老习惯的「Disallow 优先」更安全也更符合现行规范);一条都没命中就是放行。「*」匹配任意字符(含斜杠)、「$」锚定结尾,其余字符一律先 re.escape 再处理——特别注意「?」在 robots.txt 里是普通字符,不能当正则量词,否则 /a?b 会误匹配 /axb。空值的 Disallow 行不产生规则(「Disallow:」等于全站放行,把它当成规则会导致假拦截)。自有 UA 分组优先于「*」分组,同名 UA 多组会合并。抓取时按「主机:端口」缓存 robots.txt,同一站点的多个地址只取一次;缓存对象被多个抓取线程共享,所以待判路径是当参数传进去的,没有存成实例属性——存属性会出现「A 线程刚写好路径、B 线程又改了它」的串台判定,自测里专门用三个线程各判 300 次来盯这个点。
  • 界面永不假死:后台线程只往队列里放消息:tkinter 不是线程安全的,从工作线程碰界面对象轻则随机崩溃,重则抛「main thread is not in main loop」。所以抓取全部跑在线程池里,工作线程只做一件事——把 (消息类型, 数据) 塞进 queue.Queue;主线程每 80 毫秒把队列搬空并刷新表格、进度条、状态文字。好处是几百个地址的批量任务里窗口照样能拖动、能滚动,「停止」按钮点下去两三秒内必定生效,因为取消标志在每一轮循环里都会检查一次(同域名限速的等待也切成 0.05 秒的小片,保证不用等完整个间隔)。

技术栈:Python 3.8+、tkinter 图形界面、纯标准库(运行期零第三方依赖)、html.parser 自建轻量 DOM、urllib 抓取(gzip/deflate 解压)、PyInstaller 单文件打包(--noconsole)

已知局限:只处理服务端直接返回的静态 HTML,不执行 JavaScript:靠前端框架渲染出内容的页面(很多单页应用与部分资讯站)抓到的会是空壳,程序会明确报告「没有提取到正文」而不是给一份空文件。需要登录、需要验证码、或者明确在 robots.txt 里禁止抓取的页面不做处理——前者是能力边界,后两者是刻意的合规设计。正文定位是启发式算法,对结构规整的文章页准确率高,但遇到把正文与推荐区完全混排在同一容器里的页面、以及大量使用表格做版式的老站点,可能需要人工核对一下结果。整页可见文字里链接占比超过六成的页面会被判定为「链接列表或导航页」并报告失败,而不是产出一份「一堆链接当正文」的垃圾文件。单页最大读取 6 MB,超过部分会被截断。抓取速度受目标站点响应速度影响,具体耗时视网站与网络而定。

操作教程

  1. 解压后双击打开
    解压压缩包,双击「网页正文批量提取.exe」。不需要安装 Python 或任何运行库。程序启动时会在自带的本地演示站点上跑一轮(仅用于第一次打开时能直接看到效果,随时可以在窗口里改地址)。
    预期结果:出现主窗口:上面是地址输入区,中间是提取选项,下面是结果表与预览区
  2. 把要提取的网页地址放进地址框
    三种方式都行:直接在框里粘贴;点「从文件导入…」选一个放着地址的 txt;点「粘贴剪贴板」把剪贴板内容一次性放进来。一行一个地址,也可以从网页上直接框选一整块带链接的文字粘进来——程序会自动切分并去重,重复地址只算一次,缺 http:// 的会自动补上。
    预期结果:地址框里逐行出现地址;状态栏显示「已放入 N 行待处理」
  3. 按需调整提取选项(默认值就能用)
    并发数默认 6(同时最多抓 6 个页面);超时默认 15 秒;「同域名间隔」默认 0.8 秒,意思是同一个站点上的两个页面之间至少隔 0.8 秒,避免给对方的服务器造成压力;「遵守 robots.txt」默认勾选,被站点明确禁止抓取的路径会自动跳过并在结果里说明;「保留图片链接」默认勾选,图片会以 Markdown 图片语法和绝对地址保留下来。
    预期结果:每一项旁边都有说明;填了非数字会自动按默认值处理并提示,不会报错退出
  4. 选导出格式和输出目录
    格式二选一:Markdown(.md)适合放进 Obsidian、Typora、语雀这类笔记软件继续加工;纯文本(.txt)适合检索和复制。输出目录默认在桌面的「网页正文提取」文件夹,点「选择…」可以改到别处。
    预期结果:点「选择…」弹出系统文件夹对话框,不需要手打路径
  5. 点「▶ 开始提取并导出」
    程序按并发数同时抓取,进度条随完成数推进,状态栏显示当前抓的是哪个地址。中途随时可以点「■ 停止」,已抓到的结果会保留并照常导出。
    预期结果:结果表逐行出现:序号、文章标题、来源站点、正文字数、精简比例、状态与提取方式;窗口全程可拖动、可滚动,不会出现「未响应」
  6. 点某一行看正文预览和提取依据
    选中一行,左下「正文预览」显示提取出的正文,右下「提取依据 / 诊断」显示这一页的编码判定、正文定位说明、字数对比、图片数量与保存的文件名。想看看为什么某一页失败,看这里最直接。
    预期结果:预览区出现干净正文(不含导航与评论);诊断区写明「命中主体容器 <article class=...>:有效正文约 N 字、段落结构 M 处、链接密度 X%」
  7. 到输出目录取文件
    点「打开输出目录」,里面是每篇文章一个文件(文件名带序号,方便和地址顺序对照),外加一份「清单.csv」——用 Excel 双击打开记录,列有标题、来源地址、正文字数、精简比例与状态。改了格式或想重新导一遍,点「重新导出全部」即可;想只要某一篇,选中它点「复制所选正文」。
    预期结果:文件里只有文章标题与正文,没有导航、广告、评论与相关推荐;清单.csv 中文不乱码(带 BOM)

常见问题

Q:它会把我不要的东西也抓下来吗?能保证干净吗?A:程序按容器结构判断,不是按关键词删句子。三种典型噪声都能稳定排除:导航栏、标签云、文章列表这类「几乎全是链接」的区域(链接密度超过 60% 直接淘汰);评论区、相关推荐、侧栏这类 class/id 命中负向词的区域(权重降到 25%);页脚与广告这类独立容器(作为噪声字数从候选里扣掉)。所以导出的文件里通常只有标题、正文段落、列表、引用、表格和图片。仍然建议第一次用时抽看一两篇——正文定位是启发式算法,遇到把正文和推荐区完全混排的页面可能需要人工核一下。
Q:需要装 Python 或者别的运行库吗?A:不需要。运行版是单个可执行文件,双击就能打开,运行期只用 Python 标准库,没有第三方依赖,也不读写注册表、不需要管理员权限。打包之后把整个文件夹拷到别的电脑上也能直接跑,不需要在那台机器上装任何东西。
Q:抓取的时候会往别的服务器发我的数据吗?A:不会。程序只有一种对外行为:向你填写的那个网址发起 HTTP 请求取网页。不发任何数据到第三方服务器,不做统计上报,不检查更新。遵守 robots.txt 是默认开启的,被站点禁止的路径会自动跳过且不会重试。请把它用在自己有权访问的公开页面或自有站点上。
Q:同一个网站放了几十个地址会不会把对方服务器压垮?A:不会。程序对每个域名单独排队:同一个站点上的两个请求之间至少间隔「同域名间隔」秒(默认 0.8 秒),即使你把并发数开到 16,同一个域名上的请求依然是依次进行的。只有跨域名的请求才真正并行。站点比较多的时候,这个设计反而决定了整体速度。
Q:为什么某一页显示「没有提取到正文」?A:常见四种原因:① 页面正文是 JavaScript 渲染出来的,服务端返回的 HTML 里本来就没有正文(本工具不执行 JS,这是明确的能力边界);② 页面需要登录才能看到内容;③ 这一页其实是文章列表页或导航页,整页可见文字里链接占比超过六成,程序判断它不是文章正文页并主动拒绝产出垃圾文件;④ 页面是纯图片长图。诊断区会把这一页的实际情况写清楚。
Q:导出的 .md 和 .txt 有什么区别?A:内容来源是同一份解析结果,只是标记不同。.md 保留标题层级(#、##)、列表符号、引用(>)、代码块围栏和表格,适合放进笔记软件继续加工;.txt 会把这些标记全部去掉,只留纯文字,适合全文检索和直接复制。图片在 .md 里是 ![](地址),在 .txt 里是「[图片] 说明文字」。两种格式都会在文件开头带上标题、来源地址和提取时间,方便日后回溯。
Q:中文会不会乱码?A:不会。编码判定按「响应头 charset → 文件头 BOM → 页面 meta 声明 → 严格试解 UTF-8 → GB18030 / Big5 试解 → latin-1 兜底」六级顺序走,GB2312 与 GBK 会自动升级到超集 GB18030 解码。导出文件统一是 UTF-8;清单.csv 额外带 UTF-8 BOM,用 Excel 双击打开中文也不会乱码。只有极少数编码声明与实际字节完全不符的页面,才会在结果里标注「编码未能识别」。

技术实现与后续维护

整套工具由三个源码文件构成:核心逻辑(article_core.py)、图形界面(article_extract_gui.py)、演示站点(demo_server.py),加上一份 314 项断言的自测脚本。核心逻辑不含任何界面代码,所有能力都是可独立调用的函数与普通类,所以改功能时不会牵扯界面。全文有逐段中文注释,尤其是六个关键决策点(噪声字数为什么要单独扣、编码嗅探为什么不能把字节特征排在 UTF-8 之前、列表项递归入口为什么不能直接传 li、robots 的「?」为什么必须转义、待判路径为什么不能存成实例属性、tkinter 为什么要走队列)都写明了当时踩到的具体现象与修法,避免以后改回去。运行环境是 Windows 10/11 64 位 + Python 3.8 以上,运行期零第三方依赖。日常维护主要是两件事:一是跑一遍 tests/selftest.py 确认没有回归;二是遇到识别不准的站点时,在 keyword_weight() 的关键词表里补词,或用 demo_server.py 复现该版式后调整打分参数。

技术构成:

  • src/article_core.py —— 核心逻辑(1791 行,含中文注释):URL 规范化、编码嗅探、robots.txt 解析与缓存、HTTP 抓取与解压、轻量 DOM、正文定位打分、结构化块抽取、Markdown/纯文本渲染、导出与清单、并发调度。不含任何界面代码,可独立自测。
  • src/article_extract_gui.py —— tkinter 图形界面(609 行):窗口布局、选项读取与校验、后台线程与主线程的队列通信、结果表与预览区刷新、导出与复制、--demo 演示模式。
  • src/demo_server.py —— 本地演示站点(337 行):只监听 127.0.0.1,内置 12 类页面(6 篇不同容器形态的文章、GBK 编码页、链接列表页、极短页、空正文页、404、超时、robots 禁止路径),用于自测与截图,不访问外网。
  • tests/selftest.py —— 无界面回归自测(964 行 / 314 项断言,10 个分组):含本机回环 HTTP 服务,覆盖 gzip、deflate、裸 deflate、跳转、GBK、超时、404、robots 跳过、并发限速、中途停止、导出与文件名等。

运行环境:

运行环境:Windows 10/11(64 位)+ Python 3.8 以上,需自带 tkinter(Windows 官方安装包默认包含)。界面启动入口是 src/article_extract_gui.py,自测入口是 tests/selftest.py(不需要外网,全部走本机回环地址)。重新打包成单文件 exe 用 PyInstaller 的 --onefile --noconsole,工程里已经放好 build.bat 一键脚本。运行期只用 Python 标准库,没有任何第三方依赖;requirements.txt 里只列了打包用的 PyInstaller。

可扩展方向:

  • 想增加「按站点规则定制」能力:在 article_core.py 的 keyword_weight() 里加白名单表,针对特定站点的容器 class 直接给高分
  • 想支持 JavaScript 渲染的页面:把 fetch_url() 换成调用本机浏览器的方案,extract_from_html() 之后的整条流水线不用改
  • 想输出 Word 或 PDF:在 Markdownizer 之后加一个渲染器即可——结构化块(标题/段落/列表/引用/代码/表格/图片)已经是与格式无关的中间层
  • 想做成定时任务(比如每天自动抓一批并归档):Extractor 是纯对象,不依赖界面,可直接在脚本里循环调用
  • 想加「只保留指定字数以上的正文」「按关键词过滤文章」:在 Extractor 的 min_chars 参数上扩展,或在导出前对 results 做一次筛选
  • 想把清单写进数据库或推送到别处:write_index_csv() 已经把每篇的元信息整理成行,换一个 writer 就行

本工具免费提供使用,但不对外分发源码。如果你需要在本工具基础上做功能调整、对接内部系统或长期维护,可以联系我们做二次开发,源码与工程文档可在定制合作中一并交付。

需要其它功能?可以定制

这个工具只做一件事:把网页文章存成自己的资料时,全选复制必然把导航栏、广告、相关推荐和评论区一起带走,一篇篇手工清理要花掉一整天。如果你的场景还需要别的处理,可以联系我们做二次开发,按你的实际数据格式和流程定制。

常见的定制需求:

  • 按指定站点的版式定制正文识别规则(把某些容器直接标记为正文或噪声)
  • 增加图片本地化(把正文里的图片下载到本地并改写为相对路径)
  • 增加正文去重(跨文章检测重复段落,适合汇编类资料)
  • 把结果直接写入指定知识库(Obsidian 目录、语雀、飞书文档等)
  • 改成定时批量任务(每天定点抓取一批地址并按日期归档)
  • 增加多语言正文识别与翻译前的预处理
  • 联系方式:邮箱/微信见站内「联系我们」页面,或在本文下方留言
  • 定制说明:请附上你的数据样例(脱敏即可)和期望结果,方便快速评估工作量
  • 交付形式:定制项目可交付可执行程序,按需一并交付源码与工程文档,支持长期维护

使用说明与免责声明

本工具涉及数据采集,请在合法合规的前提下使用。
  • 本工具仅用于采集公开可见或你自身拥有权限的数据。
  • 请遵守目标网站的服务条款、robots 协议及《网络安全法》等相关法律法规。
  • 请合理控制请求频率,不要对目标站点造成访问压力。
  • 不得用于采集个人隐私、付费墙内容或任何受法律保护的非公开数据。
  • 因使用不当造成的后果由使用者自行承担;本工具不做数据二次分发。
免费下载网页正文批量提取 v1.0.0
平台:Windows 10/11 (64位)大小:11.8 MB版本:v1.0.0更新:2026-10-15
提取码:34d7(如提示需要,请输入)
下载地址 ▾
解压后双击即可运行,无需安装任何运行环境;只在执行任务时访问你自己填写的地址,其余处理都在本机完成。
分享到:

本文链接:https://www.biyeyuanma.cn/post/331.html

服务热线

加我微信

加我微信