Linux平台下C++实现的新闻网站

前段时间跟同学一起做了一个简单的新闻网站,用的C++语言开发的,基于linux操作系统。

该新闻网站的搭建包括两部分内容:前端+后端,前端就是简单的HTML网页,后端搭建了多线程服务器,采用的B/S模型。涉及的内容有html页面,http协议,多线程服务器模型,数据库,信息检索算法,网络爬虫等,麻雀虽小,五脏俱全。

主要包含以下功能模块:

数据抓取模块,html页面生成模块,前端交互模块,http报文解析与响应模块,多线程服务器模块,日志记录模块,数据库交互模块,新闻检索模块,以及兴趣推荐模块。

其中,

数据抓取模块主要负责对新闻网页的抓取,采用scrapy工具,主要思路是抓取新闻的标题,新闻的正文信息,得到新闻页面的字符串以后,传入到html页面生成模块中。

html页面生成模块主要负责将网络爬虫抓取到的新闻页面的信息构建网页,按照自定义的格式,创建.html形式的页面,然后插入到数据库中保存。

http报文解析与响应模块主要负责解析浏览器生成的报文,构建响应报文。简单起见,我们只解析get请求和post请求,以及文本,图片文件的请求。对于响应报文,报头包含协议版本,内容类型,连接方式,内容长度几个字段,我们采用动态的方式,往格式化的头部字符串中插入内容类型和内容长度的信息,再加上内容构建http报文。

多线程服务器模块是网站的核心模块,采用的one loop per thread模式。服务器采取守护进程的方式进行启动,并通过shell脚本进行端口号等的配置。我们的事件循环采用的epoll多路复用模型。方便起见,我们事先声明了一个对象数组,用于存放http请求的对象,这些对象保存了连接套接字的地址信息和http请求等信息。为了便于访问,我们租用了云服务器,能够提供公网访问,同时支持pc端和移动端访问。

日志模块主要负责记录用户的访问行为,包括检索的关键词,访问的页面,提交的get、post表单,ip,端口号等信息。

新闻检索模块主要负责对用户输入的关键词得到的新闻语料库进行打分,然后按照相关度进行排序,得到最终的检索结果,采用的经典的bm25算法。为了方便调用bm25算法,我们运用C++调用python技术,使用python接口完成bm25算法的部分。

兴趣推荐模块主要负责对用户进行新闻推荐。对于未注册用户,采取游客的方式进行推荐,按照关键词的搜索量和页面的访问量进行推荐。对于已注册用户,根据时间的远近以及用户的检索词频和页面访问频率进行综合推荐。初始情况下采取随机推荐。

数据库设计:

我们采用的是mysql5.7下的innodb搜索引擎,为了支持中文全文索引,我们引入了mysql5.7特有的中文分词技术,分词采用的ngram模型,设置的参数为2。

数据库中有三张表,分别为用户信息表,新闻信息表和访问信息表。用户信息表主要保存注册用户的账号和密码,新闻信息表主要保存新闻的标题,新闻内容,关键词,新闻发布的时间。访问信息表主要保存用户访问的页面信息和检索的关键词。

用户注册登录,兴趣推荐都需要经由数据库实现,我们的数据库对象采用的静态对象。

页面展示:

主页面:

Linux平台下C++实现的新闻网站

输入关键词检索页面:

Linux平台下C++实现的新闻网站

页面中存在重复的页面,需要进行去重。去重就需要先判断数据是否存在数据库中,用索引很容易判断,但是由于数据库中存在索引,往一个数据量很大的数据库中插入数据必然会导致很多慢查询,因此需要进行优化。我们的爬虫程序是定期抓取数据和插入数据库的,考虑插入原表(假设为A)之前先创建一个数据表(假设为表B),该表的类型同需要插入的表的类型一致,只不过去除了索引。在插入的时候,我们利用索引先查询A中是否存在相同的网页,如果不存在则插入到表B中,继续如此操作,直到等爬虫程序结束或者达到某个数据量。然后,我们将表A的全文索引删除,再将表B的内容一次性插入到表A中,再添加全文索引。相比每次插入带有全文索引的表,这种方式要更好一些。

未完待续。。。