Create Your Own Search Engine with Python 用python创造你自己的搜索引擎(三)

Create Your Own Search Engine with Python 用python创建你自己的搜索引擎(三)
Create Your Own Search Engine with Python  
用python创建你自己的搜索引擎(三)

 上一篇是什么来着?想想,对了,工作原理和基本算法简介,这一部分本来是代码分析的,结果一看,太长了,又分成两部分了,有凑字数、骗点击量的嫌疑,各位批评我吧!
原文地址:http://www.zackgrossbart.com/hackito/search-engine-python/
这一部分主要是search.py的介绍。

   让我们开始深入代码吧!

 这个应用程序的代码由两个文件组成——search.py和search.jssearch.py是负责从服务器上返回搜索结果的程序,而search.js则是负责在浏览器上演示搜索(结果)。search.py只运行在服务器上,search.js只运行在浏览器中。

search.py


 search.py是个PYTHON脚本,它会对搜索的词项进行语法分析(确定是语法分析?),执行搜索过程,最后生成包含搜索结果的HTML页面。search.pyCGI脚本进行开发和测试。CGI (Common Gateway Interface)是一种多种解释型脚本语言进行交互的简单方法。当要调用特定的URL时,我们就要使用命令行来调用该脚本,并把这URL的参数传递给该脚本。这种方式在UNIX系统下工作得特别好(WINDOWS又躺枪了),这个文件的第一行可以用来指定它自己的运行方式:

#!/usr/bin/env python

 这一行指定这个文件应该用python程序来运行,只要服务器环境中支持python。同时,开头的" #'意指这是注释行,不像程序的其它部分会执行。


 这个程序有着良好的通用性和可扩展性,但在部署它时,你还是要做一点改动。这个程序定义了一个变量,代表了搜索HTML文件时的根目录。

BASE_DIR = "test/"

 在命令行下运行这个程序时,这个变量没有问题。而在web服务器上运行时,你就要把它指向你的HTML文件所在的位置。search.py会打开并搜索每个文件。我们现在先来看一个简化版的dosearch方法。完整版的方法在示例程序的search.py上。


def dosearch(terms, searchtype, case, adddir, files = []):
    found = []

    if files != None:
        titlesrch = re.compile('>title<.*>/title<')1
        for file in files:

            title = ""
            if not (file.lower().endswith("html") or file.lower().endswith("htm")):
                continue2

            filecontents = open(BASE_DIR + adddir + file, 'r').read()

            titletmp = titlesrch.search(filecontents)3
            if titletmp != None:
                title = filecontents.strip()[titletmp.start() + 7:titletmp.end() - 8]

            filecontents = remove_tags(filecontents)4
            filecontents = filecontents.lstrip()
            filecontents = filecontents.rstrip()


            if dofind(filecontents, case, searchtype, terms) > 0:5
                found.append(title)
                found.append(file)

    return found6



 我们在文件中搜索词项和页面标题,虽然只关心搜索的词项是否出现在页面中,但我们还是需要获得标题标签(title tag)中的内容,于是我们使用正则表达式来帮忙。正则表达式是字符串匹配强有力的工具。我们使用正则表达式来表示,我们需要取出在标签<title> </title>之间的全部文本(.*的部分)。预先编译这个正则表达式1 ,之后我们就可以重复地在文件中使用。(再思维跳转一次)在搜索结果页面上,这些标题就用作那些链接对应的文本内容。


 这个正则表达式编译完成后,我们开始搜索文件,看看我们搜索的词项是否存在于这些文件内。想完整实现这个函数,需要递归地在子目录中搜索。图像文件或内部文件(internal file)只是打酱油的,所以我们只搜索后缀是htmlhtm的文件 2。我们打开某文件,里面有一堆的HTML标签,我们在这些标签中寻找这个页面的标题3。找到标题之后,还要移除这些HTML标签4


 我们必须保证不会把HTML标签里的搜索词项也提溜出来。测试文件numbersandcolorswithtag.html 就是这样的一个测试案例,它里面有一个 <span class="blue" /> 的标签,即使搜索词项中有blue这个项,我们也不希望把它从这个标签中取出来。

 要解决这个问题有个最简单的方法,就是在我们开始查找词项之前,把所有的HTML标签全部去掉。而这样移除标签最好的方式就是对HTML进行语法分析来实现,但是这样好像太慢太复杂了。所以,我们仅仅是寻找和 >符号,因为它们代表了标签的开始和结束。另外,在我们移除标签时,还可以把多余的空格也扔了5。等我们把搜索结果汇总之后,就返回一个包含了搜索结果的元组。


 如果我们得到搜索结果,就可以生成结果页面了,也就是说需要用这些具有相连结构的搜索结果来创建一个HTML页面(我翻译得啰嗦,原文也有点啰嗦)。又是简化版的函数——doresultspage doresults。完整版的代码仍是在search.py文件里。


def doresultspage(terms = [], results = []):
    for line in open("SearchResults.html", 'r'):1
        if line.find("${SEARCH_RESULTS_GO_HERE}") != -1:
            doresults(terms, results)2
        elif line.find("${SEARCH_TERMS_GO_HERE}") != -1:
            termindex = line.find("${SEARCH_TERMS_GO_HERE}")
            searchterms = "" + terms + "\n"
            print line.replace("${SEARCH_TERMS_GO_HERE}", searchterms)3
        else:
            print line4

 搜索结果页面的构建从doresultspage函数开始。这个函数呢,它先读取SearchResults.html文件1,根据这个HTML文件来定制搜索结果页面,使之匹配你的应用程序的外观和感觉。它所有的内容都可以修改,完全根据搜索词项和结果来设计版式。页面中存在两个特殊的词法单元(token)。${SEARCH_RESULTS_GO_HERE} 会被doresults函数中的搜索结果替换掉2。而搜索的词项则放入原来${SEARCH_TERMS_GO_HERE} 的位置3。别的部分则不发生变化,照样输出4


 doresults函数负责的是处理实际搜索结果的输出。搜索结果是包含一个div标签的有序链表。这个div标签由id——search_results指定,可以用CSS来定制。

 
def doresults(terms = [], results = []):
    print "<div id=\"search_results\">\n<ol>"
    if len(results) == 0:
        print "<h3>Your search did not return any results.</h3>"1
    for i, file in enumeratez(results):2
        if i % 2 == 1:
            continue
        print "<li><a href=\"test/" + results[i + 1] + \
        "?search=true&term=" + terms.replace("\"", "%22") + "\">"3

        print results[i] + "</a>\n"
    print "</ol>\n</div>\n"4

 这个方法(一会函数一会方法,汗)一开始要确认是否有搜索结果生成1。如果没有返回任何结果,我们则发消息通知用户。如果返回了结果,我们会对结果进行迭代(我本来想译成遍历的),生成HTML代码来显示结果。python2.3里面,新增了一个内建函数——enumerate,(汗,现在用的都3.3了)。可是我们希望代码可以用较老版本的PYTHON运行(新的应该也可以),所以实际上采用的是定制的enumerate函数——enumeratez2。如果你使用的是较新版本的python,可以用标准函数来代替它。


 在生成搜索结果的链接时,我们还要给URL增加一些特殊的参数。search.js文件会读取这些特殊的参数,在最终的代码中对搜索词项进行高亮化处理。还有一些在HTTP URL中不允许的特殊字符,所以它们必须使用转义字符序列来表示。在这之前,它们中大多数会在代码中,从我们的搜索词项中移除,但同时要保留转义的双引用字符。如果所有的搜索结果都列出来,就该生成结束标签了(close tag4

 (PS:这个编辑器老给我下绊子,不懂就是吃亏)
已经很长了,所以就不挤在这里了,下一部分就是search.js和结尾杀青。
原文地址:http://www.zackgrossbart.com/hackito/search-engine-python/