设为首页 收藏本站
查看: 1665|回复: 0

[经验分享] 搜索引擎–Python文本文件分割、PyLucene建立索引和索引搜索

[复制链接]

尚未签到

发表于 2017-5-7 14:40:31 | 显示全部楼层 |阅读模式
主机平台:Ubuntu 13.04
Python版本:2.7.4
PyLucene版本:4.4.0
原创作品,转载请标明:http://blog.yanming8.cn/archives/108



最近想使用Python来做一个小的搜索引擎,一来是强化学习一下Pyhton语言,而来是学习一下搜索引擎实现原理。

在网上搜索了好久,网上的资料和书籍都是使用JAVA平台下的Lucene,而PyLucene是Lucene的Python实现。下面是官网的说明:
PyLucene is aPythonextension for accessing JavaLuceneTM. Its goal is to allow you to use Lucene’s text indexing and searching capabilities from Python. It is API compatible with the latest version of Java Lucene, version 4.4.0
Pylucene是一个可以使用Lucene的扩展。它的目标是让你能够在Python中使用Lucene的索引和搜索。它的API和最新的JAVA Lucene是兼容的。


虽然官网说API是兼容的,但是对Python还不是很熟悉的情况下,感觉还是有点怵,慢慢摸索吧。


splitFiles.py
它实现了将大文本文件切割成50行的小文本文件。

#!/usr/bin/env python
import os
import sys
import os.path
def split(file):
  “”"split file to some small ones”"”
  if not os.path.isfile(file):
    print file,”is not a file”
    exit(1)
  txtfile=open(file,”r”)

  dirname=os.path.dirname(file)

  file_index=0

  line_cnt = 0
  outfile=open(dirname+”/output_%d”%file_index+’.txt’,'w’)
  for line in txtfile:
    if line_cnt < 50:
      outfile.write(line)
      line_cnt+=1
    else:
      outfile.close()
      file_index+=1
      outfile=open(dirname+”/output_%d”%file_index+’.txt’,'w’)
      line_cnt=0

  outfile.close()
  txtfile.close()

if __name__ == “__main__”:
  base_dir=os.path.dirname(os.path.abspath(sys.argv[0]))
  root=os.path.join(base_dir,”txtfiles”)
  #print root
  for rootdir,dirnames,filenames in os.walk(root):
    for filename in filenames:
      if not filename.endswith(‘.txt’):
        continue
      txtname=rootdir+”/”+filename
      #print txtname
      split(txtname)


IndexFiles.py
它实现了将指定索引目录下的txt文件,并保存索引到指定的目录,供搜索使用。
#!/usr/bin/env python
INDEX_DIR = “IndexFiles.index”
import sys, os, lucene, threading, time
from datetime import datetime
from java.io import File
from org.apache.lucene.analysis.miscellaneous import LimitTokenCountAnalyzer
from org.apache.lucene.analysis.standard import StandardAnalyzer
from org.apache.lucene.document import Document, Field, FieldType
from org.apache.lucene.index import FieldInfo, IndexWriter, IndexWriterConfig
from org.apache.lucene.store import SimpleFSDirectory
from org.apache.lucene.util import Version
“”"
This class is loosely based on the Lucene (java implementation) demo class
org.apache.lucene.demo.IndexFiles. It will take a directory as an argument
and will index all of the files in that directory and downward recursively.
It will index on the file path, the file name and the file contents. The
resulting Lucene index will be placed in the current directory and called
‘index’.
“”"
class Ticker(object):
  def __init__(self):
    self.tick = True
  def run(self):
    while self.tick:
      sys.stdout.write(‘.’)
      sys.stdout.flush()
      time.sleep(1.0)
class IndexFiles(object):
  “”"Usage: python IndexFiles <doc_directory>”"”
  def __init__(self, root, storeDir, analyzer):
    if not os.path.exists(storeDir):
      os.mkdir(storeDir)
    store = SimpleFSDirectory(File(storeDir))
    analyzer = LimitTokenCountAnalyzer(analyzer, 1000)#1048576
    config = IndexWriterConfig(Version.LUCENE_CURRENT, analyzer)
    config.setOpenMode(IndexWriterConfig.OpenMode.CREATE)
    writer = IndexWriter(store, config)
    self.indexDocs(root, writer)
    ticker = Ticker()
    print ‘commit index’,
    threading.Thread(target=ticker.run).start()
    writer.commit()
    writer.close()
    ticker.tick = False
    print ‘done’
  def indexDocs(self, root, writer):

    #Create a new FieldType with default properties.
    t1 = FieldType()
    t1.setIndexed(True)
    t1.setStored(True)
    t1.setTokenized(False)#True if this field’s value should be analyzed by the Analyzer.
    t1.setIndexOptions(FieldInfo.IndexOptions.DOCS_AND_FREQS)

    #Create a new FieldType with default properties.
    t2 = FieldType()
    t2.setIndexed(True)
    t2.setStored(True)
    t2.setTokenized(True)#True if this field’s value should be analyzed by the Analyzer.
    t2.setIndexOptions(FieldInfo.IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS)

    for root, dirnames, filenames in os.walk(root):
      for filename in filenames:
        if not filename.endswith(‘.txt’):
          continue
        print “adding”, filename
        try:
          path = os.path.join(root, filename)
          file = open(path)
          contents = file.read()
          file.close()
          doc = Document()
          doc.add(Field(“name”, filename, t1))
          doc.add(Field(“path”, root, t1))
          if len(contents) > 0:
            doc.add(Field(“contents”, contents, t2))
            print “length of content is %d”%(len(contents))
          else:
            print “warning: no content in %s” % filename
          writer.addDocument(doc)
        except Exception, e:
          print “Failed in indexDocs:”, e
if __name__ == ‘__main__’:
  if len(sys.argv) < 1:
    print IndexFiles.__doc__
    sys.exit(1)
  lucene.initVM(vmargs=['-Djava.awt.headless=true'])
  print ‘lucene’, lucene.VERSION
  start = datetime.now()
  try:
    base_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
    print base_dir
    print os.path.abspath(sys.argv[0])

    IndexFiles(“./txtfiles”, os.path.join(base_dir, INDEX_DIR),
         StandardAnalyzer(Version.LUCENE_CURRENT))
    end = datetime.now()
    print end – start
  except Exception, e:
    print “Failed: “, e
    raise e

SearchFile.py
它就是搜索前面生成的索引,输入搜索结果。
#!/usr/bin/env python
INDEX_DIR = “IndexFiles.index”
import sys, os, lucene
from java.io import File
from org.apache.lucene.analysis.standard import StandardAnalyzer
from org.apache.lucene.index import DirectoryReader
from org.apache.lucene.index import Term
from org.apache.lucene.queryparser.classic import QueryParser
from org.apache.lucene.store import SimpleFSDirectory
from org.apache.lucene.search import IndexSearcher
from org.apache.lucene.search import Query, TermQuery
from org.apache.lucene.util import Version
“”"
This script is loosely based on the Lucene (java implementation) demo class
org.apache.lucene.demo.SearchFiles. It will prompt for a search query, then it
will search the Lucene index in the current directory called ‘index’ for the
search query entered against the ‘contents’ field. It will then display the
‘path’ and ‘name’ fields for each of the hits it finds in the index. Note that
search.close() is currently commented out because it causes a stack overflow in
some cases.
“”"
def run(searcher, analyzer):
  while True:
    print
    print “Hit enter with no input to quit.”
    command = raw_input(“Query:”)
    if command == ”:
      return
    print
    print “Searching for:”, command
    “”"
    query = QueryParser(Version.LUCENE_CURRENT, “contents”,
              analyzer).parse(command)
    “”"
    query = TermQuery(Term(“contents”, command))
    hits = searcher.search(query,10000)
    print “%s total matching documents.” % hits.totalHits
    print “Max score:”,hits.getMaxScore()
    for hit in hits.scoreDocs:
      doc = searcher.doc(hit.doc)
      print ‘URI:’,doc.getField(“path”).stringValue()
      print ‘File:’,doc.getField(‘name’).stringValue()
      #print ‘Digest:’,doc.getField(‘contents’).stringValue()
      print ‘Health:’,hit.score
if __name__ == ‘__main__’:
  lucene.initVM(vmargs=['-Djava.awt.headless=true'])
  print ‘lucene’, lucene.VERSION
  base_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
  directory = SimpleFSDirectory(File(os.path.join(base_dir, INDEX_DIR)))
  searcher = IndexSearcher(DirectoryReader.open(directory))
  analyzer = StandardAnalyzer(Version.LUCENE_CURRENT)
  run(searcher, analyzer)
  del searcher


下面是建立索引部分结果输出:


下面是搜索的部分结果输出:

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-374301-1-1.html 上篇帖子: 沉默成本,跪在坚持----Java程序员学Python学习笔记(一) 下篇帖子: [Python]tornado的多线程模型python版MVC完结版
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表