search.py
search.py是個PYTHON腳本,它會對搜索的詞項進行語法分析(確定是語法分析?),執行搜索過程,最後生成包含搜索結果的HTML頁面。search.py用CGI腳本進行開發和測試。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
這個正則表達式編譯完成後,我們開始搜索文件,看看我們搜索的詞項是否存在於這些文件內。想完整實現這個函數,需要遞歸地在子目錄中搜索。圖像文件或內部文件(internal file)只是打醬油的,所以我們只搜索後綴是html或htm的文件 2。我們打開某文件,裏面有一堆的HTML標籤,我們在這些標籤中尋找這個頁面的標題3。找到標題之後,還要移除這些HTML標籤4。
要解決這個問題有個最簡單的方法,就是在我們開始查找詞項之前,把所有的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,可以用標準函數來代替它。