一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

用Javascript解析html

 逗咳嗽 2015-12-13

該文章有更新,請(qǐng)移步 http://pickerel./admin/blogs/267912

 

說(shuō)到用Javascript解析html,大家肯定會(huì)想到dom或者正則表達(dá)式,但這兩個(gè)都不是我今天我要說(shuō)的。dom很不錯(cuò),不過(guò)效率不高,而且必須將要解析的html插入到當(dāng)前頁(yè)面或者建立一個(gè)iframe才能進(jìn)行,而用正則表達(dá)式,又有太過(guò)繁瑣和難以維護(hù)的問(wèn)題。

 

有人要說(shuō)了,ruby、php、python有了那么多開源的優(yōu)秀的html解析的類庫(kù),什么beautiful soap,什么Mechanize,什么Hpricot,什么ScRUBYt,你為什么非要自討苦吃用javascript來(lái)干這活呢?

 

答案是:如果只允許你用javascript和html開發(fā)程序呢,比如開發(fā)adobe air的程序,比如下一步我要做的基于基于內(nèi)嵌webkit組件的Android應(yīng)用快速開發(fā)框架,有時(shí)候,輪子還是得自己造的。

 

我的這個(gè)解析實(shí)現(xiàn)只是雛形,它以Erik Arvidsson開發(fā)的SimpleHtmlParser 作為html的分析器。SimpleHtmlParser是一個(gè)基于Sax模型實(shí)現(xiàn)的html分析器,他能分析非標(biāo)準(zhǔn)的xml的格式的html別把轉(zhuǎn)換作為一個(gè)標(biāo)準(zhǔn)的xml處理。有了這個(gè)解析器做基礎(chǔ),我寫了個(gè)簡(jiǎn)單的html_extractor,用來(lái)分析html并獲取指定標(biāo)記內(nèi)的內(nèi)容。

 

html_extractor的使用

 

new html_extractor(html): 指定html字符串創(chuàng)建一個(gè)html_extractor對(duì)象

方法:

tag(tagName):設(shè)定一個(gè)待匹配的元素名,返回結(jié)果為當(dāng)面的html_extractor對(duì)象

attr(attrName, attrValue):設(shè)定匹配的屬性條件,attr必須在tag后,返回結(jié)果為當(dāng)面的html_extractor對(duì)象

match(innerOrNot):執(zhí)行匹配,返回結(jié)果為符合條件的字符串?dāng)?shù)組。

示例:

 

Js代碼  收藏代碼
  1. html = "<div>div1</div>";  
  2. //取出div標(biāo)記下的內(nèi)容,ret的結(jié)果是["div1"]  
  3. var ret = new html_extractor(html).tag("div").match();  
  4.   
  5. html = "<div id=\"head\">head</div><div id=\"content\"><p><ul><li>item1</li><li>item2</li></ul></div>";         
  6. //取出屬性id=content的div下的所有l(wèi)i下的內(nèi)容,返回結(jié)果將是["item1", "item2"]  
  7. ret = new html_extractor(html).tag("div").attr("id""content").tag("li").match();  
  8.   
  9. //提取baidu搜索結(jié)果  
  10. ret = new html_extractor(html).tag("td").attr("class""f").match();  
  11. //提取google搜索結(jié)果  
  12. ret = new html_extractor(html).tag("li").attr("class""g").match();  

 

源代碼(當(dāng)前代碼還非常原始,進(jìn)攻參考,請(qǐng)慎重使用)

Js代碼  收藏代碼
  1. var html_extractor = function(html)  
  2. {  
  3.     this.parser = new SimpleHtmlParser;  
  4.     this.html  = html;  
  5.     this.tags = [];  
  6.     this.attrs = [];      
  7. }  
  8. html_extractor.prototype.tag = function(tag)  
  9. {  
  10.     this.tags.push(tag.toLowerCase());  
  11.   
  12.     return this;  
  13. }  
  14. html_extractor.prototype.attr = function(name, value)  
  15. {  
  16.     var len = this.tags.length - 1;  
  17.     if (this.attrs[len] == undefined)this.attrs[len] = [];  
  18.     this.attrs[len].push({name:name.toLowerCase(), value: value});  
  19.     return this;  
  20. }  
  21. html_extractor.prototype.match = function(inner)  
  22. {  
  23.     var self = this;  
  24.     var handler = function(){  
  25.         this._tag_index = 0;  
  26.         this._matched_tags = [];  
  27.         this._matched = [];  
  28.         this._result = "";  
  29.         this.result = [];  
  30.         this._all_matched = false;  
  31.         forvar i = 0; i < self.tags.length; i++)this._matched[i] = false;  
  32.         this.inner = true;  
  33.         if (inner != undefined && inner != null)  
  34.         {  
  35.             this.inner = inner;  
  36.         }  
  37.   
  38.     };  
  39.     handler.prototype = {  
  40.         startElement:   function (tag, attrs) {  
  41.             this.tag_index++;  
  42.             tag = tag.toLowerCase();  
  43.             //air.trace("process tag:" + tag +  " " + this.tag_index);  
  44.   
  45.             if (this._all_matched )  
  46.             {  
  47.                 this._result += get_start_tag(tag, attrs);  
  48.                 return;  
  49.             }  
  50.   
  51.             forvar i = 0; i < this._matched.length; i++)  
  52.             {  
  53.                 //air.trace(i + ":" + this._matched[i]);  
  54.                 if (!this._matched[i] )  
  55.                 {  
  56.                     if (self.tags[i] == tag)  
  57.                     {  
  58.                         this._matched[i] = true;  
  59.                         if (self.attrs[i] != undefined)  
  60.                         {  
  61.                             for(var n = 0; n < self.attrs[i].length; n++)  
  62.                             {  
  63.                                 var attr = self.attrs[i][n];  
  64.                                 if (attr != undefined)  
  65.                                 {  
  66.                                     if(attrs[attr.name] != attr.value)  this._matched[i] = false;  
  67.                                 };  
  68.                             }  
  69.                         }  
  70.                         if (this._matched[i] )  
  71.                         {  
  72.                              //todo callback  
  73.                              //air.trace(i + ":" + this._matched[i] + " first");  
  74.                              this._matched_tags[this.tag_index] = i;  
  75.                              if (i == self.tags.length -1)  
  76.                              {  
  77.                                  this._all_matched = true;  
  78.                                  if (!this.inner) this._result += get_start_tag(tag, attrs);  
  79.                              }  
  80.                              return;  
  81.                         }  
  82.                     }  
  83.   
  84.                     if (!this._matched[i] ){break;}  
  85.   
  86.                 }  
  87.             }         
  88.         },  
  89.         endElement:     function (tag) {  
  90.             tag = tag.toLowerCase();  
  91.   
  92.             if (this._matched_tags[this.tag_index] != undefined)  
  93.             {  
  94.                 this._matched[this._matched_tags[this.tag_index]] = false;  
  95.                 if (this._all_matched)  
  96.                 {  
  97.                     if (!this.inner)this._result += "</" + tag +">";  
  98.                     this.result.push(this._result);  
  99.                     this._result = "";  
  100.                     this._all_matched = false;  
  101.                 }  
  102.             }  
  103.             else if (this._all_matched)  
  104.             {  
  105.                 this._result += "</" + tag +">";  
  106.             }  
  107.             //air.trace("finished tag:" + tag +  " " + this.tag_index);  
  108.   
  109.             this.tag_index--;  
  110.         },  
  111.         characters:     function (s) { if(this._all_matched)this._result += s;},  
  112.         comment:        function (s) {}  
  113.     };  
  114.     this.parser.contentHandler = new handler;  
  115.   
  116.     this.parser.parse(this.html);     
  117.     //reset  
  118.     this.tags = [];  
  119.     this.attrs = [];  
  120.     return this.parser.contentHandler.result;  
  121. }  
  122. function get_start_tag(tag, attrs)  
  123. {  
  124.     var ret = "<" + tag;  
  125.     for (var key in attrs)  
  126.     {  
  127.         value = attrs[key];  
  128.         ret += " " + key + "=\"" + value + "\"";  
  129.   
  130.     }  
  131.     ret += ">";  
  132.     return ret;  
  133. }  
  134.   
  135. /** SimpleHtmlParser 
  136.  * Original code by Erik Arvidsson, Mozilla Public License 
  137.  * http://erik./simplehtmlparser/simplehtmlparser.js 
  138.  */  
  139.   
  140. /* 
  141. var handler ={ 
  142.     startElement:   function (sTagName, oAttrs) {}, 
  143.     endElement:     function (sTagName) {}, 
  144.     characters:     function (s) {}, 
  145.     comment:        function (s) {} 
  146. }; 
  147. */  
  148.   
  149. function SimpleHtmlParser()  
  150. {  
  151. }  
  152.   
  153. SimpleHtmlParser.prototype = {  
  154.   
  155.     handler:    null,  
  156.   
  157.     // regexps  
  158.   
  159.     startTagRe: /^<([^>\s\/]+)((\s+[^=>\s]+(\s*=\s*((\"[^"]*\")|(\'[^']*\')|[^>\s]+))?)*)\s*\/?\s*>/m,  
  160.     endTagRe:   /^<\/([^>\s]+)[^>]*>/m,  
  161.     attrRe:     /([^=\s]+)(\s*=\s*((\"([^"]*)\")|(\'([^']*)\')|[^>\s]+))?/gm,  
  162.   
  163.     parse:  function (s, oHandler)  
  164.     {  
  165.         if (oHandler)  
  166.             this.contentHandler = oHandler;  
  167.   
  168.         var i = 0;  
  169.         var res, lc, lm, rc, index;  
  170.         var treatAsChars = false;  
  171.         var oThis = this;  
  172.         while (s.length > 0)  
  173.         {  
  174.             // Comment  
  175.             if (s.substring(0, 4) == "<!--")  
  176.             {  
  177.                 index = s.indexOf("-->");  
  178.                 if (index != -1)  
  179.                 {  
  180.                     this.contentHandler.comment(s.substring(4, index));  
  181.                     s = s.substring(index + 3);  
  182.                     treatAsChars = false;  
  183.                 }  
  184.                 else  
  185.                 {  
  186.                     treatAsChars = true;  
  187.                 }  
  188.             }  
  189.   
  190.             // end tag  
  191.             else if (s.substring(0, 2) == "</")  
  192.             {  
  193.                 if (this.endTagRe.test(s))  
  194.                 {  
  195.                     lc = RegExp.leftContext;  
  196.                     lm = RegExp.lastMatch;  
  197.                     rc = RegExp.rightContext;  
  198.   
  199.                     lm.replace(this.endTagRe, function ()  
  200.                     {  
  201.                         return oThis.parseEndTag.apply(oThis, arguments);  
  202.                     });  
  203.   
  204.                     s = rc;  
  205.                     treatAsChars = false;  
  206.                 }  
  207.                 else  
  208.                 {  
  209.                     treatAsChars = true;  
  210.                 }  
  211.             }  
  212.             // start tag  
  213.             else if (s.charAt(0) == "<")  
  214.             {  
  215.                 if (this.startTagRe.test(s))  
  216.                 {  
  217.                     lc = RegExp.leftContext;  
  218.                     lm = RegExp.lastMatch;  
  219.                     rc = RegExp.rightContext;  
  220.   
  221.                     lm.replace(this.startTagRe, function ()  
  222.                     {  
  223.                         return oThis.parseStartTag.apply(oThis, arguments);  
  224.                     });  
  225.   
  226.                     s = rc;  
  227.                     treatAsChars = false;  
  228.                 }  
  229.                 else  
  230.                 {  
  231.                     treatAsChars = true;  
  232.                 }  
  233.             }  
  234.   
  235.             if (treatAsChars)  
  236.             {  
  237.                 index = s.indexOf("<");  
  238.                 if (index == -1)  
  239.                 {  
  240.                      this.contentHandler.characters(s);  
  241.                     s = "";  
  242.                 }  
  243.                 else  
  244.                 {  
  245.                     this.contentHandler.characters(s.substring(0, index));  
  246.                     s = s.substring(index);  
  247.                 }  
  248.             }  
  249.   
  250.             treatAsChars = true;  
  251.         }  
  252.     },  
  253.   
  254.     parseStartTag:  function (sTag, sTagName, sRest)  
  255.     {  
  256.         var attrs = this.parseAttributes(sTagName, sRest);  
  257.         this.contentHandler.startElement(sTagName, attrs);  
  258.     },  
  259.   
  260.     parseEndTag:    function (sTag, sTagName)  
  261.     {  
  262.         this.contentHandler.endElement(sTagName);  
  263.     },  
  264.   
  265.     parseAttributes:    function (sTagName, s)  
  266.     {  
  267.         var oThis = this;  
  268.         var attrs = {};  
  269.         s.replace(this.attrRe, function (a0, a1, a2, a3, a4, a5, a6)  
  270.         {  
  271.             //attrs.push(oThis.parseAttribute(sTagName, a0, a1, a2, a3, a4, a5, a6));  
  272.             attr = oThis.parseAttribute(sTagName, a0, a1, a2, a3, a4, a5, a6);  
  273.             attrs[attr.name] = attr.value;  
  274.         });  
  275.         return attrs;  
  276.     },  
  277.   
  278.     parseAttribute: function (sTagName, sAttribute, sName)  
  279.     {  
  280.         var value = "";  
  281.         if (arguments[7])  
  282.             value = arguments[8];  
  283.         else if (arguments[5])  
  284.             value = arguments[6];  
  285.         else if (arguments[3])  
  286.             value = arguments[4];  
  287.   
  288.         var empty = !value && !arguments[3];  
  289.         return {name: sName.toLowerCase(), value: empty ? null : value};  
  290.     }  
  291. };  

 

 

 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    亚洲中文字幕在线乱码av| 好骚国产99在线中文| 亚洲婷婷开心色四房播播| 亚洲伊人久久精品国产| 一区二区日本一区二区欧美| 亚洲精品中文字幕欧美| 黑色丝袜脚足国产一区二区| 99久久精品午夜一区| 日韩精品毛片视频免费看| 日本精品中文字幕在线视频 | 精品推荐久久久国产av| 欧美三级精品在线观看| 深夜视频在线观看免费你懂| 激情综合五月开心久久| 热久久这里只有精品视频| 久久热在线免费视频精品| 精品国模一区二区三区欧美| 婷婷一区二区三区四区| 开心五月激情综合婷婷色| 国产精品视频第一第二区| 日韩偷拍精品一区二区三区| 国产亚洲欧美自拍中文自拍| 欧美日韩亚洲国产综合网| 亚洲欧美日韩国产自拍| 成人欧美精品一区二区三区| 久草精品视频精品视频精品| 欧美尤物在线观看西比尔| 日本加勒比不卡二三四区| 在线免费国产一区二区| 91欧美激情在线视频| 麻豆一区二区三区精品视频| 日本成人三级在线播放| 欧美精品一区二区水蜜桃| 国产一区日韩二区欧美| 中文字幕一区二区免费| 亚洲男人天堂网在线视频| 国产精品免费视频久久| 欧美国产极品一区二区| 一本色道久久综合狠狠躁| 国产午夜福利一区二区| 国产一区二区三区精品免费|