小說下載閱讀器_初始簡單版


相信園子里面的很多人和我一樣喜歡閱讀小說,下面是這幾年用的比較多一點的閱讀器,功能相對完整。

Windows本地程序/手機
1.http://www.mybook66.com/    雲帆小說閱讀器
2.http://www.rrtxt.com/       人人閱讀
3.http://www.dushubao.com/    讀書寶
還有幾個...
網站
1.http://www.sodu.net/     sodu
2.http://www.soshu.cc/     搜書

在幾年前正好寫過一個簡單的小說下載閱讀器,當時基本上沒有前期設計,想到什么就寫什么,所以代碼很亂(有C#和C++兩個版本),並且有不少bug。

現在談談思路和設計,等找到工作后再放出來曬曬了,如果有時間,會逐漸演進到一個復雜的下載閱讀器.

-------------------------------------------------

本文以及后續文章都以起點中文網的《盤龍》這部小說為例解釋約定術語(紅字部分),實際中,使用另外的鏈接(不定)來當例子。

網站主頁:      http://www.qidian.com
小說主頁:      http://www.qidian.com/Book/1017141.aspx
章節目錄索引頁: http://www.qidian.com/BookReader/1017141.aspx
章節頁:        http://www.qidian.com/BookReader/1017141,20361055.aspx

典型場景1(已知某小說網站地址,且知道小說的名稱)

1.打開瀏覽器 ,輸入某小說閱讀網網站地址,打開網站主頁
2.找到小說搜索框,輸入小說名稱,點擊搜索,出現符合搜索條件的小說列表
3.選取某小說,點擊鏈接,轉到本部小說主頁
一般一本小說的主頁上有如下幾個鏈接:點擊閱讀 下載閱讀 加入書架 ....
這里我們只關心 點擊閱讀 4.打開點擊閱讀后,頁面顯示的是本部小說的所有章節目錄
5.點擊相應的章節鏈接,就是本章小說的內容
6.閱讀本章

如果下次再看同一部小說呢?

將本次看的小說的索引頁收藏到瀏覽器的收藏夾,下次直接點擊此鏈接

 簡言之流程如下

瀏覽器-[網站地址]-搜索框-[小說名(關鍵字)]-小說列表-[小說鏈接]-小說主頁-[點擊閱讀]-小說目錄頁-[章節索引]-章節內容

典型場景2(只知道小說名稱)

1.打開瀏覽器 ,打開某搜索引擎,找到搜索框輸入某小說名,點擊搜索,出現符合搜索條件的小說網站列表
2.點擊某小說網站鏈接,打開其網站
3.余下過程同典型場景1
瀏覽器-[搜索引擎地址]-搜索框-[小說名(關鍵字)]-小說網站列表-[小說網站鏈接]-典型場景1
余下的幾個場景用時序圖代替,請自己考慮,什么情況對應哪個場景,可能有遺漏,請@我補充。
下面給出多個場景的時序圖,為了減少上傳圖片,我將多個場景的時序圖都畫在一張圖里面,對應都有標記。



普通的網頁式閱讀方式,需要如下幾個要素
1)小說名
2)網站地址或者搜索引擎地址
3)瀏覽器

缺點很明顯

1)操作步驟繁多,並且大都相似
2)讀者是主動去尋找打開小說,在打開索引頁之前,讀者無法知道小說是否更新,也就無法及時看到更新的小說
3)網站的廣告很多,閱讀章節頁面,干擾多

然而分析流程發現,真正看一部小說只需要如下兩步: 

1)通過小說名找到小說章節目錄索引頁,並打開
2)找到索引頁上要看的章節,點擊打開

小說下載閱讀器的基本功能:

1)通過輸入小說名,可獲取對應小說的主頁或者章節索引頁
2)點擊章節索引,可獲取小說內容
3)可顯示小說章節內容,以供閱讀

高級功能:

4)當程序打開狀態,收藏夾中的小說更新后,可以及時通知讀者

下面仔細分析功能

功能1:從通用搜索引擎或者網站搜索得到小說的章節目錄索引頁面

根據場景1和2的綜合來看,首先需要用到通用搜索引擎,例如Google或者Baidu,其次需要用到小說網站站內部的搜索引擎

為了簡化最初的實現過程,我的demo程序里面省略了功能1的實現,這一步放在后面帖子來進行詳細討論

--三種情況
通用搜索引擎-[小說名]-小說網站-[小說名]-小說索引頁
通用搜索引擎-[小說名]-小說索引頁
小說網站-[小說名]-小說索引頁

功能2:通過章節目錄索引頁面獲取各章節內容

這一步主要是根據小說章節索引網址,獲取此網頁內容,然后取得各個章節對應的網址,再通過章節索引獲取章節內容。

功能3:顯示章節內容

場景1和2都沒有提到顯示問題,因為在瀏覽器中打開最終章節內容的時候,就是html的方式,瀏覽器本身就是html的閱讀器,所以不需要關心此問題,但是如果以程序的方式獲取小說章節內容,得到的是html的文本,這個文本不僅包含章節內容,還有html的一些標記和其它垃圾信息,這些垃圾信息必須過濾掉,在demo程序中,並未實現對文本內容的瀏覽功能。而采用其它方式替代解決。

功能4:對章節目錄索引頁面的收藏

這個很簡單,直接放到數據庫或者文本文件中

demo程序中,上述四個功能中,功能2全部實現,功能3采用另外方式折中實現

public class Novel
{
    ///從給定的目錄索引URL獲取html
    ///參數indexPageUrl:目錄索引頁面對應的網址
    ///返回值:URL對應網址的html
    public string GetIndexPageSource(string indexPageUrl);
    ///從給定頁面html的文本中提取章節索引鏈接
    ///參數indexPageSource:頁面html的文本
    ///返回值:本html包含的章節索引URL集合
    public IList<string> GetIndexListFromIndexPage(string indexPageSource);
    ///從給定的章節索引URL獲取html
    ///參數chapterPageUrl:章節索引頁面對應的網址
    ///返回值:章節URL對應網址的html
    public string GetChapterPageSource(string chapterPageUrl);
    
    ///給定章節內容,將小說內容從html中提取出來
    ///參數chapterPageSource:頁面html的文本
    ///參數filter:過濾過濾條件,參數不一定是這個
    ///返回值:txt文本,且是人直接可閱讀的
    public string GetChapterPageByFilter(string chapterPageSource,IList<string> filter);

    //<chapter index="第一章 天龍八部">
    //    章節內容
    //<chapter/>
    public string ConvertChapterPageToXML(string chapterPage,string index);
    
    //<?xml version="1.0" encoding="UTF-8"?>
    //<?xml-stylesheet type="text/xsl" href="novel.xsl"?>
    //<novel>
    //    <chapter index="第一章 降龍有悔">章節內容</chapter>
    //    <chapter index="第二章 飛龍在天">章節內容</chapter>
    //    <chapter index="第三章 天龍八部">章節內容</chapter>
    //</novel>
    public string ConvertChapterPageListToXML(IList<string> chapterPageXML,string novelName);
    
}

看接口可以知道大概的實現方式

1)功能2,就是利用http直接獲取索引頁面,提取頁面的章節索引url,然后獲取章節頁面,再根據過濾條件提取出章節內容
2)功能3,將每章內容和章節名轉成一個xml片段,最后將這些片段組合成一個完整的xml文件,然后寫一個novel.xsl文件,這樣就可以利用瀏覽器來直接查看此novel.xml小說,不需要自己再實現一個瀏覽器。當然這么做不僅僅是為了偷懶,更重要的是xml這種格式主要是用來做數據交換,通用性比較好,其次,此程序也可以自己內建一個嵌入式的web服務器,可以以web服務的形式,提供已經整理好的小說,供局域網的人閱讀。

在實現過程中,有幾個稍微麻煩一點的地方

1.索引頁面->章節索引url列表

1)大家可以隨便找一個小說的索引頁看看,就知道索引頁面除了包含多個章節索引鏈接外,還包括其它一些與小說章節無關的鏈接,所以進行此步的時候,要加上過濾條件對鏈接進行過濾。
2)過濾方式有兩種,一種是通過html文件中的特定標記,直接過濾出包含所有章節鏈接所在的最小文本部分,然后從這一部分,提取href鏈接;第二種是先提取html文件中的所有href,然后觀察章節鏈接的共性作為過濾條件,過濾出章節鏈接。我采用的是第二種方式。

如下例子就是一個索引頁面html的一部分,示例中只包含章節索引,真實環境中還包含其它無關鏈接,里面的<a>元素是我們需要的

其它部分......
<div class="book_article_texttable"> <div class="book_article_listtext"> <dl id="chapterlist"> <dd><a href="5894704.html">寫在新書之前~</a></dd> <dd><a href="5894705.html">第一章 林動【新書開張,鄭重的求收藏!】</a></dd> <dd><a href="5894706.html">第二章 通背拳</a></dd> </dl> <div class="clear"></div> </div> <div class="book_article_listtext"> <dl id="chapterlist"> <dd><a href="5894707.html">第三章 古怪的石池</a></dd> <dd><a href="5894708.html">第四章 石池之秘</a></dd> <dd><a href="5894710.html">第五章 神秘石符</a></dd> </dl> <div class="clear"></div> </div> </div>
其它部分...... 
2)通常小說作者每天都會上傳新的小說章節,對應的就是章節索引會逐漸增多,實際在讀者追書的時候,基本上都是看新增的章節

也就是說,除了首次閱讀此書的時候可能需要下載所有章節,后面的閱讀都只需要下載新增的章節,既然有前后索引章節的比較,那么章節索引url列表就需要能夠緩存起來,當章節索引url列表緩存后,可以通過一個定時器,定時去抓取章節索引頁面,獲取新的章節索引url列表,然后對比兩次的列表,就可以知道哪些是新增章節,並通知給讀者,當然這種做法,需要設計好定時間隔,不然對網站造成壓力。
大大減小下載的章節數量
可以實現新章節提醒功能
對網站有一定壓力
定時抓取索引頁面時,如何減小對服務器的訪問壓力?
一般我們訪問web服務器的頁面,都是采用get命令,此命令會將頁面的頭部(幾百個字節)和正文(幾十k字節以上)一起取回,如果定時器的時間間隔很小,那么服務器壓力將會很大。
索引頁面初期都是幾k大小,隨着章節增多,到后面一般都是上百k的大小
解決方法
1)查看http協議可知,還有一個head命令可用,它主要是取回頁面的頭部,我們可以將頭部的一些關於頁面更改的字段緩存起來,新的頭部和緩存的對比,有更改才使用get命令下載索引頁面,這樣處理,將大大減小通訊的內容長度,減輕服務器壓力。不過也有不好的一面,就是有些頁面是動態的或者web服務器並未允許此命令。
當然,網站更新小說索引頁,也其實有一個固定的時間段的,可以酌情處理。
2)繼續查看http協議得知,get命令支持獲取某url對應頁面的某一部分(這就是斷點續傳的基礎),通過這種方法,除了首次下載索引頁面需要get整個頁面,后面的get命令只需要獲取章節更改的那部分(最小可能只有百十個字節,需要精心設置條件),不幸的是這個也需要web服務器支持。

2.章節索引url->章節內容

1)獲取章節內容的時候,是需要過濾來得到干凈的內容
2)類似章節索引過濾機制,不過這里采用第一種過濾方式,通過html文件中的特定標記,直接過濾出包含所有章節內容所在的最小文本部分,一般這個特定標記是一對字符串或者正則表達式,記住一定是成對的(起始標記,結束標記)。
3)可惜的是最小文本部分,雖然包含章節正文,但是仍然存在很多html的標記,所以這里必須再次重復進行過濾動作,刪除html的標記,一般這里做成一個過濾鏈的形式,可多次過濾,最終可形成干凈的正文。
4)這里有一種特殊情況,就是正文並不是文本文件,而是一張或者多張圖片形式的內容,這里的處理大部分和前面一樣,不同處在於要保留<img>這個元素,所以過濾的時候要特別小心此種情況

原始的html片段(最小文本部分)

<div id="booktext"><!--go--><STRONG><FONT size=5><a href="/newmessage.php?tosys=1&title=《武動乾坤 第二十八章 奇門印,殘篇》章節出錯啦!&content=章節錯誤原因:" target="_blank"" style="color:red">章節錯誤/點此舉報</a></FONT></STRONG><br><br>&nbsp;&nbsp;&nbsp;&nbsp;“奇門印,殘篇…”<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;林動怔怔的望着那木牌上的介紹,卻是沒有想到這三品武學,居然是殘缺的。<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;“這套武學,據說是爺爺一次偶然間得到的,不過也正如上面所說,這只是一門武學的殘篇,你若真是想要見識見識三品武學的話,還是換一種吧。”林霞湊上前來,道。<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;“光是殘篇就能被爺爺放在這里,想必這奇門印應該很厲害吧?”林動若有所思的道。<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;“還行吧,不過學不全,那也沒用,按照爺爺說,這殘缺的奇門印,就算是煉成功,也只是三品武學的威力,甚至,恐怕還略有不及。”林霞笑道。<!--over--></div>
起始標記:<div id="booktext"><!--go-->,結束標記:<!--over--></div>
1)從html完本中通過起始和結束標記得出最小正文,就是上述例子所示。
過濾或替換html元素:
1)
<div id="booktext"><!--go--> 和<!--over--></div> --->都替換成空字符串
2)<STRONG>(.*)</STRONG> ---> 替換成空字符串
3)<br /> --->替換成特殊標記,這里選用“;;”,換行標記必須保留,可以直接替換成\r\n(不用此方法是為了更好的擴展)
4)(&nbsp;)+ --->替換空字符串,這里的空格一般不需要保留的(段前空格),因為可以用;;來統一換成 換行和空格
...
n) ;{3,} --->替換成 ;;,暫時我用的這個,其實可以直接替換成:一個換行符\n加上四個空格,因為最終是xml轉換成html顯示的\n在html無效,所以暫時是用;;代替,也可以直接用<br/>
上述過濾和替換原則歸納為:如果不屬於正文,則必須被過濾掉(替換為空),如果對最終的正文的分段和顯示有影響,則需保留
一般來說,同一個網站的不同小說,起始結束標記是一樣的,過濾或替換的html元素也是一樣的,不同網站一般是不同的
所以設計的時候,針對網站,可以設計一套過濾標記,如果不放心,對小說也可以在設計一套過濾標記

經過上述過程,得到相對干凈的正文

;;“奇門印,殘篇…”;;林動怔怔的望着那木牌上的介紹,卻是沒有想到這三品武學,居然是殘缺的。;;“這套武學,據說是爺爺一次偶然間得到的,不過也正如上面所說,這只是一門武學的殘篇,你若真是想要見識見識三品武學的話,還是換一種吧。”林霞湊上前來,道。;;“光是殘篇就能被爺爺放在這里,想必這奇門印應該很厲害吧?”林動若有所思的道。;;“還行吧,不過學不全,那也沒用,按照爺爺說,這殘缺的奇門印,就算是煉成功,也只是三品武學的威力,甚至,恐怕還略有不及。”林霞笑道。

將;;替換成換行符和四個空格之后,得到干凈正文

    “奇門印,殘篇…”
    林動怔怔的望着那木牌上的介紹,卻是沒有想到這三品武學,居然是殘缺的。
    “這套武學,據說是爺爺一次偶然間得到的,不過也正如上面所說,這只是一門武學的殘篇,你若真是想要見識見識三品武學的話,還是換一種吧。”林霞湊上前來,道。
    “光是殘篇就能被爺爺放在這里,想必這奇門印應該很厲害吧?”林動若有所思的道。
    “還行吧,不過學不全,那也沒用,按照爺爺說,這殘缺的奇門印,就算是煉成功,也只是三品武學的威力,甚至,恐怕還略有不及。”林霞笑道。

demo程序(工具集)功能

1.新增、修改、刪除小說(索引頁),根據已有索引頁,下載章節內容,並緩存
2.針對網站可新增對應過濾器,以實現對章節名和章節內容進行過濾,得到干凈的名稱和內容,另外還有網站間共用的過濾器
3.新增時小說時,可自動關聯已有的過濾器。
4.可設定次數和時間間隔,對某小說的更新進行監控,並自動更新。
5.提供格式化工具,可對某小說的緩存章節或者按目錄進行格式化,每部小說格式化為一個xml格式,並提供對應的xslt文件,可通過瀏覽器瀏覽
6.提供格式轉化工具,將xml格式轉化成其他格式,暫時只提過xml轉umd格式
7.內嵌一個web服務器,可供局域網閱讀

C#有兩個版本,主要區別在於數據庫,一個是sqlite,一個是直接用二進制文件

C++ 只有二進制文件版

 

 

 

 

 

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM