コンピューター言語は無条件に厳格であり、構成は通常、実行される機能(演算子、数字、文字列など)に従って強調表示されます。最初に思い浮かぶのは、自然なテキスト(主題、述語など)の同様の強調表示です。例として、F。M.ドストエフスキーによる「幻想的な物語」の始まりを考え、すべての主題を緑色で、述語を青色で選択します。
このようなマークアップには、テキストのかなり複雑な分析が必要ですが、私の意見では、ハイライトは複雑にすべきではありません(ハイライトアルゴリズムの速度はページの読み込み速度とほぼ同じでなければなりません)。 私は、より単純なバージョン、つまり、頻繁に単語が繰り返されるほど意味が伝わらないという考えに基づいて、頻度を強調することに専念することにしました。 厳密に言えば、これは確かに真実ではありませんが、ドストエフスキーのすでに示されたパッセージをマークし、ストーリーでさらに使用されていない単語を太字でマークすると、次のようになります:
単語の選択はテキストの認識に大きな影響を与えるため、独自のソリューションまたはソリューションがあり、そのアルゴリズムは公開されています。 このため、この記事の残りの部分では、このようなChromeの拡張機能の開発に専念します。
まず、指定された正規表現に従って、単語頻度辞書を更新する関数を作成します。
function collect(text, frequences, pattern) { var words = text.split(/\s+/); // for (var j = 0; j < words.length; j++) { // var current = words[j].toLowerCase().replace(pattern,''); // if (!current || current.length < MIN_LENGTH) continue; // -- , -- if (!frequences[current]) frequences[current] = 1; else frequences[current] += 1; } }
DOMからの単語の使用に関する統計を収集します。
var pattern = /[^-]/g var freq = {} function stat(element) { if (/(script|style)/i.test(element.tagName)) return; // if (element.nodeType === Node.ELEMENT_NODE && element.childNodes.length > 0) for (var i = 0; i < element.childNodes.length; i++) stat(element.childNodes[i]); // collect if (element.nodeType === Node.TEXT_NODE && (/\S/.test(element.nodeValue))) { collect(element.nodeValue, freq, pattern); } } stat(window.document.getElementsByTagName('html')[0]);
次に、必要以上に一般的な単語を統計から除外します。
function remove(o, max) { var n = {}; for (var key in o) if (o[key] <= max) n[key] = o[key]; return n; } freq = remove(freq, maxFreq);
そして最後に、私たちにとって興味深いすべての単語の出現を強調します。
function markup(element, pattern) { if (/(script|style)/i.test(element.tagName)) return; // if (element.nodeType === Node.ELEMENT_NODE && element.childNodes.length > 0) { // , -, , var freq = {}; for (var i = 0; i < element.childNodes.length; i++) if (element.childNodes[i].nodeType === Node.TEXT_NODE && (/\S/.test(element.childNodes[i].nodeValue))) collect(element.childNodes[i].nodeValue, freq, pattern); if (freq && freq.length !== 0) { var efreq = []; var total = 0; // , // [, ] , // , for (var key in freq) if (freqRus[key]) efreq.push([key, freq[key]]); efreq.sort(function(a, b) {return a[0].length - b[0].length}); // , -, // var max = element.childNodes.length*efreq.length*2; for (var i = 0; i < element.childNodes.length; i++) { if (total++ > max) break; if (element.childNodes[i].nodeType === Node.TEXT_NODE) { var minPos = -1, minJ = -1; // for (var j in efreq) { key = efreq[j][0]; var pos = element.childNodes[i].nodeValue.toLowerCase().indexOf(key); if (pos >= 0 && (minJ === -1 || minPos>pos)) { minPos = pos; minJ = j; } } // -- if (minPos !== -1) { key = efreq[minJ][0]; val = efreq[minJ][1]; // , , "strong" var spannode = window.document.createElement('strong'); var middle = element.childNodes[i].splitText(minPos); var endbit = middle.splitText(key.length); var middleclone = middle.cloneNode(true); spannode.appendChild(middleclone); element.replaceChild(spannode, middle); } } } } } } } markup(window.document.getElementsByTagName('html')[0], pattern);
おわりに
単語の形式を考慮に入れると便利です。履歴を蓄積できます(つまり、1ページのフレームワーク内ではなく、すべてを収集して頻度辞書を作成できます)。 さらに、辞書に影響を与えることができると便利です(いくつかの単語を修正し、決して含めないでください)。
完全な例は、githubで取得できます。
github.com/parsifal-47/nalacol
またはすぐにChromeのアプリケーションとして:
chrome.google.com/webstore/detail/natural-language-colorer/jjcldlhpnolppcclcgdbblbilmealfjd
この記事が読者に自然言語でテキストをハイライトするための興味深いアルゴリズムを作成するように促すことを嬉しく思います。