日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

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

 命運(yùn)之輪 2009-06-18

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

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

究其原因是因?yàn)槠ヅ浔磉_(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>.*?

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

注意:

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

2.正則表達(dá)式中,不要出現(xiàn)不成對的<,因?yàn)楹竺嫖覀円?lt;>去除標(biāo)簽內(nèi)的文字。

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

現(xiàn)在的實(shí)現(xiàn)實(shí)際上是遞歸實(shí)現(xiàn):實(shí)際上我們在遞歸時采用的是what[0].也就意味著實(shí)際上我們用上層匹配的結(jié)果作為下層的范圍。實(shí)際上如果我們修改成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實(shí)現(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;
   }
    }
   

以前的實(shí)現(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ā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多