- 主机环境:Ubuntu 13.04
- Python版本:2.7.4
- Django版本:1.5.4
- Scrapy版本:0.18.2
- ElasticSearch版本:0.90.5
闲来无聊,查看了相关搜索引擎的基本知识,经过搜集资料,了解了搜索引擎所需要的基本子系统,爬取子系统,索引服务子系统,Web请求和应答子系统。然后经过学习基本的开源框架文档,集成的项目已经PUSH到GitHub。
首先查看基于开源的Scrapy爬虫框架编写的一个爬虫,爬取校园网的内容(主要是免流量)
01 |
#!/usr/bin/env python |
02 |
#-*- coding:utf-8 -*- |
03 |
#from urlparse import urljoin |
04 |
from scrapy.utils.url import urljoin_rfc
|
05 |
from scrapy.spider import BaseSpider
|
06 |
from scrapy.selector import HtmlXPathSelector
|
07 |
from scrapy.http import Request
|
08 |
|
09 |
from scrapy.exceptions import DropItem
|
10 |
|
11 |
from mymodules.items import Website
|
12 |
|
13 |
import urllib
|
14 |
import re
|
15 |
|
16 |
class Xidian_Spider(BaseSpider):
|
17 |
name = "xidian_spider"
|
18 |
start_urls = [
|
19 |
"http://www.xidian.edu.cn" ,
|
21 |
|
22 |
]
|
23 |
|
24 |
def __init__( self ):
|
25 |
"""init the allowed_domain"""
|
26 |
self .allowed_domains = [ 'xidian.edu.cn' ]
|
27 |
|
28 |
def parse( self , response):
|
29 |
"""In this parse,we use double yeild to return the item or Request"""
|
30 |
hxs = HtmlXPathSelector(response)
|
31 |
|
32 |
refer_websites = hxs.select( '//@href' ).extract()
|
33 |
|
34 |
#if not self.gethostname(response.url) in self.allowed_domains:
|
35 |
# self.allowed_domains.append(self.gethostname(response.url))
|
36 |
|
37 |
item = Website()
|
38 |
item[ 'url' ] = response.url
|
39 |
item[ 'title' ] = hxs.select( '/html/head/title/text()' ).extract()[ 0 ]
|
40 |
|
41 |
"""FIXME:This XPath select all the elements,include the javascript code.BAD!!"""
|
42 |
str = ''
|
43 |
list = hxs.select( '/html/body//*/text()' ).extract()
|
44 |
for s in list :
|
45 |
str + = s.strip()
|
46 |
str + = ' '
|
47 |
|
48 |
item[ 'content' ] = str
|
49 |
|
50 |
yield item
|
51 |
|
52 |
for weburl in refer_websites:
|
53 |
|
54 |
utf8_url = weburl.encode( 'utf-8' )
|
55 |
|
56 |
"""The following regex to match the prefix and postfix of urls"""
|
57 |
postfix = re. compile (r '.+\.((jpg)|(ico)|(rar)|(zip)|(doc)|(ppt)|(xls)|(css)|(exe)|(pdf))x?$' )
|
58 |
prefix = re. compile (r '^((javascript:)|(openapi)).+' )
|
59 |
|
60 |
if postfix.match(utf8_url):
|
61 |
continue
|
62 |
if prefix.match(utf8_url):
|
63 |
continue
|
64 |
if not utf8_url.startswith( 'http://' ):
|
65 |
#weburl = urljoin_rfc(response.url, weburl, response.encoding)
|
66 |
weburl = 'http://' + self .gethostname(response.url) + '/' + weburl
|
67 |
|
68 |
weburl = re.sub(r '/\.\./\.\./' ,r '/' ,weburl)
|
69 |
weburl = re.sub(r '/\.\./' ,r '/' ,weburl)
|
70 |
|
71 |
yield Request(weburl, callback = self .parse)
|
72 |
|
73 |
def gethostname( self , res_url):
|
74 |
"""get the host name of a url"""
|
75 |
proto, rest = urllib.splittype(res_url)
|
76 |
host, rest = urllib.splithost(rest)
|
77 |
return host
|
爬取得到的ITEM会交给PIPELINE处理。
这里的PipeLine做了去重处理,不能简单的放在内容,所以使用的是Bloom Filter的算法,这里直接安装了Python的开源库中的pybloomfilter(有时间研究一下)
01 |
class DuplicatesPipeline( object ):
|
02 |
|
03 |
def __init__( self ):
|
04 |
self .bf = BloomFilter( 10000000 , 0.01 , 'filter.bloom' )
|
05 |
self .f_write = open ( 'visitedsites' , 'w' )
|
06 |
self .si = SearchIndex()
|
07 |
self .si.SearchInit()
|
08 |
|
09 |
def process_item( self , item, spider):
|
10 |
print '************%d pages visited!*****************' % len ( self .bf)
|
11 |
if self .bf.add(item[ 'url' ]): #True if item in the BF
|
12 |
raise DropItem( "Duplicate item found: %s" % item)
|
13 |
else :
|
14 |
#print '%d pages visited!'% len(self.url_seen)
|
15 |
self .save_to_file(item[ 'url' ],item[ 'title' ])
|
16 |
self .si.AddIndex(item)
|
17 |
return item
|
18 |
|
19 |
def save_to_file( self ,url,utitle):
|
20 |
self .f_write.write(url)
|
21 |
self .f_write.write( '\t' )
|
22 |
self .f_write.write(utitle.encode( 'utf-8' ))
|
23 |
self .f_write.write( '\n' )
|
24 |
|
25 |
def __del__( self ):
|
26 |
"""docstring for __del__"""
|
27 |
self .f_write.close()
|
28 |
self .si.IndexDone()
|
该类中的SearchIndex是ElasticSearch建立索引的类。定义如下:
01 |
#!/usr/bin/env python |
02 |
#-*- coding:utf-8-*- |
03 |
import os
|
04 |
import sys
|
05 |
from pyes import *
|
06 |
from mymodules.items import Website
|
07 |
INDEX_NAME = 'xidian_spider'
|
08 |
|
09 |
class SearchIndex( object ):
|
10 |
|
11 |
def SearchInit( self ):
|
12 |
self .conn = ES( '127.0.0.1:9200' , timeout = 3.5 ) #Connect to ES
|
13 |
try :
|
14 |
self .conn.delete_index(INDEX_NAME)
|
15 |
#pass
|
16 |
except :
|
17 |
pass
|
18 |
self .conn.create_index(INDEX_NAME) #Create a new INDEX
|
19 |
|
20 |
#Define the structure of the data format
|
21 |
mapping = {u 'content' : { 'boost' : 1.0 ,
|
22 |
'index' : 'analyzed' ,
|
23 |
'store' : 'yes' ,
|
24 |
'type' : u 'string' ,
|
25 |
"indexAnalyzer" : "ik" ,
|
26 |
"searchAnalyzer" : "ik" ,
|
27 |
"term_vector" : "with_positions_offsets" },
|
28 |
u 'title' : { 'boost' : 1.0 ,
|
29 |
'index' : 'analyzed' ,
|
30 |
'store' : 'yes' ,
|
31 |
'type' : u 'string' ,
|
32 |
"indexAnalyzer" : "ik" ,
|
33 |
"searchAnalyzer" : "ik" ,
|
34 |
"term_vector" : "with_positions_offsets" },
|
35 |
u 'url' : { 'boost' : 1.0 ,
|
36 |
'index' : 'analyzed' ,
|
37 |
'store' : 'yes' ,
|
38 |
'type' : u 'string' ,
|
39 |
#"indexAnalyzer":"ik",
|
40 |
#"searchAnalyzer":"ik",
|
41 |
"term_vector" : "with_positions_offsets" },
|
42 |
}
|
43 |
|
44 |
self .conn.put_mapping( "searchEngine-type" , { 'properties' :mapping}, [INDEX_NAME]) #Define the type
|
45 |
|
46 |
def AddIndex( self ,item):
|
47 |
|
48 |
print 'Adding Index item URL %s' % item[ 'title' ].encode( 'utf-8' )
|
49 |
self .conn.index({ 'title' :item[ 'title' ].encode( 'utf-8' ), \
|
50 |
'url' :item[ 'url' ].encode( 'utf-8' ),\
|
51 |
'content' :item[ 'content' ].encode( 'utf-8' )\
|
52 |
},INDEX_NAME, 'searchEngine-type' )
|
53 |
|
54 |
def IndexDone( self ):
|
55 |
self .conn.default_indices = [INDEX_NAME] #Set the default indices
|
56 |
self .conn.refresh() #Refresh the ES
|
其中中文分词使用的是IK分词,Python库中直接安装即可。
Django中接受搜索请求的处理函数如下:
01 |
def search(request):
|
02 |
"""docstring for search"""
|
03 |
if 'q' in request.GET:
|
04 |
q = request.GET[ 'q' ]
|
05 |
print q
|
06 |
if 'page' in request.GET:
|
07 |
page = unicode (request.GET[ 'page' ])
|
08 |
else :
|
09 |
page = unicode ( 1 )
|
10 |
start = clock()
|
11 |
results = dosearch(q,page) #connect to ES to return the results
|
12 |
end = clock()
|
13 |
return render(request, 'res_search.html' , { 'results' : results,
|
14 |
'query' :q,
|
15 |
'count' : len (results),
|
16 |
'time' :end - start,
|
17 |
'page' :page,
|
18 |
'nextpage' : int (page) + 1 })
|
19 |
else :
|
20 |
message = 'You submitted an empty form.'
|
21 |
return HttpResponse(message)
|
其中调用dosearch函数进行连接ES查询,函数内容如下:
01 |
def dosearch(string,upage):
|
02 |
conn = ES( '127.0.0.1:9200' , timeout = 3.5 ) #连接ES
|
03 |
fq_title = FieldQuery(analyzer = 'ik' )
|
04 |
fq_title.add( 'title' ,string)
|
05 |
|
06 |
fq_content = FieldQuery(analyzer = 'ik' )
|
07 |
fq_content.add( 'content' ,string)
|
08 |
|
09 |
bq = BoolQuery(should = [fq_title,fq_content])
|
10 |
|
11 |
h = HighLighter([ '[' ], [ ']' ], fragment_size = 100 )
|
12 |
|
13 |
page = int (upage.encode( 'utf-8' ))
|
14 |
if page < 1 :
|
15 |
page = 1
|
16 |
|
17 |
s = Search(bq,highlight = h,start = (page - 1 ) * PAGE_SIZE,size = PAGE_SIZE)
|
18 |
s.add_highlight( "content" )
|
19 |
s.add_highlight( 'title' )
|
20 |
results = conn.search(s,indices = 'xidian_spider' ,doc_types = 'searchEngine-type' )
|
21 |
|
22 |
list = []
|
23 |
for r in results:
|
24 |
if (r._meta.highlight.has_key( "title" )):
|
25 |
r[ 'title' ] = r._meta.highlight[u "title" ][ 0 ]
|
26 |
if (r._meta.highlight.has_key( 'content' )):
|
27 |
r[ 'content' ] = r._meta.highlight[u 'content' ][ 0 ]
|
28 |
|
29 |
res = Results()
|
30 |
res.content = r[ 'content' ]
|
31 |
res.title = r[ 'title' ]
|
32 |
res.url = r[ 'url' ]
|
33 |
list .append(res)
|
34 |
return list
|
相关推荐
python毕业设计-基于Django+Scrapy+ElasticSearch的全文搜索引擎系统设计与实现+使用说明.zippython毕业设计-基于Django+Scrapy+ElasticSearch的全文搜索引擎系统设计与实现+使用说明.zip 【备注】 1、该资源内项目...
在构建一个基于Django、Scrapy和Elasticsearch的搜索引擎时,我们首先需要理解这三个工具的核心功能和它们如何协同工作。 Django是一个高级的Python Web框架,它支持快速开发和简洁、实用的设计。在这个项目中,...
Scrapy + Elasticsearch + Django打造全文搜索引擎源码 Scrapy + Elasticsearch + Django打造全文搜索引擎源码 Scrapy + Elasticsearch + Django打造全文搜索引擎源码 Scrapy + Elasticsearch + Django打造...
scrapy爬虫获取数据存储至es,ElasticSearch+Django实现搜索页面。 快速开始 # 下拉项目代码 git clone https://github.com/downdawn/eswork.git # 安装requirements.txt依赖 pip install -r requirements.txt # ...
Python毕业设计 基于Django+scrapy-redis+ElasticSearch的招聘岗位的搜索引擎系统源码+详细说明+全部数据资料 高分项目 【备注】 1、该项目是高分毕业设计项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该...
【项目介绍】:基于scrapy的采集系统,采用reids、kafka、celery、rabbitmq、elasticsearch、mysql、django等技术 打造新生代的数据搜索和数据基础平台 Dependencies Please see requirements.txt for Pip package...
在构建一个基于分布式爬虫框架的搜索引擎网站时,通常会涉及到多个关键技术,其中包括Scrapy、Elasticsearch和Django。这三个组件各自承担着不同的角色,共同构建了一个高效、可扩展的搜索解决方案。 **Scrapy**: ...
【标题】"scrapy+es+mysql+django打造搜索引擎"涉及了四个主要技术:Scrapy、Elasticsearch、MySQL和Django,它们共同构建了一个功能强大的搜索引擎系统。 **Scrapy** 是一个Python编写的用于爬取网站并提取结构化...
scrapy爬虫获取数据存储至es,ElasticSearch+Django实现搜索页面。 快速开始 # 下拉项目代码 git clone https://github.com/downdawn/eswork.git # 安装requirements.txt依赖 pip install -r requirements.txt # ...
django Django是一个高级的Python Web框架,可以快速开发安全和可维护的网站。由经验丰富的开发者构建,Django负责处理网站开发中麻烦的部分,可以专注于编写应用程序,而无需重新开发。它是免费和开源的,有活跃...
5. **优化与扩展**:为了提高搜索性能,可以考虑引入全文搜索引擎,如Elasticsearch,以实现更复杂的查询和更高效的索引。此外,还可以添加缓存机制以减少数据库查询次数,提升用户体验。 6. **人工智能(AI)**:...
基于Scrapy、ElasticSearch和Django构建一个小型全文搜索引擎是一个很好的毕业设计项目,它结合了爬虫、搜索引擎和Web开发等多个技术领域。以下是一个可能的项目开发流程: ### 1. 需求分析 - 确定搜索引擎的目标...
【资源说明】 【备注】 1、该项目是个人高分毕业设计项目源码,已获...4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!
毕设项目:基于Scrapy+ElasticSearch+Django的小型全文搜索引擎 该项目为三方面组成:分布式爬虫系统,ElasticSearch数据存储,以及DjangoSearch搭建的web网站。 待续...
本项目是一款基于scrapy_elasticsearch_django构建的Django项目全文搜索引擎,源码包含549个文件,涉及326个JPG图片、145个PNG图片、29个Python脚本、15个JPEG图片、5个GIF图片、5个JSON文件、4个CSS样式表、4个...
基于Scrapy+ElasticSearch+Django的小型全文搜索引擎.zip
在这个项目中,我们看到一个利用Scrapy、Elasticsearch和Django构建的分布式搜索引擎网站的实现。这三者都是IT领域中的重要工具,用于数据抓取、存储和展示。 首先,**Scrapy** 是一个强大的Python爬虫框架,用于...
【作品名称】:基于Scrapy+Elasticsearch+Django搭建的分布式电影搜索 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【项目介绍】...
基于Scrapy+ElasticSearch+Django的小型全文搜索引擎全部资料+详细文档.zip 【备注】 1、该项目是个人高分项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的...
在本项目中,"基于Scrapy+Elasticsearch+Django搭建的分布式电影搜索.zip" 提供了一个使用Python技术栈构建的分布式电影搜索引擎。这个系统利用了三个强大的工具:Scrapy用于爬取网络数据,Elasticsearch进行高效的...