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


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

    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++ 只有二进制文件版

     

     

     

     

  • 相关阅读:
    js获取页面所有搜索条件
    js计算两经纬度之间的距离
    .NET MVC 序列化与反序列化
    微信浏览器内禁止页面回退返回
    Winform组合ComboBox和TreeView实现ComboTreeView
    如何在Oracle触发器中使用查询语句
    DevExpress Winform:纯代码方式创建PopupMenu
    DevExpress GridView 鼠标热点追踪 高亮显示行
    Task.Wait and “Inlining”
    重置Visual Studio 2017的配置
  • 原文地址:https://www.cnblogs.com/simfe/p/2777101.html
Copyright © 2020-2023  润新知