模板引擎正则表明式调节和测验小本事

依附前两篇的博文:

Apache/2.2.9 (Win32) +
PHP/5.2.17,在使用正则表明式
preg_match_all (如
preg_match_all(“/ni(.*?)wo/”, $html,
$matches);)进行深入分析相称相比长的字符串 $html
时(大于10万字节,一般用于解析收集回来的网页源码),Apache服务器会崩溃自动重启。

平台是windows server 2003(32位系统) + Apache/2.2.9 (Win32) +
PHP/5.2.17,在使用正则表明式
preg_match_all (如
preg_match_all(“/ni(.*?)wo/”, $html,
$matches);)实行解析相称比较长的字符串 $html
时(大于10万字节,一般用来分析收罗回来的网页源码),Apache服务器会崩溃自动重启。

基邹静之则表明式替换的模版引擎很轻松遇上正则表明式最大回想/递归的限制。
惰性相配并不可怕,不荒谬意况下模板并不会相当不足用,往往不会压倒限制,discuz的沙盘引擎就大方应用了。不过因而而不去留神、不去学学,则轻巧书写错误并遇上难点。
当preg_*回来的是null的时候则要留心了,判定函数是is_null.
阴差阳错并不吓人,可是最为把错误都完全的输出,那样调节和测量试验就很轻松了。
除却输出出错原因,还要输出匹配的文件和应用的正则,那样就很轻巧调节和测量检验了。
PHP代码

基于curl数据搜聚之单页面收集函数get_html的使用

在Apache错误日志里有如此的升迁:

在Apache错误日志里有那样的唤醒:

复制代码 代码如下:

基于curl数据搜聚之单页面并行收罗函数get_htmls的使用

[Thu Apr 11 18:31:31 2013] [notice] Parent: child process exited
with status 128 — Restarting.
[Thu Apr 11 18:31:31 2013] [notice] Apache/2.2.9 (Win32) PHP/5.2.17
configured — resuming normal operations
[Thu Apr 11 18:31:31 2013] [notice] Server built: Jun 13 2008
04:04:59
[Thu Apr 11 18:31:31 2013] [notice] Parent: Created child process
2964
[Thu Apr 11 18:31:31 2013] [notice] Disabled use of AcceptEx()
WinSock2 API
[Thu Apr 11 18:31:31 2013] [notice] Child 2964: Child process is
running
[Thu Apr 11 18:31:31 2013] [notice] Child 2964: Acquired the start
mutex.
[Thu Apr 11 18:31:31 2013] [notice] Child 2964: Starting 350 worker
threads.
[Thu Apr 11 18:31:31 2013] [notice] Child 2964: Listening on port
80.

[Thu Apr 11 18:31:31 2013] [notice] Parent: child process exited
with status 128 — Restarting.
[Thu Apr 11 18:31:31 2013] [notice] Apache/2.2.9 (Win32) PHP/5.2.17
configured — resuming normal operations
[Thu Apr 11 18:31:31 2013] [notice] Server built: Jun 13 2008
04:04:59
[Thu Apr 11 18:31:31 2013] [notice] Parent: Created child process
2964
[Thu Apr 11 18:31:31 2013] [notice] Disabled use of AcceptEx()
WinSock2 API
[Thu Apr 11 18:31:31 2013] [notice] Child 2964: Child process is
running
[Thu Apr 11 18:31:31 2013] [notice] Child 2964: Acquired the start
mutex.
[Thu Apr 11 18:31:31 2013] [notice] Child 2964: Starting 350 worker
threads.
[Thu Apr 11 18:31:31 2013] [notice] Child 2964: Listening on port

<?php
if (is_null($tmp)){
模板引擎正则表明式调节和测验小本事。$error_code = preg_last_error();
switch($error_code){
case PREG_NO_ERROR :
echo ‘PREG_NO_ERROR’;
break;
case PREG_INTERNAL_ERROR:
echo ‘PREG_INTERNAL_ERROR’;
break;
case PREG_BACKTRACK_LIMIT_ERROR:
echo ‘PREG_BACKTRACK_LIMIT_ERROR’;
break;
case PREG_RECURSION_LIMIT_ERROR:
echo ‘PREG_RECURSION_LIMIT_ERROR’;
break;
case PREG_BAD_UTF8_ERROR:
echo ‘PREG_BAD_UTF8_ERROR’;
break;
case PREG_BAD_UTF8_OFFSET_ERROR:
echo ‘PREG_BAD_UTF8_OFFSET_ERROR’;
break;
default:
echo ‘UNKNOW ERROR’;
}
exit;
}

已经足以获得了小编们必要的html文件,今后内需处理得到的文本获取到大家须要的搜罗的数额。

透过查阅Apache官方以及论坛资料后,发掘win平台下用正则 preg_match_all
或preg_match
分析相比长的字符串时,导致apache崩溃重启的原故是windows平台下暗许分配的线程仓库空间
ThreadStackSize 太小导致的。 win32暗许独有256KB,而在
linux下暗中认可值是
8M,那正是为啥一样的先后在 linux平台下通常,而在
win平台下不正规的来头。

参谋资料 1、2010, Laruence
《深悉正则(pcre)最大回忆/递归限制》
2、2013,
PHP普通话手册preg_last_error

对于html文档的分析,未有像XML那样的分析类,因为HTML文档有大多不成对的价签,很不严俊。那一年就需要选用任何的局部扶助类了,simplehtmldom是一个近乎于JQuery格局操作HTML文书档案的深入分析类。能够很有利的获得想要的数额,缺憾速度慢。这里不是大家这里切磋的第一,小编最首要运用正则来合营自身所要求的募集的数据,能够异常的快捷的拿走小编急需搜聚的音讯。

依靠PCRE library的合法表明:256 KB
的库房空间对应的pcre.recursion_limit大小应该不超越524。
Here is a table of safe values of pcre.recursion_limit for a variety of
executable stack sizes:
下边正是一张Stacksize和pcre.recursion_limit对应的建议安全值,超过那么些数值就极有希望产生仓库溢出,apache
crash:

透过查阅Apache官方以及论坛资料后,发掘win平台下用正则 preg_match_all
或preg_match
剖判比较长的字符串时,导致apache崩溃重启的来由是windows平台下暗许分配的线程货仓空间
ThreadStackSize 太小导致的。 win32私下认可唯有256KB,而在 linux下暗中认可值是
8M,这正是干吗一样的次第在 linux平台下符合规律,而在
win平台下不正规的原因。

您也许感兴趣的文章:

  • 正则表明式高端学习技巧
  • ASP正则表明式技能
  • PHP
    正则表明式的几则利用本事
  • 正则表明式高端技巧及实例详解
    笨活儿
  • javascript 正则表明式(二)
    使用才能表明
  • 正则表明式的尖端手艺分享
  • .NET
    正则表明式使用高等本领之替换类介绍
  • 正则表明式相配不带有有个别字符串的技能
  • 写出高作用的正则表明式本事计算

考虑到get_html能够断定再次回到的数码,不过get_htmls未有艺术判定,为了便利调式和调用写了之类七个函数:

Stacksize   pcre.recursion_limit
 64 MB      134217
 32 MB      67108
 16 MB      33554
  8 MB      16777
  4 MB      8388
  2 MB      4194
  1 MB      2097
512 KB      1048
256 KB      524
只要你未曾调动货仓大小,就亟须在采纳正则的PHP页面最起先参预:

依据PCRE library的官方认证:256 KB
的货仓空间对应的pcre.recursion_limit大小应该不当先524。
Here is a table of safe values of pcre.recursion_limit for a variety of
executable stack sizes:
上面正是一张Stacksize和pcre.recursion_limit对应的提议安全值,超越这一个数值就极有望爆发货仓溢出,apache
crash:
Stacksize   pcre.recursion_limit
 64 MB      134217
 32 MB      67108
 16 MB      33554
  8 MB      16777
  4 MB      8388
  2 MB      4194
  1 MB      2097
512 KB      1048
256 KB      524

复制代码 代码如下:

<?php
ini_set(“pcre.recursion_limit”, “524”); // PHP default is 100,000.
?>

若果您未曾调解酒店大小,就非得在使用正则的PHP页面最早先参预:

function
get_matches($pattern,$html,$err_msg,$multi=false,$flags=0,$offset=0){
     if(!$multi){
         if(!preg_match($pattern,$html,$matches,$flags,$offset)){
             echo $err_msg.”! 错误消息:
“.get_preg_err_msg().”\n”;
             return false;
         }
     }else{
        
if(!preg_match_all($pattern,$html,$matches,$flags,$offset)){
             echo $err_msg.”! 错误新闻:
“.get_preg_err_msg().”\n”;
             return false;
         }
     }
     return $matches;
 }
 function get_preg_err_msg(){
     $error_code = preg_last_error();
     switch($error_code){
         case PREG_NO_ERROR :
             $err_msg = ‘PREG_NO_ERROR’;
             break;
         case PREG_INTERNAL_ERROR:
             $err_msg = ‘PREG_INTERNAL_ERROR’;
             break;
         case PREG_BACKTRACK_LIMIT_ERROR:
             $err_msg = ‘PREG_BACKTRACK_LIMIT_ERROR’;
             break;
         case PREG_RECURSION_LIMIT_ERROR:
             $err_msg = ‘PREG_RECURSION_LIMIT_ERROR’;
             break;
         case PREG_BAD_UTF8_ERROR:
             $err_msg = ‘PREG_BAD_UTF8_ERROR’;
             break;
         case PREG_BAD_UTF8_OFFSET_ERROR:
             $err_msg = ‘PREG_BAD_UTF8_OFFSET_ERROR’;
             break;
         default:
             return ‘未知错误!’;
     }
     return $err_msg.’: ‘.$error_code;
 }

查阅具体的不当可以应用下面包车型地铁代码:

<?php
ini_set(“pcre.recursion_limit”, “524”); // PHP default is 100,000.
?>

可以如此调用:

 代码如下

翻看具体的一无所长能够运用上面的代码:

复制代码 代码如下:

$resultsArray = preg_match_美高梅开户网址,all(“/table.*?<a>/isU”, $html,
$contents);
if ($resultsArray === 0){
echo get_pcre_err();
}
function get_pcre_err(){
        $pcre_err = preg_last_error();  // PHP 5.2 and above.
        if ($pcre_err === PREG_NO_ERROR) {
            $msg = ‘Successful non-match.’;
        } else {
            // preg_match error!
            switch ($pcre_err) {
                case PREG_INTERNAL_ERROR:
                    $msg = ‘PREG_INTERNAL_ERROR’;
                    break;
                case PREG_BACKTRACK_LIMIT_ERROR:
                    $msg = ‘PREG_BACKTRACK_LIMIT_ERROR’;
                    break;
                case PREG_RECURSION_LIMIT_ERROR:
                    $msg = ‘PREG_RECURSION_LIMIT_ERROR’;
                    break;
                case PREG_BAD_UTF8_ERROR:
                    $msg = ‘PREG_BAD_UTF8_ERROR’;
                    break;
                case PREG_BAD_UTF8_OFFSET_ERROR:
                    $msg = ‘PREG_BAD_UTF8_OFFSET_ERROR’;
                    break;
                default:
                    $msg = ‘Unrecognized PREG error’;
                    break;
            }
        }
    return($msg);
}

$resultsArray = preg_match_all(“/table.*?<a>/isU”, $html,
$contents);
if ($resultsArray === 0){
echo get_pcre_err();
}
function get_pcre_err(){
        $pcre_err = preg_last_error();  // PHP 5.2 and above.
        if ($pcre_err === PREG_NO_ERROR) {
            $msg = ‘Successful non-match.’;
        } else {
            // preg_match error!
            switch ($pcre_err) {
                case PREG_INTERNAL_ERROR:
                    $msg = ‘PREG_INTERNAL_ERROR’;
                    break;
                case PREG_BACKTRACK_LIMIT_ERROR:
                    $msg = ‘PREG_BACKTRACK_LIMIT_ERROR’;
                    break;
                case PREG_RECURSION_LIMIT_ERROR:
                    $msg = ‘PREG_RECURSION_LIMIT_ERROR’;
                    break;
                case PREG_BAD_UTF8_ERROR:
                    $msg = ‘PREG_BAD_UTF8_ERROR’;
                    break;
                case PREG_BAD_UTF8_OFFSET_ERROR:
                    $msg = ‘PREG_BAD_UTF8_OFFSET_ERROR’;
                    break;
                default:
                    $msg = ‘Unrecognized PREG error’;
                    break;
            }
        }
    return($msg);
}

$url = ”;
 $html = get_html($url);
 $matches =
get_matches(‘!<a[^<]+</a>!’,$html,’未有找到链接’,true);
 if($matches){
     var_dump($matches);
 }

    对王丽萍则的梳洗符 isU 表明:
i: 表示in-casesensitive,即大小写不灵动
s: PCRE_多塔LL,表示点号能够相配换行符。
U:
表示PCRE_UNGREEDY,表示非贪婪,相当于perl/python语言的.*?,在十分进度中,对于.*正则,一有合作立刻实施,并不是等.*寻觅了颇具字符再一一再次回到
   
在使用正则表明式时,大家相应尽量幸免递归调用,递归轻巧变成客栈溢出。举个例子:
/<table((?!<table).)*?</a>/isU 就能够爆发错误,而使用
/<table.*?</a>/i 就正常。

对刘阳则的梳洗符 isU 表达:

只怕那样调用:

 那么怎样充实win平台下 ThreadStackSize 的深浅呢? 在apache的安顿文件
httpd.conf 里启用 “Include
conf/extra/httpd-mpm.conf”(删除后面包车型地铁讲授#),然后在 httpd-mpm.conf
文件里的 mpm_winnt_module 配置模块里安装 “ThreadStackSize
8伍仟00”就能够(大约8M)。

i: 表示in-casesensitive,即大小写不灵敏
s: PCRE_多塔LL,表示点号能够匹配换行符。
U:
表示PCRE_UNGREEDY,表示非贪婪,约等于perl/python语言的.*?,在特别进度中,对于.*正则,一有拾分霎时实践,并非等.*寻觅了独具字符再一一再次来到

复制代码 代码如下:

 代码如下

在使用正则表明式时,大家应有尽量防止递归调用,递归轻松变成商旅溢出。比方:

$urls = array(”);
 $htmls = get_htmls($urls);
 foreach($htmls as $html){
     $matches =
get_matches(‘!<a[^<]+</a>!’,$html,’未有找到链接’,true);
     if($matches){
         var_dump($matches);
     }
 }

<IfModule mpm_winnt_module>
    ThreadStackSize 8400000
    ThreadsPerChild      200
    MaxRequestsPerChild    10000
    Win32DisableAcceptEx
</IfModule>

/<table((?!<table).)*?</a>/isU 就能够发生错误,而利用
/<table.*?</a>/i 就正常。

就足以获得所需的音讯,无论单页面搜集大概多页面收集,最后PHP依旧不得不管理多个页面,由于接纳get_matches了,能够对回到的值进行推断真伪,获得正确的数量,由于采纳正则的时候际遇了超过正则回溯的标题,增添get_preg_err_msg来唤起正则音信。

那边必要专注的是,31个人的Apache程序只好最多选用差十分少2GB内部存款和储蓄器空间!
因而,ThreadStackSize 和ThreadsPerChild 的值相乘后(8M *
200)不应有抢先2G,不然不能够运维apache,出现的不当日志如下:
[Thu Apr 11 20:02:45 2013] [crit] (OS
8)存款和储蓄空间欠缺,不能管理此命令。  : Child 4832: _beginthreadex failed.
Unable to create all worker threads. Created 212 of the 220 threads
requested with the
ThreadsPerChild configuration directive.
   
通过地方的提示,飘易能够告诉大家的是在自家的那台服务器上,当线程客栈大小设为8M时,作者得以安装的线程数最多是2拾一个。

那么哪些充实win平台下 ThreadStackSize 的大大小小呢? 在apache的安顿文件
httpd.conf 里启用 “Include
conf/extra/httpd-mpm.conf”(删除前边的评释#),然后在 httpd-mpm.conf
文件里的 mpm_winnt_module 配置模块里安装 “ThreadStackSize
8陆仟00”就可以(大致8M)。

出于收罗数据的时候,平日是搜聚列表页,根据列表页获得的情节页链接再收罗内容页,大概更多的层系,那么循环嵌套会相当多,对于代码的主宰会倍感不可能。那我们是否能够把访谈列表页的代码和收集内容页的代码,只怕越多的层系的募集代码分离开,乃至循环都简化呢?

<IfModule mpm_winnt_module>
    ThreadStackSize 8400000
    ThreadsPerChild      200
    MaxRequestsPerChild    10000
    Win32DisableAcceptEx
</IfModule>

你可能感兴趣的稿子:

  • php使用curl抓取qq空间的访客新闻示例
  • php
    file_get_contents抓取Gzip网页乱码的三种减轻措施
  • 行使PHP
    curl模拟浏览器抓取网址新闻
  • 二个PHP的长途图片抓取函数共享
  • php抓取页面包车型大巴三种艺术详解
  • PHP CU翼虎L模拟登入天涯论坛和讯抓取页面内容
    基于EaglePHP框架开辟
  • php下通过curl抓取yahoo boss
    寻找结果的完成代码
  • php curl
    登陆163信箱并抓取邮箱基友列表的代码(经测量试验)
  • php使用curl和正则表明式抓取网页数据示例

那边须要注意的是,叁十二位的Apache程序只可以最多采纳大概2GB内存空间!
由此,ThreadStackSize 和ThreadsPerChild 的值相乘后(8M *
200)不应有超越2G,不然不能起动apache,出现的荒唐日志如下:

[Thu Apr 11 20:02:45 2013] [crit] (OS
8)存款和储蓄空间不足,无法管理此命令。  : Child 4832: _beginthreadex failed.
Unable to create all worker threads. Created 212 of the 220 threads
requested with the
ThreadsPerChild configuration directive.

经过地点的晋升,飘易能够告知大家的是在自家的那台服务器上,当线程商旅大小设为8M时,笔者能够安装的线程数最多是2拾一个。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图