利用calibre的recipe抓取網(wǎng)頁制作電子書

原文網(wǎng)址
https://bookfere.com/post/562.html

之前書伴曾寫過一篇文章《Calibre 使用教程之抓取 RSS 制成電子書》柳琢,介紹了利用 Calibre 的“抓取新聞”功能把網(wǎng)站的新聞源制期刊樣式電子書的方法装诡。不過軟件界面上也只提供了直接添加 RSS 地址的方法壮虫,也就是說網(wǎng)站必須有 RSS 供稿才行,否則就無法抓取思瘟。那對于不提供 RSS 的網(wǎng)站是否能夠抓取它上面的內(nèi)容制成電子書呢荸百?本文就來介紹一種進階技巧來解決這個問題。

在開始具體步驟之前滨攻,先簡單的描述一下工作流程:首先編寫一個 Calibre Recipe 腳本文件够话,根據(jù) Calibre 指定的規(guī)范定義具體的抓取行為,然后使用 Calibre 把此腳本轉(zhuǎn)化成 mobi 格式電子書文件铡买。

注意更鲁,本文的相關(guān)操作是在命令行中進行的,并且會牽涉到簡單的代碼編寫奇钞,為了讓更多沒有編程基礎(chǔ)的小伙伴能直接上手使用澡为,本文會盡可能詳細的解釋每一條代碼的作用,以便套用景埃。

一媒至、認識 Calibre Recipe 腳本

Recipe 這個單詞的含義為“食譜”、“處方”谷徙,顧名思義拒啰,它為 Calibre 定義了抓取新聞源這一動作的執(zhí)行細節(jié)。Calibre 也為 Recipe 腳本提供了一份詳盡的文檔“API documentation for recipes”完慧,對所能使用的參數(shù)或函數(shù)做了詳細的說明谋旦。如果你有編程基礎(chǔ),可能感覺直接查看它的源代碼會更清晰一些。

在抓取 RSS 制成電子書那篇文章中册着,我們只需要在 Calibre 軟件界面上拴孤,通過“添加自定義新聞源(Add or edit a custom news source)”菜單項調(diào)出操作面板,在里面添加 RSS 地址就完事兒了甲捏,剩下的抓取演熟、轉(zhuǎn)換工作就全部交給 Calibre 自動處理了。其實在這個過程的背后司顿,Calibre 也是根據(jù)你添加的 RSS 地址自動生成了一個 Recipe 腳本芒粹,并根據(jù)此腳本抓取內(nèi)容的〈罅铮可以點擊“添加自定義新聞來源”操作面板左下角的【切換到高級模式】(Switch to advanced mode)按鈕化漆,便可以看到如下所示代碼:

#!/usr/bin/env python2
# vim:fileencoding=utf-8
from __future__ import unicode_literals, division, absolute_import, print_function
from calibre.web.feeds.news import BasicNewsRecipe

class AdvancedUserRecipe1504764482(BasicNewsRecipe):
    title          = 'My news source'
    oldest_article = 7
    max_articles_per_feed = 100
    auto_cleanup   = True

    feeds          = [
        ('科學松鼠會', 'http://songshuhui.net/feed'),
        ('泛科學', 'http://pansci.tw/feed'),
    ]

從以上這個簡單的 Recipe 腳本中,我們可以看到此腳本繼承了 Calibre 提供的 BasicNewsRecipe 這個類猎提,并簡單的重寫了一下這個類的某些參數(shù)获三。由于 Calibre 可以自動處理標準的 RSS 結(jié)構(gòu)旁蔼,所以不需要我們額外修改就可以輕松抓取內(nèi)容锨苏。但是對于不提供 RSS 的網(wǎng)站內(nèi)容又該如何處理呢?

對于不提供 RSS 的網(wǎng)站棺聊,我們可以通過解析頁面內(nèi)容伞租,獲取一個數(shù)據(jù)結(jié)構(gòu)再進行轉(zhuǎn)換。Calibre Recipe 腳本提供的 parse_index() 方法就可以用來做這件事限佩。下面我們就來編寫一個簡單的 Recipe 腳本葵诈。

<small>提示:Calibre Recipe 腳本的 parse_index() 方法需要解析網(wǎng)站頁面的代碼結(jié)構(gòu)來提取數(shù)據(jù),但由于不同網(wǎng)站的代碼結(jié)構(gòu)也不相同祟同,從而處理邏輯也會有所差異作喘,所以抓取不同的網(wǎng)站內(nèi)容,可能就需要寫一個與之相對應(yīng)的 Recipe 腳本晕城。</small>

二泞坦、編寫 Calibre Recipe 腳本

下面以王垠的博客“當然我在扯淡”為例,編寫一個 Recipe 腳本砖顷,將整個博客內(nèi)容轉(zhuǎn)制成 mobi 格式的電子書贰锁。這個博客頁面結(jié)構(gòu)比較簡單,個人感覺比較適合上手滤蝠,初步了解一些基本的 Recipe 腳本寫法豌熄。

在開始編寫代碼之前我們先來分析一下這個博客的頁面結(jié)構(gòu):博客的首頁即是全部文章列表,列表中每一篇文章的標題被被類選擇器 li.list-group-item 包裹著物咳。這樣我們就可以提取出所有文章的標題和文章鏈接锣险,并據(jù)此循環(huán)處理每一篇文章內(nèi)容,組合成可供 Calibre 轉(zhuǎn)換的數(shù)據(jù)結(jié)構(gòu)。

下面是可用的 Recipe 腳本代碼芯肤,代碼中每一行都做了注釋夯接。看不懂可以看下面的詳細解釋纷妆。

#!/usr/bin/python
# encoding: utf-8

from calibre.web.feeds.recipes import BasicNewsRecipe # 引入 Recipe 基礎(chǔ)類

class Wang_Yin_Blog(BasicNewsRecipe): # 繼承 BasicNewsRecipe 類的新類名

    #///////////////////
    # 設(shè)置電子書元數(shù)據(jù)
    #///////////////////
    title = '當然我在扯淡' # 電子書名
    description = u'王垠的博客' # 電子書簡介
    #cover_url = '' # 電子書封面
    #masthead_url = '' # 頁頭圖片
    __author__ = '王垠' # 作者
    language = 'zh' # 語言
    encoding = 'utf-8' # 編碼

    #///////////////////
    # 抓取頁面內(nèi)容設(shè)置
    #///////////////////
    #keep_only_tags = [{ 'class': 'example' }] # 僅保留指定選擇器包含的內(nèi)容
    no_stylesheets = True # 去除 CSS 樣式
    remove_javascript = True # 去除 JavaScript 腳本
    auto_cleanup = True # 自動清理 HTML 代碼
    delay = 5 # 抓取頁面間隔秒數(shù)
    max_articles_per_feed = 999 # 抓取文章數(shù)量

    #///////////////////
    # 頁面內(nèi)容解析方法
    #///////////////////
    def parse_index(self):
        site = 'http://www.yinwang.org' # 頁面列表頁
        soup = self.index_to_soup(site) # 解析列表頁返回 BeautifulSoup 對象
        links = soup.findAll("li",{"class":"list-group-item title"}) # 獲取所有文章鏈接
        articles = [] # 定義空文章資源數(shù)組
        for link in links: # 循環(huán)處理所有文章鏈接
            title = link.a.contents[0].strip() # 提取文章標題
            url = site + link.a.get("href") # 提取文章鏈接
            a = {'title': title , 'url':url} # 組合標題和鏈接
            articles.append(a) # 累加到數(shù)組中
        ans = [(self.title, articles)] # 組成最終的數(shù)據(jù)結(jié)構(gòu)
        return ans # 返回可供 Calibre 轉(zhuǎn)換的數(shù)據(jù)結(jié)構(gòu)

首先引入 Calibre 提供的基礎(chǔ)類 BasicNewsRecipe 并創(chuàng)建一個繼承基礎(chǔ)類的新類 Wang_Yin_Blog盔几。

接下來重寫一些可作為電子書的元數(shù)據(jù)的參數(shù)。如標題掩幢、簡介逊拍、作者、語言际邻、編碼之類芯丧。注意上面代碼中 cover_urlmasthead_url 這兩個參數(shù)被注釋掉了,這樣 Calibre 會自動生成封面和期刊頭世曾。如果你想要自定義電子書封面和期刊頭缨恒,可以使用這兩個參數(shù)指定圖片的路徑。

然后還需要設(shè)置控制抓取頁面所需要的一些參數(shù)轮听。如去除電子書不需要的 CSS 樣式和 Javascript 腳本骗露,設(shè)定抓取頁面的時間間隔(避免對目標服務(wù)器造成負擔),設(shè)定抓取文章的數(shù)量(如果想要抓取所有文章設(shè)置一個足夠大的數(shù)值即可)等血巍。注意以上代碼中有一個 auto_cleanup 參數(shù)萧锉,它會用可讀性算法自動清理 HTML 標簽提取頁面中的有用內(nèi)容。如果頁面內(nèi)容比較復(fù)雜述寡,還可以使用 keep_only_tags 這個參數(shù)柿隙,指定僅提取頁面中某個標簽中的內(nèi)容,因為本例頁面內(nèi)容較簡單就注釋掉了鲫凶。

相關(guān)參數(shù)設(shè)置完畢后禀崖,就可以編寫處理頁面內(nèi)容的 parse_index() 方法了。在此方法中 Calibre 使用了內(nèi)置的 Python 模塊 BeautifulSoup螟炫。首先把首頁的文章列表解析成 BeautifulSoup 對象波附,然后提取出所有標題列表,循環(huán)處理這些列表后不恭,最終合并成一個完整的數(shù)據(jù)結(jié)構(gòu)交給 Calibre 轉(zhuǎn)換處理叶雹。

這樣一個簡單的 Recipe 腳本就寫完了,將其保存為 .recipe 文件備用换吧,本例保存為 wangyin.recipe折晦。接下來就可以把這個“小處方”轉(zhuǎn)換成 mobi 格式的電子書文件了。

<small>提示:當然有些網(wǎng)站的情況要復(fù)雜得多沾瓦,比如處理帶分頁的頁面满着、復(fù)雜內(nèi)容類型谦炒,還有多內(nèi)容來源的合并等,這些進階技巧限于篇幅暫不展開风喇。如果感興趣宁改,也可以翻一翻 Calibre 提供的 API 文檔“API documentation for recipes”自行研究一下。</small>

三魂莫、認識命令行工具 ebook-convert

有了寫好的 Recipe 腳本还蹲,接下來的工作就是將其轉(zhuǎn)化成 mobi 格式的電子書文件了。

在《Calibre 使用教程之批量獲取電子書元數(shù)據(jù)》這篇文章中耙考,我們認識了 Calibre 的一個命令行工具 ebook-meta谜喊,它可以獲取電子書的元數(shù)據(jù)。現(xiàn)在要接觸到另外一個命令行工具 ebook-convert倦始,此工具可以把某種格式轉(zhuǎn)換成另一種格式斗遏。比如想要把某個 epub 轉(zhuǎn)換成 mobi,只需要輸入以下命令即可:

ebook-convert BookName.epub BookName.mobi

當然想要使用 ebook-convert 命令需要預(yù)先在電腦里安裝 Calibre鞋邑。在 Windows 系統(tǒng)中诵次,一般安裝完成后即可直接在“命令提示符”中使用。對于 macOS 系統(tǒng)則需要設(shè)置一下環(huán)境變量枚碗,設(shè)置方法和 ebook-meta 一樣逾一,參考《Calibre 使用教程之批量獲取電子書元數(shù)據(jù)》這篇文章中的“準備 ebook-meta 工具”。

四视译、把 Recipe 腳本轉(zhuǎn)化為 mobi 文件

和轉(zhuǎn)換普通的電子書的格式一樣嬉荆,只需要輸入以下命令即可開始進行轉(zhuǎn)化。轉(zhuǎn)換所需要的時間和文章條目和網(wǎng)速相關(guān)酷含,如果你抓取的站點不幸被墻了,還需要使用網(wǎng)絡(luò)代理汪茧。

ebook-convert wangyin.recipe wangyin.mobi --output-profile kindle

注意上面的代碼中增加了一個參數(shù) --output-profile kindle椅亚,這個參數(shù)的意思是根據(jù) Kindle 設(shè)備做適配,如果不添加這個參數(shù)舱污,轉(zhuǎn)換出來的電子書會有一個對 Kindle 來說多余的翻頁導航呀舔。

另外在轉(zhuǎn)換的過程中也會有意外情況,比如由于資源鏈接被墻扩灯,或由于網(wǎng)絡(luò)不穩(wěn)定導致頁面抓取失敗媚赖。本例中抓取的博客由于引用了兩張 Google 服務(wù)器上的圖片,不使用代理就會抓取失敗珠插。

以上命令執(zhí)行完畢后便可以得到最終的電子書文件 wangyin.mobi惧磺,拷貝或推送到 Kindle 即可閱讀。

<small>提示:如果你不想使用命令行工具捻撑,當然也可以使用 Calibre 界面上的“抓取新聞”功能來完成同樣的工作磨隘。你只需要把編寫好的 Recipe 代碼粘貼到新建的 Recipe 腳本中缤底,或者直接導入已有的 Recipe 腳本文件,然后和抓取 RSS 的操作一樣番捂,在“定期新聞下載”面板上選中“自定義腳本”个唧,點擊【立即下載】按鈕即可完成轉(zhuǎn)換。不過這種方法會始終帶有翻頁導航设预。</small>

五徙歼、現(xiàn)成的 Calibre Recipe 腳本

除了自己手動針對某個網(wǎng)站的內(nèi)容編寫 Recipe 腳本外,對于一些知名度較高的站點鳖枕,已經(jīng)有很多現(xiàn)成的 Recipe 腳本可用鲁沥,比如 Calibre 項目自身就提供了一個 Recipe 腳本庫(Calibre 的“抓取新聞”內(nèi)置的那些就是使用的這些 Recipe 腳本)。另外也有很多網(wǎng)友也分享了自己編寫的的 Recipe 腳本耕魄,你可以訪問 GitHub 搜索關(guān)鍵字“calibre recipe”來查找感興趣的腳本画恰。當然也歡迎你的分享。

以上就是利用 Recipe 腳本抓取不提供 RSS 的網(wǎng)站內(nèi)容并制成電子書的方法吸奴。以上內(nèi)容盡量兼顧沒有任何編程經(jīng)驗的小伙伴允扇,如果按照你的理解方式對那些地方不太明白,請留言则奥,確認有誤區(qū)后會按照你的意見進行更改考润。如果你發(fā)現(xiàn)本文存在錯誤,也歡迎留言指正读处。有更好的玩兒法糊治,也歡迎分享。


我自己的作品

以下是我成功抓取crazyguyonabike.com上一篇日志的recipe文件罚舱。改了幾個地方井辜,居然成功了。

#!/usr/bin/python
# encoding: utf-8

from calibre.web.feeds.recipes import BasicNewsRecipe # 引入 Recipe 基礎(chǔ)類

class Wang_Yin_Blog(BasicNewsRecipe): # 繼承 BasicNewsRecipe 類的新類名

    #///////////////////
    # 設(shè)置電子書元數(shù)據(jù)
    #///////////////////
    title = 'nz tips' # 電子書名
    description = 'nz tips for crazy' # 電子書簡介
    #cover_url = '' # 電子書封面
    #masthead_url = '' # 頁頭圖片
    __author__ = 'some' # 作者
    language = 'zh' # 語言
    encoding = 'utf-8' # 編碼

    #///////////////////
    # 抓取頁面內(nèi)容設(shè)置
    #///////////////////
    #keep_only_tags = [{ 'class': 'example' }] # 僅保留指定選擇器包含的內(nèi)容
    no_stylesheets = True # 去除 CSS 樣式
    remove_javascript = True # 去除 JavaScript 腳本
    auto_cleanup = True # 自動清理 HTML 代碼
    delay = 5 # 抓取頁面間隔秒數(shù)
    max_articles_per_feed = 999 # 抓取文章數(shù)量

    #///////////////////
    # 頁面內(nèi)容解析方法
    #///////////////////
    def parse_index(self):
        site = 'https://www.crazyguyonabike.com/doc/?o=1mr&doc_id=5873&v=6H' # 頁面列表頁
        site2 = 'https://www.crazyguyonabike.com'
        soup = self.index_to_soup(site) # 解析列表頁返回 BeautifulSoup 對象
        links = soup.findAll("dd") # 獲取所有文章鏈接
        articles = [] # 定義空文章資源數(shù)組
        for link in links: # 循環(huán)處理所有文章鏈接
            title = link.a.contents[0].strip() # 提取文章標題
            url = site2 + link.a.get("href") # 提取文章鏈接
            a = {'title': title , 'url':url} # 組合標題和鏈接
            articles.append(a) # 累加到數(shù)組中
        ans = [(self.title, articles)] # 組成最終的數(shù)據(jù)結(jié)構(gòu)
        return ans # 返回可供 Calibre 轉(zhuǎn)換的數(shù)據(jù)結(jié)構(gòu)

    ```
只改了幾個地方管闷。
1是增加了一個site2的變量粥脚,因為日志的目錄頁不是首頁。
2是把需要查找的tag修改成頁頁上的dd包个。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末刷允,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子碧囊,更是在濱河造成了極大的恐慌树灶,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件糯而,死亡現(xiàn)場離奇詭異天通,居然都是意外死亡,警方通過查閱死者的電腦和手機歧蒋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門土砂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來州既,“玉大人,你說我怎么就攤上這事萝映∥庖叮” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵序臂,是天一觀的道長蚌卤。 經(jīng)常有香客問我,道長奥秆,這世上最難降的妖魔是什么逊彭? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮构订,結(jié)果婚禮上侮叮,老公的妹妹穿的比我還像新娘。我一直安慰自己悼瘾,他們只是感情好囊榜,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著亥宿,像睡著了一般卸勺。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上烫扼,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天曙求,我揣著相機與錄音,去河邊找鬼映企。 笑死悟狱,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的卑吭。 我是一名探鬼主播芽淡,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼豆赏!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起富稻,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤掷邦,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后椭赋,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體抚岗,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年哪怔,在試婚紗的時候發(fā)現(xiàn)自己被綠了宣蔚。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片向抢。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖胚委,靈堂內(nèi)的尸體忽然破棺而出挟鸠,到底是詐尸還是另有隱情,我是刑警寧澤亩冬,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布艘希,位于F島的核電站,受9級特大地震影響硅急,放射性物質(zhì)發(fā)生泄漏覆享。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一营袜、第九天 我趴在偏房一處隱蔽的房頂上張望撒顿。 院中可真熱鬧,春花似錦荚板、人聲如沸凤壁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽客扎。三九已至,卻和暖如春罚斗,著一層夾襖步出監(jiān)牢的瞬間徙鱼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工针姿, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留袱吆,地道東北人。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓距淫,卻偏偏與公主長得像绞绒,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子榕暇,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容