簡體   English   中英

在HTML文檔中突出顯示詞匯表術語

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM