2011-12-03 71 views
1

我們有多達2000和術語詞彙表(其中每個詞彙表術語可以 包括一個,兩個或三個詞(或者使用空格 或破折號)分離。突出一個HTML文檔內術語詞彙表

現在我們正在尋找一個解決方案,用於突出顯示 (更長)HTML文檔(最多100 KB的HTML標記)內的所有術語,以便 生成帶有高亮條款的靜態HTML頁面。解決方案是:大量術語表術語 和長HTML文檔...什麼是藍圖有效解決方案 (在Python中)。

現在我正在考慮使用lxml解析HTML文檔,迭代所有文本節點,然後將每個文本節點中的內容與所有術語表術語進行匹配。

即時突出顯示的客戶端(瀏覽器)不是一個選項,因爲IE會抱怨腳本超時的長時間運行的腳本......因此不適合用於生產。

有什麼更好的想法嗎?

+0

你可能想看看美麗的湯爲你的解析 –

+0

我評論和沒有回答的事實應該指出,我可能有足夠的時間在我的手中實際寫出正確的答案。見下文。 –

+0

您不必在一個循環中使用客戶端的highlite。使用setTimeout來模擬協同例程。 – Dykam

回答

-1

如何查看術語表中的每個術語,然後對每個術語使用正則表達式來查找HTML中的所有事件?您可以將這些事件中的每一個替換爲包含在跨度中的術語,並使用「突出顯示」類來進行樣式化,以獲得背景顏色。

+0

那麼如果詞彙表術語在頁面的標題或元(可以預期),或者更糟糕,如果文檔是關於html本身並且說「form」是術語表術語呢? –

+0

好點。正則表達式可以通過不考慮「<>」中包含的任何內容來解釋元素。 –

+1

讓我爲堅持道歉,但使用正則表達式來解析HTML是[一個壞主意](http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/ 1732454#1732454)。更重要的是,除非你的問題很簡單(這裏可能會或可能不會),但除非你是一個正則表達式大師,否則你可能無法做到。解析HTML **是一個解決的問題,所以你應該使用正確的工具來完成。 –

2

您可以使用解析器以遞歸方式導航樹並僅替換由文本組成的標籤。
在這樣做,仍然有幾件事情你需要考慮:
- 並非所有的文本需要更換(如內嵌的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') 

這應該替換「A」與「b」,但留下內容的任何occurence那就是:
- Inside inline javascript或css(雖然內聯JS或CSS不應出現在文檔的正文中)。
- 在諸如IMG標記的一個參考,一個...
- 一個標籤本身當然

,你一定要去,這取決於你的詞彙表,以確保你不會只更換部分與其他事物相關的詞;要做到這一點是有道理的使用regex insted content.replace。

0

我認爲突出顯示與客戶端JavaScript是最好的選擇。它可以節省您的服務器處理時間和帶寬,更重要的是,可以保持html清潔並可用於那些不需要不必要標記的人員,例如打印或轉換爲其他格式時。

爲了避免超時,只需將作業拆分成塊,然後在setTimeout out函數中逐個處理它們。下面是這種方法的一個例子

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) 
}) 

讓我知道如果你有問題。

相關問題