基于vue前端框架/scrapy爬虫框架/结巴分词实现的小型搜索引擎

小型搜索引擎(tinySearchEngine)

基于scrapy爬虫框架,结巴分词,php和vue.js实现的小型搜索引擎。

a tiny search engine based on vue.js and use scrapy,jieba,php to accomplish it

Build Setup

# install dependencies
npm install

# serve with hot reload at localhost:8080
npm run dev

# build for production with minification
npm run build

# build for production and view the bundle analyzer report
npm run build --report

整体实现

大体流程如下:

1.爬虫爬取网页数据,保存在文件中,

2.python读取文件内容,存到数据库表中,使用结巴分词对网页内容进行分词,并获得TF-IDF值,构建倒排索引保存到数据库中。

3.前端界面接受用户输入,使用POST请求将数据发送到后端。

4.后端接受到数据进行分词,然后在倒排索引数据库查询,结果取并集,然后根据倒排索引数据库结果在结果数据库中查询,返回网页的具体信息。

5.前端收到返回后,将结果呈现出来。

具体实现

1.爬虫

爬虫采用的是python的爬虫库scrapy,只需要进行简单的配置就可以使用,如果要递归爬取,可以采用class DmozSpider(CrawlSpider)

要获得的数据网页数据主要有:url,title,description,keywords,具体配置如下:

item['title'] = response.selector.xpath('//title/text()').extract()
item['keywords'] = response.selector.xpath('//meta[@name="keywords"]/@content').extract()
item['description'] = response.selector.xpath('//meta[@name="description"]/@content').extract()

同时,为了保存数据,需要定义items,在items.py中添加如下:

url = scrapy.Field()
title = scrapy.Field()
keywords = scrapy.Field()
description = scrapy.Field()

在终端中运行scrapy crawl dmoz -o items.json -t json,可以把数据存到items.json中。

2.分词

分词我选用的是python环境下的结巴分词, 在考虑了好几种分词后,最后选择了结巴分词,主要是安装简单(可以直接通过pip安装),使用方便,并且在社区的贡献下,衍生出了不同语言版本(在后端中,我采用的是结巴分词的php版本)。

结巴分词直接提供了基于TF-IDF算法的关键词提取功能:

jieba.analyse.extract_tags(sentence, topK=20, withWeight=False, allowPOS=())

sentence 为待提取的文本

topK 为返回几个 TF/IDF 权重最大的关键词,默认值为 20

withWeight 为是否一并返回关键词权重值,默认值为 Falseallow

POS 仅包括指定词性的词,默认值为空,即不筛选

所以在分词过程中,可以直接通过结巴分词获得关键词,以及关键词对应的TF-IDF值。

3.数据库

数据库选择的是MySQL,新建数据库名python,数据库下有两个表,search_result,inverted index

├── python                         //数据库         
│   ├── search_result        //搜索结果
│   └── inverted indexsuoyin      //倒排索引

经过爬虫爬取的数据保存在items.json中,在jsonToMySQL.py中,将文件中保存的数据存到数据库表search_result中,有index作为网页的唯一标志,字段有index_,url,title,date,description

在urlToKeywords.py中,从表search_result中读取每一条,利用结巴分词提取关键字,并获得每个关键词的TF-IDF值,保存到表inverted index中,在查询的过程中,输入一条语句,将这条语句分词后得到关键词,将每个关键词进inverted index中查询,得到index和TF-IDF,结果取并集,根据index到search_result查询url,title等信息,利用TF-IDF之和进行页面的排序。

4.前端

前端采用前端框架vue.js使用vue-router实现路由管理,使用axios发送http请求。组件有两个,模仿的是百度的首页,在有输入的时候输入框位置变化(百度打开时输入框居中,有输入的时候变换到输入框在顶部),百度应该是用切换css类的方式来实现的,我采用的是切换组件,首页输入框有输入改变触发<input type='text>'input事件,触发后,实现页面跳转到结果页面,为了保持输入的数据不变,把输入框的值进行了组件间的通信,首页组件将输入值传给父组件,父组件将值传给结果子组件,并且创建钩子,在页面挂载mounted后,让输入框获得焦点

//子组件向父组件通信,传递输入框的值
methods: {
    change: function(){
        this.$emit('childChange',this.query)
    },
}
//父组件监听到子组件的事件后,实现页面跳转。
showResult: function(data){
      //alert('hello')
      this.query=data
      console.log(this.query)
      this.$router.replace({path:'/result'})
  }  
//子组件接受来自于父组件的值
props: ['parentQuery'],

mounted后,结果页面输入框获得焦点

 mounted: function(){
    var input_query=document.getElementById('input')
    input_query.focus()
  },

前端接受的来自于后端的json数据,利用vue的列表渲染,页面选择按钮数量根据返回结果的数目确定parseInt(num/10)+1就是按钮的个数,同时采用条件渲染控制出现结果选择的时间。

<button v-if="show_button" v-for="n in parseInt(length/10)+1" v-on:click="page_select=n">{{n}}</button>

结果显示

    <div v-for="item in part_response">
        <a id="title" v-bind:href="item.url" target="_blank" class="item_title">{{ item.title}}</a>
        <p class="item_description">{{ item.description }}</p>
        <li id="small_url_content"><a v-bind:href="item.url" id="small_url" target="_blank">{{ item.url }}</a></li>
        <li id="date">&nbsp{{ item.date }}</li>
    </div>

利用计算属性,只显示十个结果,并根据当前页的不同显示不同的结果。

part_response: function(){
        var part=[]
        for(let start = (this.page_select-1)*10;start<this.page_select*10;start++){
            if(start<this.length){
                part.push(this.response[start])
            }
        }
        //shixian guanjianzi gaoliang;
        var split_query = this.query.split("")
        console.log(split_query)
        var char
        var part_to_str =  JSON.stringify(part)
        return part
    }

5.后端

在后端同样需要分词,后端接受到前端发送的数据,对搜索进行分词,我采用的是结巴分词的PHP版,需要在使用的时候引入需要的PHP文件即可,但是在使用的时候要初始化,即调用Jieba::init(),但是该过程非常耗时间,搜索的绝大多数时间都消耗在此,为了测试消耗时间,我注释掉所有代码,只保留该初始化函数,发现耗时基本跟执行完整查询一致,目前还没有很好的解决方法,自己实现分词功能不是很现实。

分词后得到几个关键词,从倒排索引数据库搜索对应结果,按照TF-IDF排序,将index从搜索结果数据库查询,返回title,url等字段,保存在二维数组中,最后使用json返回结果。

echo json_encode($return_array);

运行截图

显示结果1
首页
用户输入
显示结果2

项目地址

项目地址

文件结构

.
├── back_end.php     //后端文件,负责把接受前端的POST请求,查询后返回以json返回结果
├── build
├── config
├── dist         
│   ├── index.html    //首页
│   └── static
│       ├── css
│       └── js
├── DomzSpider.py      //爬虫文件,负责爬取网页的title,url,description保存在一个josn文件中
├── index.html
├── node_modulels      //node模块
├── package.json
├── README.md
├── src
│   ├── App.vue
│   ├── assets
│   │   └── logo.png
│   ├── components
│   │   ├── searchEngine.vue       //搜索的首页
│   │   └── searchResult.vue       //搜索结果显示
│   ├── main.js
│   └── router                    //路由
│       └── index.js
├── static
├── test
├── jsonToMySQL.py                //从json读取数据保存到MySQL数据库search_result表中
└── urlToKeywords.py              //从数据库search_result表读取数据,利用结巴分词将获得TF-IDF,保存到                                    //inverted index表中

参考

dySE:一个 Java 搜索引擎的实现,第 1 部分: 网络爬虫

Python抓取框架Scrapy快速入门教程

自制简单搜索引擎

结巴中文分词

"結巴"中文分詞:做最好的 PHP 中文分詞、中文斷詞組件。

For detailed explanation on how things work, checkout the guide and docs for vue-loader.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345

推荐阅读更多精彩内容

  • 这个系列的第六个主题,主要谈一些搜索引擎相关的常见技术。 1995年是搜索引擎商业公司发展的重要起点,《浅谈推荐系...
    我偏笑_NSNirvana阅读 6,600评论 3 24
  • 常用概念: 自然语言处理(NLP) 数据挖掘 推荐算法 用户画像 知识图谱 信息检索 文本分类 常用技术: 词级别...
    御风之星阅读 9,152评论 1 25
  • 从初中二年级开始,喜欢上了抄诗,不知道为什么,那时自己做了一个很小的本子,抄了大约二三十首,都是教材上的,可惜本子...
    苏步哲阅读 511评论 0 1
  • 一转眼分身术训练营就要接近尾声了,在这一周短训里,从课程中学到了很多知识和生活中怎么去应用的方法,顺便不小心见识到...
    自我迭代的小喆阅读 407评论 1 0
  • 上上周老公带娃回老家之后,我就毁容了。顶着一张毁容的脸,上班晃悠着,来到办公室,两位领导都问我怎么了, 问我...
    阳光洒洒阅读 216评论 1 1