[英]Highlighting glossary terms inside a HTML document
我們有一個詞匯表,最多可包含2000個術語(其中每個術語詞可能包含一個,兩個或三個詞(用空格或破折號分隔)。
現在,我們正在尋找一種突出顯示(較長)HTML文檔(最多100 KB的HTML標記)中的所有術語的解決方案,以生成帶有突出顯示的術語的靜態HTML頁面。
一個有效的解決方案的約束是:大量的詞匯表術語和冗長的HTML文檔...有效的解決方案(在Python中)的藍圖是什么。
現在,我正在考慮使用lxml解析HTML文檔,遍歷所有文本節點,然后將每個文本節點中的內容與所有詞匯表術語進行匹配。
客戶端(瀏覽器)突出顯示不是一個可行的選擇,因為IE會抱怨長時間運行的腳本以及腳本超時...因此無法用於生產環境。
有更好的主意嗎?
您可以使用解析器以遞歸方式導航樹並僅替換由文本組成的標簽。
這樣做時,您仍然需要考慮幾件事:
-並非所有文字都需要替換(例如內聯javascript)
-文檔的某些元素可能不需要解析(例如標題等)
這是一個快速且非生產就緒的示例,說明如何實現此目標:
html = """The HTML you need to parse"""
import BeautifulSoup
IGNORE_TAGS = ['script', 'style']
def parse_content(item, replace_what, replace_with, ignore_tags = IGNORE_TAGS):
for content in item.contents:
if isinstance(content, BeautifulSoup.NavigableString):
content.replaceWith(content.replace(replace_what, replace_with, ignore_tags))
else:
if content.name not in ignore_tags:
parse_content(content, replace_what, replace_with, ignore_tags)
return item
soup = BeautifulSoup.BeautifulSoup(html)
body = soup.html.body
replaced_content = parse_content(body, 'a', 'b')
這應該用“ b”替換出現的“ a”,但是保留以下內容:
-內聯javascript或CSS(盡管內聯JS或CSS不應出現在文檔正文中)。
-標記中的參考,例如img,...
-標簽本身
當然,然后,根據詞匯表,您需要確保不要僅將單詞的一部分替換為其他單詞; 為此,使用content.replace的正則表達式很有意義。
我認為用客戶端JavaScript突出顯示是最好的選擇。 它可以節省您的服務器處理時間和帶寬,更重要的是,可以使html保持干凈並可供那些不需要不必要標記的人使用,例如,在打印或轉換為其他格式時。
為了避免超時,只需將作業拆分為多個塊,然后在setTimeout的線程化函數中逐個處理它們。 這是這種方法的一個例子
function hilite(terms, chunkSize) {
// prepare stuff
var terms = new RegExp("\\b(" + terms.join("|") + ")\\b", "gi");
// collect all text nodes in the document
var textNodes = [];
$("body").find("*").contents().each(function() {
if (this.nodeType == 3)
textNodes.push(this)
});
// process N text nodes at a time, surround terms with text "markers"
function step() {
for (var i = 0; i < chunkSize; i++) {
if (!textNodes.length)
return done();
var node = textNodes.shift();
node.nodeValue = node.nodeValue.replace(terms, "\x1e$&\x1f");
}
setTimeout(step, 100);
}
// when done, replace "markers" with html
function done() {
$("body").html($("body").html().
replace(/\x1e/g, "<b>").
replace(/\x1f/g, "</b>")
);
}
// let's go
step()
}
像這樣使用它:
$(function() {
hilite(["highlight", "these", "words"], 100)
})
如果您有任何問題,請告訴我。
如何遍歷詞匯表中的每個術語,然后對每個術語使用正則表達式查找HTML中所有出現的內容? 您可以將這些事件中的每一個都替換為用“突出顯示”類包裹在范圍中的術語,該類將被設置為具有背景色。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.