ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

calibre 新闻配方(Recipe)开发实战:从零创建与定制新闻电子书

calibre 新闻配方(Recipe)开发实战:从零创建与定制新闻电子书 calibre 新闻配方Recipe开发实战从零创建与定制新闻电子书【免费下载链接】calibreThe official source code repository for the calibre ebook manager项目地址: https://gitcode.com/GitHub_Trending/ca/calibre导读manual/news.rst是 calibre 官方文档中讲解新闻下载框架Recipe 框架的权威指南。calibre 内置了一套强大、灵活且易用的框架用于从互联网下载新闻并转换为电子书。本文以该文档为核心骨架结合 BasicNewsRecipe 源码 与仓库内置 recipes 的实际实现系统讲解从仅提供一个 RSS 地址即可自动抓取到通过 Python 代码深度定制抓取流程的完整进阶路径。读完本文你将掌握在 calibre GUI 中创建自定义新闻源、使用高级模式编写print_version/parse_index/preprocess_html等钩子方法、以及用ebook-convert命令行高效调试配方的方法。一、Recipe 框架概览一切新闻源的载体calibre 将下载某个新闻源所需的全部信息源地址、抓取规则、内容清洗规则、电子书排版样式等封装为一个recipe配方。用户只需要为每个想订阅的新闻网站创建一个 recipe之后点击获取新闻按钮即可一键生成电子书。从源码看配方的核心基类是BasicNewsRecipe定义于 src/calibre/web/feeds/news.py其类文档说明通过逐步覆写该类中的功能可以做出越来越定制化、越来越强大的配方。它提供了大量可供覆写的类属性和方法本文后面的实战会逐一触达。按官方文档的引导最佳学习路径是按顺序完成下面几个由浅入深的例子完全自动抓取——适用于提供完整内容full-contentRSS的博客定制抓取流程——针对只有摘要、正文在网页里的新闻源改用打印版本页面替换文章样式——关闭网站的 CSS规避字号过小等排版问题裁剪与改写内容——用remove_tags/extra_css对 HTML 进行精细手术真实案例——解析《纽约时报》完整配方见识parse_index、preprocess_html等高级 API。二、完全自动抓取从 calibre Blog 开始2.1 前提源必须提供完整内容 RSScalibre Blogcalibre 官方博客的每篇文章都完整嵌入在 RSS 中属于full-content feeds。因此抓取这种源几乎不需要任何定制只需提供 URLhttp://blog.calibre-ebook.com/feeds/posts/default在博客页面底部 Subscribe to订阅区域选择Posts - Atom即可找到上述 RSS 地址。2.2 GUI 操作步骤在 calibre 主界面中右键点击Fetch news获取新闻按钮选择Add a custom news source添加自定义新闻源菜单项点击New Recipe新建配方按钮弹出新建配方对话框见上方截图。在对话框中填写字段填写内容说明Recipe title配方标题Calibre Blog最终生成的电子书标题Oldest article最早文章按需设置控制从每个 feed 下载多早之前的文章天数Max. number of articles最大文章数按需设置控制从每个 feed 最多下载多少篇文章Feed title订阅源标题如Calibre Blog该 feed 在电子书中的栏目名Feed URL订阅源地址RSS 地址填入上文获取的 Atom 地址填写 feed 标题与 URL 后点击Add feed添加订阅源再点击Save保存并关闭对话框配方即创建完成。2.3 测试下载点击Fetch news按钮在Custom news sources自定义新闻源子菜单中点击Calibre Blog。几分钟后下载好的博客文章电子书会出现在主书库视图若已连接阅读器则会直接放入阅读器而非书库。选中该书并点击View阅读即可阅读。从源码看自动抓取之所以零配置即可成功是因为下载器会基于 feed 内嵌内容长度自动猜测是否包含完整文章见 use_embedded_content 属性 的说明默认None表示按嵌入内容长度自动判断可强制设为True/False。但对大多数只有摘要、正文在网页上的新闻源就需要进入下一阶段了。三、抓取摘要型源bbc.co.uk 的第一次尝试BBC 提供的是摘要型 RSS——feed 里只有文章链接和简短摘要完整文章是一张独立网页。官方文档以 BBC 的两个 feed 为例News Front Pagehttps://newsrss.bbc.co.uk/rss/newsonline_world_edition/front_page/rss.xmlScience/Naturehttps://newsrss.bbc.co.uk/rss/newsonline_world_edition/science/nature/rss.xml按上一节流程为 BBC 创建配方并下载后你会发现calibre 已经能从每篇文章的网页中提取出主要内容但提取并非完美——可能残留菜单、导航等无用内容也可能误删文章标题等有效内容。此时就需要定制抓取流程。四、高级模式定制抓取流程在Add custom news sources添加自定义新闻源对话框中点击Switch to Advanced mode切换到高级模式按钮即可进入配方的代码形态——基础模式填写的字段会被自动翻译成等价的 Python 代码。4.1 最容易见效的定制使用打印版本打印版本print version的页面通常杂质更少转换为电子书的效果好得多。操作思路在上一节下载的电子书中每篇文章末尾有一小段说明其来源 URL 的文字把该 URL 复制到浏览器打开在文章网页上寻找指向 Printable version打印版本的链接并点击对比两个 URL 的差异。以文档中的 BBC 文章为例文章 URL https://news.bbc.co.uk/2/hi/science/nature/7312016.stm 打印版本 URL https://newsvote.bbc.co.uk/mpapps/pagetools/print/news.bbc.co.uk/2/hi/science/nature/7312016.stm可见规律把每个文章 URL 都加上前缀newsvote.bbc.co.uk/mpapps/pagetools/print/即可得到打印版本。在高级模式对话框中只需要为配方追加两行代码def print_version(self, url): return url.replace(https://, https://newsvote.bbc.co.uk/mpapps/pagetools/print/)注意这是 Python 代码缩进至关重要def行必须顶格或与类内其他方法对齐。print_version是BasicNewsRecipe提供的钩子方法它对每一篇文章都会被调用参数url是文章原始 URL返回值是新 URL。在 源码 中基类默认实现直接抛出NotImplementedError即不做任何改写子类覆写后即可实现 URL 改写官方文档给出的另一个典型例子是return url ?pagewantedprint。保存后点击Add/update recipe重新下载即可得到明显改善的电子书。4.2 关闭样式表解决字号问题打印版本网页的字号往往偏小转换时 calibre 会尝试自动修正但修正后菜单、导航栏的字号相对正文反而显得过大——因为这些字号通常由网站的 CSS 样式表控制。解决办法是禁止下载这些样式表在配方中加一行no_stylesheets True在 源码 中no_stylesheets的默认值是False文档注释说明对于样式表过度复杂、不适合转换为电子书格式的网站将其置为True即可跳过样式表的下载与处理。注意这一招会丢弃网页自带的所有样式后续需要用extra_css自行补充适合电子书的排版。五、裁剪与改写remove_tags 与 extra_csscalibre 对已下载内容的操作能力非常强大。仍以 BBC 配方为例查看几篇打印版文章的 HTML 源码可以发现每篇文章末尾有一段无用的页脚结构为div classfooter ... /div通过remove_tags属性即可将其整体移除remove_tags [dict(namediv, attrs{class:footer})]再为之前被no_stylesheets禁用的样式补充我们自己的 CSS用于电子书排版extra_css .headline {font-size: x-large;} \n .fact { padding-top: 10pt }remove_tags的匹配规则在 源码注释 中有详细说明每个待删除标签是一个字典name键指定标签名如divattrs键指定属性匹配如{class: footer}所有键均可选匹配语义遵循 BeautifulSoup 的搜索规则。更常见的写法还有remove_tags [dict(namediv, class_advert)]表示删除所有div classadvert及其全部子节点。而extra_css会被插入到每个下载 HTML 文件的style标签中、/head之前从而覆盖除元素内联style属性以外的所有 CSS见 源码。如果你想程序化生成 CSS也可以覆写get_extra_css()方法见 源码。至此BBC 配方已具备生产级品质。但 recipe 框架的能力远不止于此下面通过《纽约时报》这个真实案例见识更完整的 API。六、真实案例《纽约时报》配方逐段解析以下是官方文档给出的《纽约时报》The New York Times完整配方它暴露了BasicNewsRecipe的更多 APIimport string, re from calibre import strftime from calibre.web.feeds.recipes import BasicNewsRecipe from calibre.ebooks.BeautifulSoup import BeautifulSoup class NYTimes(BasicNewsRecipe): title The New York Times __author__ Kovid Goyal description Daily news from the New York Times timefmt [%a, %d %b, %Y] needs_subscription True remove_tags_before dict(idarticle) remove_tags_after dict(idarticle) remove_tags [dict(attrs{class:[articleTools, post-tools, side_tool, nextArticleLink clearfix]}), dict(id[footer, toolsRight, articleInline, navigation, archive, side_search, blog_sidebar, side_tool, side_index]), dict(name[script, noscript, style])] encoding cp1252 no_stylesheets True extra_css h1 {font: sans-serif large;}\n.byline {font:monospace;} def get_browser(self): br BasicNewsRecipe.get_browser(self) if self.username is not None and self.password is not None: br.open(https://www.nytimes.com/auth/login) br.select_form(namelogin) br[USERID] self.username br[PASSWORD] self.password br.submit() return br def parse_index(self): soup self.index_to_soup(https://www.nytimes.com/pages/todayspaper/index.html) def feed_title(div): return .join(div.findAll(textTrue, recursiveFalse)).strip() articles {} key None ans [] for div in soup.findAll(True, attrs{class:[section-headline, story, story headline]}): if .join(div[class]) section-headline: key string.capwords(feed_title(div)) articles[key] [] ans.append(key) elif .join(div[class]) in [story, story headline]: a div.find(a, hrefTrue) if not a: continue url re.sub(r\?.*, , a[href]) url ?pagewantedall title self.tag_to_string(a, use_altTrue).strip() description pubdate strftime(%a, %d %b) summary div.find(True, attrs{class:summary}) if summary: description self.tag_to_string(summary, use_altFalse) feed key if key is not None else Uncategorized if feed not in articles: articles[feed] [] if not podcasts in url: articles[feed].append( dict(titletitle, urlurl, datepubdate, descriptiondescription, content)) ans self.sort_index_by(ans, {The Front Page:-1, Dining In, Dining Out:1, Obituaries:2}) ans [(key, articles[key]) for key in ans if key in articles] return ans def preprocess_html(self, soup): refresh soup.find(meta, {http-equiv:refresh}) if refresh is None: return soup content refresh.get(content).partition()[2] raw self.browser.open(https://www.nytimes.comcontent).read() return BeautifulSoup(raw.decode(cp1252, replace))6.1 时间格式timefmttimefmt [%a, %d %b, %Y]该属性设置电子书首页显示的时间格式即星期, 日 月, 年如[Fri, 05 Sep, 2026]。在 源码 中默认值为 [%a, %d %b %Y]格式化指令遵循 Pythonstrftime语法。6.2 内容清洗指令组remove_tags_before dict(idarticle) remove_tags_after dict(idarticle) remove_tags [dict(attrs{class:[...]}), dict(id[...]), dict(name[script, noscript, style])]这三个属性配合使用作用分别是remove_tags_before删除第一个匹配标签之前的所有内容源码remove_tags_after删除第一个匹配标签之后的所有内容源码remove_tags删除所有匹配的标签及其子节点源码。本配方用dict(idarticle)把正文锁定在article idarticle范围内并批量清除侧边栏、页脚、脚本等杂物。同类属性还有remove_attributes删除所有标签上的指定属性如[style, font]、keep_only_tags只保留匹配标签及其子节点其余清空、preprocess_regexps在 HTML 上执行正则替换源码。6.3 付费订阅needs_subscription 与 get_browserneeds_subscription Trueneeds_subscription True告诉 calibre访问该源需要用户名和密码因此每次使用该配方时 calibre 都会向用户询问凭据设为optional则凭据可选见 源码。配方的get_browser()方法覆写了基类实现负责实际登录 NYT 网站先调用基类BasicNewsRecipe.get_browser(self)获得浏览器实例再模拟填写登录表单并提交。登录成功后calibre 会复用同一个已登录的浏览器实例抓取全部内容。从 源码 可见基类get_browser的默认行为返回一个支持 Cookie、忽略 robots.txt、处理页面刷新、附带常见随机 User-Agent 的 mechanize 浏览器实例。此外源码还提供了browser_type属性默认mechanize可改为webengine真实 Chromium 内核或qtQt 网络后端二者都支持 HTTP/2、更不容易被反爬机制识别。注意机制若配方覆写了get_browser多线程下载时会通过clone_browser克隆浏览器实例以保证线程安全源码。6.4 解析报纸版面parse_indexparse_index()的任务是打开纽约时报今日报纸索引页https://www.nytimes.com/pages/todayspaper/index.html解析出当天报纸的文章清单。它比简单使用 RSS 复杂但生成的电子书与当日报纸版面高度吻合。源码 明确规定了parse_index的契约返回值必须是列表每个元素是(feed title, list of articles)二元组每篇文章是一个字典支持title、url、date、description、content、author等键。该方法存在时会优先于默认的parse_feeds被调用。本配方中值得注意的技巧index_to_soup()便捷方法把索引页 URL 抓下来并解析成 BeautifulSoup 对象源码用soup.findAll按 CSS class 定位版面标题section-headline与文章块story把文章归类到各版面re.sub(r\?.*, , a[href])去掉 URL 中的查询参数再追加?pagewantedall以请求完整文章sort_index_by()便捷方法按权重字典调整版面顺序让头版排在最前源码。如果你不喜欢 BeautifulSoupcalibre 还自带lxml与html5lib两种推荐解析器。用它们替代index_to_soup()的标准调用方式为raw self.index_to_soup(url, rawTrue) # For html5lib import html5lib root html5lib.parse(raw, namespaceHTMLElementsFalse, treebuilderlxml) # For the lxml html 4 parser from lxml import html root html.fromstring(raw)index_to_soup(url, rawTrue)会返回原始 HTML 字符串而不是 BeautifulSoup 对象见 源码 中raw参数的分支处理。6.5 任意变换 HTMLpreprocess_htmlpreprocess_html(soup)可对每一篇下载的 HTML 页面执行任意变换。本配方用它绕过 NYT 在每篇文章前展示的广告页如果页面含有meta http-equivrefresh跳转标签就解析出真实目标地址并重新抓取。源码 指出preprocess_html是在remove_tags等清洗属性之后被调用的而更早的钩子preprocess_raw_html源码则作用于 HTML 尚未解析成对象树之前、先于preprocess_regexps。相关钩子还有postprocess_html抓取与链接解析之后源码、skip_ad_pages跳过广告页源码等。若某篇文章不应被下载可在预处理方法中调用abort_article()中止源码。七、开发新配方的实用技巧命令行调试开发配方的最佳方式是利用命令行界面用你熟悉的 Python 编辑器编写配方保存为myrecipe.recipe.recipe扩展名是必需的用下面的命令测试下载ebook-convert myrecipe.recipe .epub --test -vv --debug-pipeline debug各参数含义参数作用ebook-convert myrecipe.recipe .epub下载所有网页并生成 EPUB 文件myrecipe.epub--test只从至多两个 feed 中各下载少量文章用于快速验证测试模式下get_feeds也会被截断见 源码-vv让 ebook-convert 输出大量运行细节日志--debug-pipeline debug把下载到的 HTML 原文保存到debug/input目录下载完成后用浏览器打开debug/input/index.html检查下载与预处理是否正确确认无误后即可生成各种格式的电子书ebook-convert myrecipe.recipe myrecipe.epub ebook-convert myrecipe.recipe myrecipe.mobi ...macOS 提示在 macOS 上命令行工具位于 calibre 应用包内部。例如把 calibre 安装到/Applications时命令行工具位于/Applications/calibre.app/Contents/MacOS/需使用该路径下的ebook-convert。八、深入学习与内置配方想进一步掌握BasicNewsRecipe的更多字段与方法可参考API 文档manual/news_recipe.rstBasicNewsRecipe类及其全部重要方法、字段的自动生成文档基类源码src/calibre/web/feeds/news.pyBasicNewsRecipe定义内含全部属性与钩子方法的权威注释例如oldest_article默认 7 天、max_articles_per_feed默认 100、simultaneous_downloads默认 5、timeout默认 120 秒、delay默认 0 等内置配方仓库 recipes 目录 中存放了数以百计随 calibre 发布的内置配方如guardian.recipe、economist.recipe等是学习各类抓取技巧的宝库配方常用的辅助属性还有feeds支持[url1, url2, ...]或[(title, url), ...]两种形式、encoding覆盖错误字符集声明如cp1252、masthead_urlKindle 刊头图、compress_news_images图片压缩与scale_news_images_to_device按设备屏幕缩放、recipe_specific_options向用户暴露可定制选项、auto_cleanup基于 readability 算法自动提取正文源码等均可按需查阅源码注释获取取值范围与默认值。当你对配方满意、且认为它有足够的需求度时可以将其分享给其他 calibre 用户并有机会被收录进内置配方集合——这正是仓库 recipes 中数百个配方不断壮大的来源。九、小结从本文可以梳理出 calibre 新闻配方的完整进阶路径提供完整内容 RSS 的源可直接在 GUI 基础模式完成只需标题与 URL摘要型源需要切换到高级模式用print_version定向到打印版本页面进一步可用no_stylesheets摆脱网站样式干扰用remove_tags/extra_css裁剪内容、定制排版而面对复杂网站如付费订阅、需要解析版面索引的报纸则可以全面覆写get_browser、parse_index、preprocess_html等钩子方法配合ebook-convert命令行的--test -vv --debug-pipeline快速迭代调试。这套框架的全部能力最终都沉淀在 BasicNewsRecipe 源码 与其 API 文档 manual/news_recipe.rst 中值得每一个配方作者深入研读。【免费下载链接】calibreThe official source code repository for the calibre ebook manager项目地址: https://gitcode.com/GitHub_Trending/ca/calibre创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表