小说下载阅读器_初始简单版

2 篇文章 0 订阅
1 篇文章 0 订阅

小说下载阅读器_初始简单版

相信园子里面的很多人和我一样喜欢阅读小说,下面是这几年用的比较多一点的阅读器,功能相对完整。

复制代码
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元素也是一样的,不同网站一般是不同的
所以设计的时候,针对网站,可以设计一套过滤标记,如果不放心,对小说也可以在设计一套过滤标记
复制代码

经过上述过程,得到相对干净的正文

;;“奇门印,残篇…”;;林动怔怔的望着那木牌上的介绍,却是没有想到这三品武学,居然是残缺的。;;“这套武学,据说是爷爷一次偶然间得到的,不过也正如上面所说,这只是一门武学的残篇,你若真是想要见识见识三品武学的话,还是换一种吧。”林霞凑上前来,道。;;“光是残篇就能被爷爷放在这里,想必这奇门印应该很厉害吧?”林动若有所思的道。;;“还行吧,不过学不全,那也没用,按照爷爷说,这残缺的奇门印,就算是炼成功,也只是三品武学的威力,甚至,恐怕还略有不及。”林霞笑道。

将;;替换成换行符和四个空格之后,得到干净正文

按 Ctrl+C 复制代码
按 Ctrl+C 复制代码

demo程序(工具集)功能

复制代码
1.新增、修改、删除小说(索引页),根据已有索引页,下载章节内容,并缓存
2.针对网站可新增对应过滤器,以实现对章节名和章节内容进行过滤,得到干净的名称和内容,另外还有网站间共用的过滤器
3.新增时小说时,可自动关联已有的过滤器。
4.可设定次数和时间间隔,对某小说的更新进行监控,并自动更新。
5.提供格式化工具,可对某小说的缓存章节或者按目录进行格式化,每部小说格式化为一个xml格式,并提供对应的xslt文件,可通过浏览器浏览
6.提供格式转化工具,将xml格式转化成其他格式,暂时只提过xml转umd格式
7.内嵌一个web服务器,可供局域网阅读
复制代码

C#有两个版本,主要区别在于数据库,一个是sqlite,一个是直接用二进制文件

C++ 只有二进制文件版

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值