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

Create Your Own Search Engine with Python  
用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和結尾殺青。

發佈了52 篇原創文章 · 獲贊 4 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章