背景:HTMLの要件は、その後、いくつかのプロセス/操作、DOMオブジェクトツリーまたはオブジェクトツリーJSに文字列をオンにする必要があります。
htmlparser
ライブラリは大丈夫でしたが、属性変換にいくつかの特別なプロパティ値では動作しません。また、オープンラベルの構文``(見
構文開始タグ:WHATWG
)、 `HTML属性のサポートrules`(
属性:WHATWG
)といくつかのいくつかの境界のシナリオで他のライブラリの実装、(特殊な属性値および
Webコンポーネント
)プロセスまたは自身のライン...よく、の欠如と、それはより良いHTMLパーサの機能を持っていました。
この資料は、技術的沈殿であることが、記録処理の下で達成され、関連する要件への参照が存在してもよいです。
前処理
まず、コンテンツを見つけることを期待して一致させるために、いくつかの正規表現を定義します
CONST ltReg = / \ </グラム のconst gtReg = / \> / gの constのsqReg = / '/ gを CONST qReg = / "/ gでの CONST sqAttrReg = /(?<= \ = ')[^'] *?(? = ')/ G CONST qAttrReg = /(?<= \ = ")[^"] *?(?= ")/ gの CONST qRegBk = /" / G CONST sqRegBk = /' / G CONST ltRegBk = / </ G CONST gtRegBk = /> /グラム CONST attrReplaceReg = /[\:\w\d_-]*?=(["].*?["]|['].*?['])/g CONST attrReg = /(?<=\s)([\:\w\d\-]+\=(["'].*?["']|[\w\d]+)|\w+)/g のconst numReg = / ^ \ dの+ $ / constのclReg = / \ N / gでの CONST SREG = / \ S /グラム のconst spReg = / \ sの+ /グラムの CONST tagReg = / \ <[^ \ <\>] *?\> / CONST startReg = / \ <[^ \ / \!]。*?\>/ constのendReg = /\<\/.*?\>/ constのcommentReg = /(?<=\<\!\-\-).*?(?=\-\-\>)/ CONST tagCheckReg = / [\ \ W - ](<= \ <?)+ /
一例として、単純なHTML文字列を取るために、処理ロジックを開始します。
CONST STR = ' <DIV ID = "コンテナ"> <DIV CLASS = "テスト"データHTML = "<P>ハロー1 </ P>"> <P>ハロー2 </ P> の<input type = "text "値="ハロー3" > </ div> </ div> `
プロパティ値のエスケープ
、開いている各タブを取って、文字列strを取得代わりに文字をエスケープするか、タグや特殊文字以内属性、文字列STR1を返します
CONST replaceAttribute =(HTML:文字列):文字列=> { 戻りhtml.replace(attrReplaceReg、V => { 戻りVの .replace(ltReg、 '<') .replace(gtReg、 '>') .replace(sqAttrReg、V => { 戻りv.replace(qReg、「" ') }) .replace(qAttrReg、V => { 戻りv.replace(sqReg、 ''') }) }) }
結果は以下の通りであります:
; `<DIV ID = "コンテナ"> <DIV CLASS = "テスト"データHTML = "<P>ハロー1 </ P>"> <P>ハロー2 </ P> の<input type = "text"の値= "ハロー3"> </ div> </ div> `
コンテンツのアレイを形成します
0009ステップで文字列から切り出した要素:新しい配列ARRに配置され、(要素であるオープンラベル、コンテンツ、タグ閉鎖)。
CONST convertStringToArray =(HTML:列)=> { せprivateHtml = HTML せtemporaryHtml = HTML CONSTのARR = [] 一方(privateHtml.match(tagReg)){ privateHtml = temporaryHtml.replace(tagReg、(V、I)=> { (I> 0){もし CONST値= temporaryHtml.slice(0、I) (value.replace(SREG、 '').LENGTH> 0){もし arr.push(値) } } temporaryHtml = temporaryHtml.slice(I + v.length) arr.push(V) リターン'' }) } 戻りARR }
結果は以下の通りであります:
[ "<DIV ID =" コンテナ ">"、 "<DIV CLASS =" テスト "データHTML = "<P>ハロー1 </ P>">"、 "<P>"、 "ハロー2"、 " </ P> " "<入力タイプ=" テキスト" 値= "ハロー3">」、 "</ div>"、 "</ div>"]
生成オブジェクトツリー
ARRのステップは、処理対象のツリーに、循環上に形成されました
//単一ラベルセットの VAR = singleTags [ 'IMG'、 'INPUT'、 'BR'、 'HR'、 'メタ'、 'リンク'、 'PARAM'、 'ベース'、 'BASEFONT'、 '地域'、 "ソース「 『トラック』、 『埋め込み』 ] // DomUtilオブジェクトは、関数又はnodejsに従ってJS / DOMオブジェクト・ブラウザ環境を生成することであることを特徴とする請求 VAR makeUpTree =関数(ARR){ VARルートDomUtil =(」コンテナ「) VAR = 0ディープ parentElements = VAR [ルート] arr.forEach(関数(I){ VAR parentElement = parentElements [parentElements。長さ- 1] IF(parentElement){ VAR inlineI = toOneLine(I) //オープンラベル治療、新しいオープンラベルタグ (startReg.test(inlineI)){IF ディープ++の VARタグ名= i.match(tagCheckReg) IF(!tagNameを){ スローエラー( 'ラベル指定エラー') } 1 = DomUtil(tagNameを[0]) - VARのELEMENT VAR ATTRS = matchAttr (I) attrs.forEach(関数(ATTR){ IF(ELEMENT - 1){ element_1.setAttribute(ATTR [0]、ATTRの[1]) } }) parentElement.appendChild(ELEMENT - 1) //単一ラベルの治療、deep--、閉フラグを完了 IF( singleTags.indexOf(tagNameを[0])> -1 || i.charAt(i.length - 2)=== '/' ){ deep-- }他{ parentElements.push(element_1) } } //闭合标签处理 他IF(endReg.test(inlineI)){ deep-- parentElements.pop() }そうであれば(commentReg.test(inlineI)){ VAR matchValue = i.match(commentReg) var注釈= matchValue?matchValue [0]: ' 深い++の VAR要素= DomUtil( 'コメント'、コメント) parentElement.appendChild(要素) deep-- }他{ 深い++用 のvarのTextElement = DomUtil( 'テキスト'、I) parentElement.appendChild(のTextElement) ディープ- } } }) (ディープIF <0){ スローエラー( '過剰ラベルの閉鎖存在') }他IF(ディープ> 0){ スローエラー( '過剰オープンラベルの存在') } 戻りroot.children }
結果は以下の通りであります:
[ { ATTRS:{ ID: 'コンテナー' }、 parentElement:[DOMELEMENT]、 子供:[ { ATTRS:{ クラス: 'テスト'、 'データHTML': '<P>ハロー1 </ P>' }、 parentElement:[DOMELEMENT]、 子供:[ { ATTRS:{}、 parentElement:[DOMELEMENT]、 子供:[ { ATTRS:{}、 parentElement:[DOMELEMENT]、 子供:[]、 tagNameを: 'テキスト'、 データ'こんにちは2' } ]、 tagNameを'P' }、 { ATTRS:{ タイプ: 'テキスト'、 値'ハロー3' }、 parentElement:[DOMELEMENT]、 子供:[]、 tagNameを'入力' } ]、 tagNameを' DIV」 } ]、 tagNameを: 'DIV' } ]
組み合わせ
上記の3つのステップの組み合わせ
CONSTパーサー=(HTML:列)=> { CONST htmlAfterAttrsReplace = replaceAttribute(HTML) CONSTのStringArray = convertStringToArray(htmlAfterAttrsReplace) CONST domTree = makeUpTree(のStringArray) domTreeを返します }
テスト
最後に、波をテストしてください。
チュウヤ/淘宝網/百度/ JD / TXホームページやニュースページは、HTMLが多く、HTML文字に比べて `100ms`以内に完了基本的な実行の波、そしておそらく数千人のような数のDOMを、テストコピーされますATTRSオブジェクトと文字列のオブジェクトの属性は、まだ対応します。
EMM ...かなり、との最初の行。
遂に
コードを書くには十分満足して何...
あなたが私たちのチームに興味がある場合は、参加することを歓迎し、あなたの参加を楽しみにして、あなたは私のメール[email protected]を提供することができます!
より多くのジョブを表示することができ
チュウヤ動員を