甲乙小朋友的房子

甲乙小朋友很笨,但甲乙小朋友不会放弃

0%

简单搜索引擎的实现

这是很久以前的IRIE的期末大作业。现在贴在自己的博客上。

实验要求: 1. 用爬虫采集特定网站的信息; 2. 设计实现信息检索与提取系统,对采集的信息进行检索提取; 3. 结合webpy与html实现界面展示。

相关知识

爬虫

网络爬虫是捜索引擎抓取系统中重要的组成部分,其主要目的是将互联网上的网页下载到本地形成一个文件或互联网内容的镜像备份。流程如下: a. 从给定的入口网址把第一个网页下载下来 b. 从第一个网页中提取出所有新的网页地址,放入下载列表中 c. 按下载列表中的地址,下载所有新的网页 d. 从所有新的网页中找出没有下载过的网页地址,更新下载列表 e. 重复3、4两步,直到更新后的下载列表为空表时停止 其实就是简化成下面的步骤: a. 按下载列表进行下载 b. 更新下载列表 c. 循环操作a,b,直到列表为空结束 在本次作业中我们使用python编码实现爬虫的功能,其中用到的python组件有: urllib2:用于获取URLs(Uniform Resource Locators)的组件,以urlopen函数的形式提供一个非常简单的接口,具有利用不同协议获取URLs的能力,同时提供了一个比较复杂的接口来处理一般情况,如:基础验证,cookies代理和其他。通过handlers和openers的对象提供。urllib2支持获取不同格式的URLs并利用它们相关网络协议(例如FTP,HTTP)进行获取。 BeautifulSoup:是python的一个库,最主要的功能是从网页抓取数据。它提供简单的、python式的函数用来处理导航、搜索、修改分析树等功能。可以通过解析文档为用户提供需要抓取的数据。在bs4库中导入。 Htmlparser:是一个开源项目,提供了线性和嵌套两种方式来解析网页,主要用于 html 网页的转换(Transformation)以及网页内容的抽取(Extraction)。HtmlParser 有如下一些易于使用的特性:过滤器(Filters),访问者模式(Visitors),处理自定义标签以及易于使用的 JavaBeans。 selenium :是一个模拟浏览器,进行web的自动化测试的工具,它提供一组API可以与真实的浏览器内核交互。用于抓取js动态生成的页面。

信息检索系统模型

信息检索系统的模型主要有布尔模型、向量模型和概率模型。其中布尔模型 是最早的IR模型,也是应用最广泛的模型,目前仍然应用于商业系统中,布尔模型查询简单但不支持部分匹配,很难控制被检索的文档数量;向量模型(VSM:Vector Space Model)是Salton在上世纪60年代提出的,成功应用于SMART(System for the Manipulation and Retrieval of Text)文本检索系统,其基于关键词,并根据关键词的出现频率计算相似度,向量模型中术语权重的算法提高了检索的性能,部分匹配的策略使得检索的结果文档集更接近用户的检索需求,同时可以根据结果文档对于查询串的相关度使用Cosine Ranking等公式对结果文档进行排序。 在本次作业中信息检索系统采用向量模型,根据相似度返回结果。 ## 结巴(Jieba)分词 结巴(jieba)是一个可以对一段中文进行分词的插件,支持精确模式、全模式及搜索引擎模式三种分词模式,可以适应不同需求。其基本实现原理有:(1)基于Trie树结构实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图(DAG);(2)采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合;(3)对于未登录词,采用了基于汉字成词能力的HMM模型,使用了Viterbi算法。 ## 基于webpy界面设计网页 webpy 是一个轻量级Python web框架,可以快速的完成简单的web页面。在本次实验中使用webpy建立搜索网页,web.py 的模板语言叫做 Templetor,它能负责将 python 的强大功能传递给模板系统。本实验中使用template与html编写网页。

系统设计

本次实验中信息检索与提取系统的整体设计流程如下图所示。主要包括抓取信息、分词、建立索引、建立向量模型、计算比较相似度、返回结果这六个过程,此外,我们基于webpy建立了搜索的网页界面,使查询过程更加简洁明了。下面具体介绍相应的模块。

抓取信息

使用python编写爬虫程序抓取新浪网(http://news.sina.com.cn/) 上的新闻,使用urllib2获取网页源代码,使用beautifulsoup和htmlparser解析网页获取网页中的新闻(标题、关键字、内容、日期),用selenium获取js动态生成的数据(评论数)。解析过的与未解析的链接分开标记。经过一段时间的抓取,共获得3000多条新闻信息,保存为txt文件,具体格式如下: 每条新闻包括标题、关键字、时间、网址、评论数(热度)等信息。

分词 导入jieba分词模块,首先按是否为汉字、数字、英文字符及标点 符号对新闻内容进行梳理,去除掉信息缺失的数据,然后用jieba分词对title及description内容进行分词,得到如下txt文件; 建立索引 对于所有的词,按照其在全部新闻中出现的情况建立倒排索引,将每个词与相应的新闻序号建立联系。 建立向量模型 结合建立的倒排索引表,计算每个新闻条目的向量,其中权重采用tf-idf算法生成,构建向量模型。 查询返回结果 根据在query中输入的关键词与向量模型进行数量积计算相似度,根据相似度的大小将检索到的新闻按序列出。如:query中输入“南海,菲律宾”,得到的检索结果如下: 前后端实现 基于webpy界面设计搜索网页,建立交互的界面。在之前系统设计的基 础上,在webpy框架下,利用templates模板语言将后台结果与前端界面进行交互,并在服务器端使用GET和POST函数与客户端web交互并传递参数传递参数,将搜索新闻在网页上呈现出来。其主要步骤为:(1)客户端发送get请求,触发服务端get()函数,调用index.html网页,返回给客户端。(2)客户端发送搜索关键字并通过post方式给服务端,触发服务端post()函数,post()函数将收到的关键字传入之前设计的搜索系统中,得到返回值新闻条目。(3)通过webpy传递给result.html,得到html网页后发给客户端。

最终效果

例如想要查询与“习近平”“南海”相关的新闻,按下图输入,关键词之间要有空格。 点击search之后的网页界面如下,将我们之前抓取的与“习近平”及“南海”有关的新闻链接按照相似度大小排列,同时列出相应的时间、内容及热度。 如果输入的关键词并不在之前建立的索引中,则会出现如下界面:

遇到的问题及解决方法

• 对Python语言不熟悉、甚至0基础: 阅读相关书籍,掌握for循环,try,list dict 等基本数据结构的操作及语法,文件读写操作,数学运算等,快速上手。 • Python程序运行打印之后不输出: import sys reload(sys) sys.setdefaultencoding('utf-8') • 获取网页速度慢: if response.info().get('Content-Encoding') == 'gzip': buf = StringIO(response.read()) f = gzip.GzipFile(fileobj=buf) 下载压缩的网页,速度更快 • 获取网页异常时,程序中断,导致不能源源不断地爬取到需要的网页: 利用try/except处理异常。

1
2
3
4
5
6
7
8
try:

except urllib2.HTTPError as e: # 处理HTTP异常

except urllib2.URLError as e:#处理URL异常

except:#处理全部类型异常,使程序不中断

• beautifulsoup解析网页内容不全,无法获取新闻网页中关于评论数目的信息: 查看网页源代码发现评论数是js动态生成的,beautifulsoup不能用于获取动态生成的数据,经查阅网上资料,返现selenium包可以用于解析网页中js动态生成的数据,我们首先获取新闻id,访问新浪新闻评论链接,找到其中评论数据。 commenturl = 'http://comment5.news.sina.com.cn/comment/skin/default.html?channel=gn&newsid=comos-' + newsid driver = webdriver.PhantomJS() driver.set_page_load_timeout(30)#设置延时 driver.get(commenturl)#获取网页 comment = driver.find_element_by_class_name('f_red').text#获取元素 • selenium运行报错: 需要添加环境变量,将PhantomJS文件所在文件夹添加到\(PATH文件下:sudo vi /etc/paths • 搜索时建立索引过程耗费时间 预先建立好索引,存储在内存中,搜索时直接利用已经建立好的索引进行搜索。 • 为每条新闻数据、query建立向量并存储速度慢、由于字典集合很大,导致向量稀疏、耗费资源,另外进行向量乘法运算计算相似度时产生不必要的浪费: 仅为每条新闻数据建立字典,存储包含的词和tf-idf权重值,计算query和每一个新闻条目的相似度时,只需要对query中包含的关键词在新闻条目中的权值进行运算即可(因为其它位都是0),简化运算。 • 新闻条目数量庞大,query与新闻的匹配计算量大、效率低: 给定query时,我们先访问query中关键词在索引中的倒排列表,只对其中的新闻与query进行相似度计算、排序、返回最终结果,极大程度上过滤掉与query不相关的新闻条目。 • 字典创建无序,不能按创建顺序输出结果: 利用OrderedDict有序字典,能够记录下字典的创建顺序,有序输出结果dict= collections.OrderedDict() • 搜索结果优化:搜索返回的结果题目中不包含关键词: 对在新闻题目中出现的关键词增加权重,使得题目与关键词匹配度越高的新闻排名越靠前,符合真实需求。 • webpy不能直接调用Python中的函数: 在webpy模板首行定义一个变量\)def with (posts) 在Python中计算后利用将参数传入,可以是任意类型。 • webpy使用template时,路径设置: render = web.template.render('templates/') 打开render下的index.html: render.index()