这段时间一直在琢磨一个事儿:怎么把网页上那些值得反复读的长文、连载小说,弄到墨水屏阅读器上去看。用手机刷屏幕刺眼,用电脑看又坐不住,还是墨水屏舒服。但网页直接发给阅读器,排版直接乱到没法看,图片加载慢,字又小又挤。折腾了几个工具之后,我算是摸出了一套比较顺手的流程,今天就把这套方法拆开聊透。
我下面说的方案,主要围绕E-Ink设备展开,但核心思路其实对所有电子书阅读器通用。核心只有一件事:把网页内容清洗干净,转成阅读器最适配的格式,然后传进去舒舒服服地看。整个过程涉及的工具有在线转换、本地脚本、阅读器自带的推送服务,还有必要的格式微调手段,我会一个一个说清楚它们的适用场景和坑。
1. 内容整体设计与思路拆解
1.1 为什么非要转格式,直接发送不行吗
很多人一开始会想,阅读器不是能打开网页吗?带浏览器的型号确实能开,但真用起来体验很差。墨水屏刷新慢,网页里的动态元素、弹窗、无限滚动脚本,在墨水屏上要么卡死,要么显示残缺。网页默认的字号是给手机和电脑屏幕设计的,放到阅读器上,一行字能铺满大半屏,段落间距全乱,图片和文字对不上。
最要命的是网页里充斥着导航栏、推荐位、评论区和各种广告脚本。这些东西在普通屏幕上无所谓,但墨水屏阅读讲究的是沉浸感。一屏就那么点地方,如果三分之一是导航、四分之一是“相关阅读推荐”,真正的正文区域就没多少,翻页效率极低,眼睛来回找文字,比纸质书累得多。
所以,网页转电子书的本质不是换个后缀名,而是做一次内容清洗和重排版。清洗是指去掉所有非正文的页面元素,重排版是指把正文按照阅读器的分页逻辑、字号设置、行距偏好来重新组织。
我测试过不下十种方案,最后稳定下来用的,流程上可以分成三条路线:在线转换、本地批处理、阅读器原生服务。这三条路线对应不同场景,也各有各的坑,下面先把整体思路梳理清楚,再逐个讲细节。
1.2 三条路线怎么选:在线、本地还是原生服务
先说我用下来的感受。在线转换工具适合快速把单篇网页转成电子书文件,比如看到一篇公众号文章、一篇知乎高赞回答,想马上转到阅读器里。这种场景下,本地起环境就有点重了,复制粘贴网址、点几下按钮、下载文件,效率最高。
本地批处理适合断断续续积攒了大量网页链接的情况。比如我追某部连载小说,一天更新两三章,攒一周就有十几个链接。这时候一个个在线转非常低效,我用本地的命令行工具写一个简单的脚本,批量抓取、批量清洗、批量合并,一次处理完所有章节,最后生成一个完整的电子书文件。
阅读器原生服务适合那种长期订阅的内容源,比如某个博客的RSS更新。它不需要手动转换,配置好之后,每天新文章会自动推送到阅读器里,打开就能看,体验最接近订杂志。
这三条路线其实不冲突,甚至可以组合使用。我把它们当成一个工具箱的不同层,按场景选就行。下面进入具体工具和步骤的部分,我把每个环节的操作细节和踩过的坑都列出来。
2. 核心细节解析与实操要点
2.1 在线转换工具怎么用才不踩坑
在线工具里我用得最多的是两个思路:一个是Web to EPUB/PDF这类通用转换服务,一个是浏览器扩展的一键推送。
通用转换服务的核心逻辑,是把网页DOM结构里的正文区域识别出来,再输出成EPUB或PDF。实际用的时候,选择一个能自动提取正文、而不是整个页面截图转PDF的工具很重要。用整个页面转PDF的做法,在墨水屏上就是灾难,不是你看到什么就得到什么,而是把整个网页拉成长条,分页全靠切割,切在图片中间、切在代码块中间都是常有的事。
正确的操作流程是:
- 打开工具页面,粘贴网页链接
- 选择合适的输出格式,EPUB优先,PDF只在排版有特殊要求时才用
- 有些工具允许选择正文识别的起始位置,如果识别到了无关内容,手动拖动选择范围
- 生成之后,这个文件建议先在电脑上转成EPUB检查一下封面目录
实战心得:在线工具对国内一些重排版、多脚本的网站识别率不高。知乎专栏、公众号文章这类相对规范,基本不会出错。但那些论坛、小说站,页面里有大量广告位和分页脚本,提取结果经常把广告文字也混进正文,需要手动清理。
遇到这种情况,我的处理顺序是:先用Pocket或简悦类的阅读模式插件,把网页先抓成一份干净的离线页面,然后再对这份离线页面做转换。相当于先做一次预清洗,再交给转换工具,识别准确率会高非常多。
2.2 本地批处理工具:真正可复制的流程
本地批处理的核心,是找对命令行工具和写对脚本。我主要用的组合是:Curl抓页面,Python加BeautifulSoup做内容清洗,最后用Pandoc转EPUB。这套组合每一个环节都能控制,出错知道错在哪一步,不像在线工具那样是个黑盒子。
先说抓取。有些网页内容不是直接写在HTML里的,而是通过JavaScript异步加载出来的,这种情况下Curl抓到的HTML里根本没有正文。我遇到过一个连载网站,正文得先请求一个API接口,再把返回的内容插进页面里,直接用Curl抓页面只能抓到骨架。我换了一种方式:用Playwright模拟浏览器访问,等页面加载完再抓取渲染后的HTML。这个方法慢一些,但效果稳定。
再说清洗。清洗是整个流程里最关键的环节。美团的页面结构各有各的写法,有的正文在article标签里,有的在div class="content"里,有的干脆没有语义化标签,到处是嵌套的div。我维护着一个针对不同网站的选择器配置,每个配置指定正文的CSS选择器,清洗脚本按配置去提取正文。提取完之后,还有一步很重要的清理:把正文里残留的脚本代码、隐藏元素、空白字符全部移除。
最后是转换。Pandoc可以把清洗好的HTML转成EPUB,这个没问题。但我不想只转章节内容,还想有目录,有封面,最好一章一个文件,阅读器翻页和跳转都方便。所以我的脚本逻辑是:按章节切分内容,每章生成一个HTML片段,再统一交给Pandoc合并生成EPUB。整个过程跑完,从积攒链接到拿到一个排版干净的EPUB文件,大概三分钟。
2.3 E-Ink特有的格式适配细节
EPUB和PDF在墨水屏上的体验差异非常大,这个事要重点说。很多人觉得PDF打印排版好,转成PDF准没错,但现实是PDF是固定版面,字号固定、行距固定,到了阅读器上,要么字太小看着费劲,要么放大之后一行字被裁掉一半,翻页对不齐,体验很糟糕。
EPUB则是流式排版,字号、行距、边距都可以在阅读器上自由调整,屏幕大小不同也能自适应重排。对墨水屏来说,EPUB是绝对优先选择。Kindle甚至可以直接推送EPUB文件,它自己会再转一遍。
如果你追求的是像纸质书那样的阅读体验,我建议转换之后的文件用Sigil之类的工具做一次最终检查。主要看三件事:目录是否完整、章节标题是否正确识别、图片有没有超出屏幕宽度。图片超宽的问题在小说阅读场景里不常见,但看技术教程和带截图的长文时经常遇到,我一般会把过宽的图片统一等比缩放,保底在阅读器上完整体验。
字体方面也值得多说一句。中文阅读器通常内置了好几种中文字体,但如果你传的EPUB里指定了不存在的字体样式,阅读器会用默认字体替代,理论上不影响阅读。但有些EPUB会在CSS里硬编码字号单位,比如用pt或px固定字号,这样在阅读器上调整字号就不生效。我的做法是生成EPUB前,把所有字号相关的CSS全部清理掉,让阅读器的全局字号设置来接管,这样最舒服。
2.4 阅读器原生服务的配置思路
如果你用的是Kindle、掌阅、文石这类主流阅读器,它们都有各自的推送服务。Kindle的Send to Kindle、掌阅的WiFi传书等,本质上都是可以把网页内容生成文件后推送到设备上。
阅读器原生服务里最值得花时间配置的,是RSS推送。订阅一个博客的RSS,配置好之后,博客更新了,阅读器里就能直接出现新文章。这个也不是从零做起的,用现成的RSS服务也能解决,但如果你想完全自己掌控,思路也很清楚:用个轻量的脚本定时抓取RSS条目,转成EPUB推送进阅读器。
这块我踩过的一个坑是图片处理。RSS里的图片链接,有些是相对路径,有些是防盗链的。防盗链的问题在阅读器上特别明显,图片直接显示成一个裂开的图标。解决办法是下载图片到本地,转成EPUB时把图片一起打包进去,这样图片就随书走了,不会出现加载失败的情况。
配置RSS推送的核心,其实不在技术,而在内容筛选。RSS里经常混着广告软文和一些无关的“推荐阅读”,不加筛选地全推过来,阅读器里就会混进一堆垃圾。所以我在脚本里加了关键词过滤规则,想在推送之前就排除掉大部分无关内容。
3. 实操过程与核心环节实现
3.1 单篇文章快速转换的完整步骤
这个场景最常用,我就以一篇公众号长文为例,把在线转换的完整流程走一遍。
第一步,在电脑浏览器里打开文章页面,用阅读模式插件(简悦、Pocket都可以)先把文章抓下来。注意不要直接复制网页内容粘贴到文本编辑器里——那样会把隐藏的格式代码也带进来,转成EPUB后字体、颜色都乱。
第二步,在Pocket里打开抓取好的文章,确认正文完整、图片正常,然后把它导出成一个包含正文内容的HTML文件。如果你的阅读器支持Pocket绑定,这一步可以省略,直接同步到阅读器客户端就行。
第三步,把HTML文件交给转换工具转EPUB。我用得比较多的是一个叫ebook-converter的本地工具,它底层其实调的是Calibre的命令行接口,稳定可靠。有一个关键参数要注意:转换时设置--base-font-size=12,这个数值不是随便定的,是配合阅读器默认字号比例算过的,能让字在墨水屏上显示得不大不小,刚好是纸质书的感觉。
第四步,手机或电脑上把生成的EPUB文件通过网盘、邮箱附件或数据线传到阅读器里。Kindle用户可以直接用Send to Kindle网页版,掌阅用户用WiFi传书,文石用户用内置的微信直传也方便。
这四步看起来简单,实际很多人拦在第一步。用阅读模式插件先抓一遍,核心意义在于完成了90%的清洗工作,后面转换输出出来的文件,排版已接近出版物的水准。
3.2 批量抓取连载小说:一个可复用的脚本思路
连载小说是网页转电子书最刚需的场景。我追的一部小说每天固定更新两章,攒两周之后一次性转成一本书,在阅读器里能连续看到最新章节。这里就把我用的脚本思路展开讲,为了方便理解,我把它拆成几个关键步骤。
第一步,准备链接列表。我在浏览器里打开小说目录页,右键检查出所有章节链接,复制成一个文本文件,每行一个URL。
第二步,抓取页面。用Python脚本逐个请求,拿到每章页面的HTML。这里必须加请求间隔,不然很容易触发对方服务的访问频率限制,而且对别人服务器也不够友好。
第三步,提取正文。根据我维护的配置,定位正文所在的DOM节点,抽出纯净的文本,同时保留段落结构。这一步的细节在于,很多小说网站正文分页,每章可能有两页、三页,需要把分页的链接也抓下来,合并成一章完整内容。
第四步,清洗合并。把每一章的标题统一成「第X章 XXX」的格式,加上作者名、书名信息,最后合并生成一个EPUB文件。注意,这里的EPUB要带目录,每个章节生成一个导航点,这样在阅读器里才能直接从目录跳转。
这一步脚本写完之后,我后续使用只需要维护选择器配置,碰到网站改版,哪个站提取不出来了,更新一下选择器就行。整个流程的核心不在代码量,而在对目标网站结构的持续跟踪和维护。
关于小说EPUB的目录生成,我坚持一个原则:章节标题里不能带乱码和时间戳。有些小说站的标题格式不统一,比如有时带更新时间,有时不带。我脚本里专门做了一个标题清洗的步骤,把更新时间、站名后缀这些无关信息全部去掉,保证目录显示干净。
3.3 如何把图片、表格、代码块处理到可读状态
小说场景基本不涉及图片表格,但技术文章、教程类网页,转换时三样东西最头疼:图片、表格、代码块。
图片的处理思路,核心是“本地化”。在转EPUB前把网页里所有图片下载到本地,路径改成本地相对路径,图片超过屏幕宽度的,用工具统一缩放到合适尺寸。我一般会把图片宽度限制在转换为阅读器屏幕宽度的90%左右,留出边距呼吸感,看起来不会顶着屏幕边缘。
表格在EPUB里的表现一直不理想。EPUB对复杂表格的支持很弱,有很多阅读器渲染会错位,横竖线消失。我的处理方式两种:表格不大且关键信息重要的话,用脚本把表格转成简化结构;表格很大且横屏才能看的话,干脆转成高清图片插入。理由是墨水屏的分页逻辑对表格的兼容远不如图片稳。
代码块的处理最特殊。代码最怕的就是换行和缩进被打乱,一打乱,逻辑就看不懂了。我用代码块包裹<pre>标签,配上专门的CSS样式,保持缩进和空格。同时关闭自动换行,让代码在横屏下完整展示,不然小屏设备上代码缩进全飘。
有一点要提醒:如果转出来的EPUB在阅读器上代码区域显示成一团黑块,大概率是CSS样式没生效。阅读器对EPUB内置CSS的支持各有差异,最常见的表现就是不认识background-color这类属性。我的对策是不同品牌阅读器上,代码块的背景色统一不加,只靠字数缩进区分,反而最通用。
3.4 目录、封面、元数据:让电子书像本“真书”
一个被人忽略的细节是元数据。EPUB文件里包含了书名、作者、简介等信息,这些信息会在阅读器的书架界面显示。很多转换工具默认把书名设成网页的标题标签,结果书架上一排“某某网站 - 文章详情页”,看着很乱。
我习惯在转换时把这三项信息手动指定好:书名、作者、语言。
- 书名抓网页里的一级标题,如果有固定的排版风格就按格式规范成「网名 · 标题」
- 作者写原作者的名字,而不是网站名
- 语言统一标记为zh-CN,这样在阅读器里中英文混排的标点处理和换行规则才会正确
封面这个事,如果你是给连载小说做合集,建议单独配一张封面图。没有封面也能看,但书架上一堆灰色默认图,翻找时很难靠视觉区分。我用的是最简单的方式:用工具把书名文本渲染成一张图片,尺寸直接按Kindle的推荐比例设置,再作为封面文件嵌入。
这里有一个实操心得:不要用网页里的截图当封面,分辨率不一定够,而且颜色不对,在墨水屏上会显得很脏。纯文本封面的干净程度,远超过截图封面。
4. 常见问题与排查技巧实录
4.1 转换出来的EPUB在阅读器上字体忽大忽小
这个问题我遇到得最多。表现是章节之间、段落之间的字号不统一,有的段落字体明显偏大,有的偏小。
排查思路:用Sigil打开EPUB的CSS文件,查看是不是有多处重复定义字号。网页转换过来的HTML经常会带内联样式,有些段落里直接写了font-size: 18px,有些段落没写,阅读器就用全局字号,于是忽大忽小。
解法:写一个小的清理脚本,把HTML里所有标签的style属性全部删除,只保留正文和标题的语义结构,让阅读器的全局样式统一接管。不要怕损失什么,网页里的内联样式本来就不适合阅读器场景。
4.2 推送到阅读器后,图片集体显示不出来
这也是高频问题。之前在电脑上打开EPUB图片显示正常,推到阅读器里就全是裂图。原因在图片路径:转换工具生成EPUB时,图片路径写的是绝对路径(比如file:///C:/...),而不是EPUB内部相对路径。阅读器拿到文件后,内部结构变了,绝对路径就失效了。
排查步骤:用解压软件打开EPUB文件,进入OEBPS或images目录,确认图片文件存在,再打开对应的.xhtml文件,查看<img>标签的src属性。如果是http://开头或者绝对路径,就说明路径不对。
固定解法:转换后统一做一次路径修复,把所有图片引用改成相对路径。如果你用Calibre转换,它有自动修复机制,但未必每次都靠谱,建议改完之后重新压缩成EPUB验证一下。
4.3 在线阅读工具识别错正文,把评论区也当内容
在线转换工具是把整个网页的内容提取出来,遇到评论区火热、正文之后跟了很长一段推荐阅读的情况,工具经常把握不住边界,把评论区也揉进正文,生成的书后半段全是一堆无关讨论。
我的解法有两个:
- 尽量用阅读模式插件先抓取,再做转换。阅读模式插件的正文识别算法通常比通用转换工具强很多。
- 在线工具如果允许手动指定正文区域,在页面上直接框选范围。这个一劳永逸的办法是用户体验最直接最有效的。
另一个思路是CSS选择器黑名单。如果你用本地脚本方案,可以在配置里指定哪些选择器的内容必须移除,比如.comment-area、.recommend-list、#footer等。这个名单可以跟随网站维护,时间长了效果非常稳定。
4.4 生成的EPUB在阅读器上目录空白
目录空白常见于批量转换场景,尤其是章节链接没提取全、章节标题为空的时候。转换工具生成目录时,每个章节标签需要有title属性,如果标题为空,目录节点就无法生成。
排查思路:打开EPUB的toc.ncx或nav.xhtml文件,看目录条目是否存在。如果存在但阅读器上空白,可能是阅读器对EPUB3的导航格式支持不完整,可以转用EPUB2格式。这里又要提到Calibre的转换,它可以在两种版本之间互转,保留目录结构。
另一个可能的原因是用长文件名当章节名,目录里显示不完整。我建议章节标题控制在20个字以内,长标题截断或改写,一级目录显示时观感好很多。
4.5 批量转换时经常漏掉某些章节,该怎么排查
批量转换最怕静默失败:脚本跑了半天,声称完成了,结果生成的书少了最后三章,排查起来很费劲。我现在的做法是在脚本里加了输出日志,每处理完一个章节都打印一条记录,包括URL、标题、提取到的文字长度。如果某个章节的文字长度明显偏短,比如只有10个字,那基本可以断定提取失败。
造成漏章原因就两类:一类是页面结构不一样,有的章节页有“上一章/下一章”按钮,有的页面缺这个导航,导致脚本认为没有分页;另一个是反爬机制拦截了部分请求,返回了一个验证页面,而不是正文。
对于前者,增强配置的兼容性,对不同页面结构分别处理。对于后者,加请求间隔、加浏览器识别信息,大多数情况下能解决。如果你碰到的是那种非常严格的防护,我建议放弃自动化,直接手动打开网页复制正文,虽然费点功夫,但最稳。
4.6 字体导入:如何让中文EPUB在阅读器上更舒服
墨水屏阅读器的默认中文字体通常够了,但如果你对阅读密度有要求,可以自己导入字体。Kindle和图瑞讯这类阅读器都支持字体文件放在指定目录,转换出来的EPUB里也能内嵌字体。
内嵌字体的坑主要在文件大小。一个标准中文字体重则有十几MB,内嵌进EPUB,整个文件会变得非常臃肿,阅读器打开和翻页都受影响。我的建议是别内嵌,除非你真需要宋体以外的特殊字形。字体放在阅读器本地,EPUB本身不指定字体,阅读器会按你设置的字形渲染。
字号与行距的推荐值也分享一下:阅读器全局字号设为“中”或“较大”,行距设为1.5倍,边距设为中等。这套参数配合干净排版,在墨水屏上读一小时眼睛基本不累。具体参数各家阅读器略有出入,但原则很简单:正文区字体在屏幕上显示出来的视觉大小,不要小于纸质书小五号字。所有设置都以这个视觉大小为准。
4.7 长文转PDF的替代思路:什么时候放弃EPUB
EPUB虽说通常是最优选,但有些内容真的不适合流式排版。比如那种带大量表格、图表、特殊排版的网页文档,转成EPUB后结构会很乱。这时候我的选择是:放弃EPUB,用浏览器的“完整网页截图”功能把整个页面按等宽长图导出,再切割成适合阅读器的分页。严格来说这是一个降级方案,但在表格型内容面前,图片格式远比EPUB的残缺表格可靠。
另外一个场景是代码教程。代码块的缩进和等宽特性,在EPUB里很难稳定渲染,而生成横屏PDF后,代码展示完整、不乱跳。我的习惯是:纯文字内容走EPUB,代码密集的内容走PDF,图片表格特别多的内容也走PDF。方案选择没有绝对,合不合适才是重点。
这个取舍我在多次使用后想明白一件事:网页转电子书的本质是提取内容和适配设备,不是执着于某一种文件格式。先评估内容结构,再决定输出格式,准确率能提升很多,也少走很多弯路。
5. 一些私藏的实操心得
说几个不太好写进教程、但实际帮我省了很多事的细节。
第一,本地脚本方案里,请求数据的频率一定要控制。有一次我为了测试脚本,在短时间内请求了同一网站大量页面,结果整个请求队列被限制访问,后面半小时什么都拉不回来。现在我的脚本里都固定了一个请求间隔,宁可慢一点,也不要触发限制。
第二,RSS推送方案在批量抓完新文章之后,最好再加一个去重逻辑。因为RSS服务偶尔会重复推送同一篇文章,去重逻辑按文章标题做一个简单判断就够。
第三,EPUB文件传到阅读器后,第一件事是检查目录,第二步是跳转书里最后几页,确认文件没在第99%的地方损坏。有几次我转出来的书,前面看着一切正常,但结尾几章缺失或乱码。养成这个习惯之后,再没发生过在阅读器里兴致勃勃打开一本坏书的事。
第四,如果你反复转换同一类型的网站,强烈建议把清洗规则沉淀成一个模板。这个模板不用很复杂,它本质上就是一份“网站域名对应正文选择器”的配置表。每天都有新站点加进来,维护久了,转换成功率会非常高。
这一套流程用下来,我现在积攒的电子书文件里有技术文章、有小说合集、有教程文档,加起来有几千本书。平时常用的反倒是每天推送的博客文章订阅,阅读器安安静静躺在床头,晚上躺下打开,想看的都在,眼睛不累,心情也好。写这些,希望对同样折腾过网页转电子书的朋友有点帮助。