乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      正則表達(dá)式內(nèi)存耗盡異常解決方案 - 星星的日志 - 網(wǎng)易博客

       命運之輪 2009-06-18

      正則表達(dá)式內(nèi)存耗盡異常解決方案 2009-03-15 10:01

      前面碰到的正則表達(dá)式匹配時,產(chǎn)生的內(nèi)存耗盡異常,大概提到兩種方案,一種是給匹配建立線程,超時時把它殺死。另一種則從其根源上看,即正則表達(dá)式產(chǎn)生內(nèi)存耗盡異常的原因是,由于匹配是個np完全問題,為了避免無限執(zhí)行下去,所以實現(xiàn)中一般對匹配中達(dá)到的狀態(tài)進(jìn)行了計數(shù),當(dāng)狀態(tài)達(dá)到了一定數(shù)目則拋出這個異常。

      究其原因是因為匹配表達(dá)式中出現(xiàn)了太多的.*,導(dǎo)致匹配的可能性大大增加,出現(xiàn)的回溯次數(shù)增多,對于web頁面的匹配,我們結(jié)合一下,提出如下匹配方式,即把原來的一次匹配,改成多層匹配,即首先利用上層匹配,縮小匹配的文本,然后再在已經(jīng)滿足上層匹配的文本中進(jìn)行下層的匹配。

      比如(?<=<li class=g>).*?<.*?><a.*?href="(.*?)"[^>]*?>(.*?)</a>(.*?)<br>.*?<cite>(.*?)</CITE>.*?(?=</a></span>)

      我們則拆成下面兩個匹配過程:

      (?<=<li class=g>)(.*?)(?=</a></span>)

      .*?<.*?><a.*?href="(.*?)"[^>]*?>(.*?)</a>(.*?)<br>.*?<cite>(.*?)</CITE>.*?

      具體實現(xiàn),我們則將原來的正則表達(dá)式,改成多個的組合,兩個正則式之間用token char隔離。

      注意:

      1.由于我們采用了空格作為分割正則表達(dá)式的標(biāo)志,因此必須把正則表達(dá)式本身含有的空格全部使用\s替代。因此必須注意保證config.xml里的正則表達(dá)式與這里所采用的處理方式相一致。

      2.正則表達(dá)式中,不要出現(xiàn)不成對的<,因為后面我們要利用<>去除標(biāo)簽內(nèi)的文字。

      3.有時候雖然在正則匹配測試工具里匹配成功,但是在程序中也可能依然錯誤,原因就是,在我們程序中對正則式中空格的特殊性的使用造成的。

      現(xiàn)在的實現(xiàn)實際上是遞歸實現(xiàn):實際上我們在遞歸時采用的是what[0].也就意味著實際上我們用上層匹配的結(jié)果作為下層的范圍。實際上如果我們修改成what[1]將允許我們使用更加復(fù)雜的篩選.比如我們(?<=<li

      recurseSearch(regex_exprs,web_text,set,what[0].first,what[0].second,level+1);


          /*
          完成正則表達(dá)式的多層匹配,上一層的匹配結(jié)果作為下一層的輸入串,繼續(xù)進(jìn)行匹配,層層過濾。 
          參數(shù)如下:
          regex_exprs-代表所有各層正則表達(dá)式的集合
          web_text-要處理的網(wǎng)頁文本
          set-保存結(jié)果的集合
          start-待處理的文本的起始處
          end- 待處理的文本的結(jié)束處
          level-控制結(jié)束,及當(dāng)前處理那個正則表達(dá)式的層數(shù),從1開始計數(shù)。
          */
         void HtmlParser::recurseSearch(vector<boost::regex> &regex_exprs,WebText &web_text,ResultSet &set,str_const_iterator start,str_const_iterator end,int level){
            
        //int index = web_text.start_index;        
        boost::smatch what;
        boost::regex expression = regex_exprs[level-1];
        while( boost::regex_search(start, end, what, expression) )
        {
            //如果是最終的那個正則表達(dá)式 ,則開始搞結(jié)果
            if(level == regex_exprs.size()){           
          Result elem(web_text.source.getName());    
          int sub_count = (int)what.size();
          for(int i = 1 ; i < sub_count ; i++ ){
             std::string msg(what[i].first, what[i].second);
             elem.setBySubNumber(msg,(RES_CONTENT_TYPE)i);
          }
          //注意我們這里修改了 web_text.start_index的值,用它來給結(jié)果在網(wǎng)頁中的索引賦值。
          elem.setIndexInSource(web_text.start_index);     
          web_text.start_index++;
          elem.deleteBrace();
          set.addResult(elem);    
         }
         else{
          recurseSearch(regex_exprs,web_text,set,what[0].first,what[0].second,level+1);
         } 
          start = what[0].second;     
         }
             


         }

       
         
          /*
              利用正則表達(dá)式,從網(wǎng)頁中抽取每條搜索結(jié)果,具體則通過調(diào)用 HtmlParser::recurseSearch實現(xiàn)
              并將結(jié)果直接保存到 ResultSet中
              使用時,由 ResultSet調(diào)用,同時本身回調(diào)ResultSet里的addResult方法,添加搜索結(jié)果
          */
          void HtmlParser::webParse(WebText &web_text,ResultSet &set){
              try{
                  debug_log("HtmlParser::webParse:download web:" ,web_text.text);

         string web_regex = web_text.getRegex();     
         vector<boost::regex> regex_exprs;
         /*
         注意,如果選擇'!',則只能處理一個正則式的情況,無法處理多層正則的情況。
         所以如果想恢復(fù)原來的模式,只需要把這里的string_token()的第二個參數(shù)改成'!',
         同時保證config.xml里的正則表達(dá)式只有一個即可。
         */
         vector<string> regex_tokens = string_token(web_regex,' ');
         for(int i = 0 ; i < regex_tokens.size(); i++){       
            boost::regex expression(regex_tokens[i],boost::regex::perl|boost::regex::icase);
            regex_exprs.push_back(expression);
         }   
         str_const_iterator start = web_text.text.begin();
         str_const_iterator end = web_text.text.end();    
          
                  recurseSearch(regex_exprs,web_text,set,start,end,1);
            }
         catch(boost::regex_error e){
            string exception_str = string("exception:expression is not a valid regular expression: \"") + e.what() + "\"";
            debug_log(web_text.getSiteName()+"-HtmlParser::webParse:",exception_str);
          cout<< exception_str <<endl;

         }
         catch(std::runtime_error e){
            string exception_str = string("exception:expression runtime_error: \"") + e.what() + "\"";
            debug_log(web_text.getSiteName()+"HtmlParser::webParse:",exception_str);
          cout<< exception_str <<endl;
         }
         catch(std::bad_alloc e){
            string exception_str = string("exception:expression bad_alloc: \"") + e.what() + "\"";
            debug_log(web_text.getSiteName()+"HtmlParser::webParse:",exception_str);
          cout<< exception_str <<endl;
         }
          }
         

      以前的實現(xiàn)如下:

      /*
          void HtmlParser::webParse(WebText &web_text,ResultSet &set){
              try{
         string web_regex = web_text.getRegex();
         
         boost::regex expression(web_regex,boost::regex::perl|boost::regex::icase);       
         boost::smatch what;
         str_const_iterator start = web_text.text.begin();
         str_const_iterator end = web_text.text.end(); 
         
                  debug_log("HtmlParser::webParse:download web:" ,web_text.text);
         int index = web_text.start_index;
        
         while( boost::regex_search(start, end, what, expression) )
         {           
          Result elem(web_text.source.getName());    
          //std::cout<< "Have:" ;
          int sub_count = (int)what.size();
          for(int i = 1 ; i < sub_count ; i++ ){
             std::string msg(what[i].first, what[i].second);
             //std::cout<< msg.c_str() << std::endl;
             elem.setBySubNumber(msg,(RES_CONTENT_TYPE)i);
          }
          start = what[0].second;     
          elem.setIndexInSource(index);     
          index++;
          elem.deleteBrace();
          set.addResult(elem);
         }
            }
         catch(boost::regex_error e){
            string exception_str = string("exception:expression is not a valid regular expression: \"") + e.what() + "\"";
            debug_log(web_text.getSiteName()+"-HtmlParser::webParse:",exception_str);
          cout<< exception_str <<endl;

         }
         catch(std::runtime_error e){
            string exception_str = string("exception:expression runtime_error: \"") + e.what() + "\"";
            debug_log(web_text.getSiteName()+"HtmlParser::webParse:",exception_str);
          cout<< exception_str <<endl;
         }
         catch(std::bad_alloc e){
            string exception_str = string("exception:expression bad_alloc: \"") + e.what() + "\"";
            debug_log(web_text.getSiteName()+"HtmlParser::webParse:",exception_str);
          cout<< exception_str <<endl;
         }
          }
          */

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

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多