preg_match模式用于查找字符串和标记之间的内容

时间:2010-09-03 19:10:18

标签: php regex

我正在开发一个读取电子邮件内容的PHP脚本,并提取某些信息以存储在数据库中。

使用imap_fetchbody($ imap_stream,$ msg_number,1),我能够得到电子邮件的正文。在某些情况下(特别是从手机发送的短信电子邮件),电子邮件正文如下:

===------=_Part_110734_170079945.1283532109852
Content-Type: text/html;charset=UTF-8;
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

<html> 
    <head> 
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
        <title>Multimedia Message</title> 
    </head> 
    <body leftmargin="0" topmargin="0"> 


                <tr height="15" style="border-top: 1px solid #0F7BBC;"> 
                    <td> 
                        SMS to email test
                    </td> 
                </tr> 


     </body> 
</html> 


------=_Part_110734_170079945.1283532109852--===

我想提取电子邮件的“内容”。所以,我的计划是:

检查主体是否包含“html”标签。如果没有,我可以正常阅读(它不是HTML电子邮件)。

如果是,请在“html”标签之间提取内容。然后,删除所有其他HTML标记,“内容”就是剩下的内容。

但是,当谈到正则表达式时,我很无能为力。

我试过了:

$pattern = '/<html[^>]*>(.*?)<\/html>/i';
preg_match($pattern, $body, $matches);
// my 'content' should be in $matches[1]

但这不起作用(可能是因为$ body包含换行符和其他空格)。所以我试过这个:

$pattern = '/<html[^>]*>([.\s]*?)<\/html>/i';
preg_match($pattern, $body, $matches);

但这也不起作用。

那么,我可以使用什么$ pattern来提取“html”标签之间的所有文本?

更新:我偶然发现了一个解决方法 - 首先删除所有空格:

$body = preg_replace('/\s\s+/', ' ', $body);
$pattern = '/<body[^>]*>(.*?)<\/body>/';

我怀疑这不是最快或最有效的方法,但它有效,并且是迄今为止我所做的最好的方法。如果有的话,我仍然会欣赏更好的解决方案。

更新2:感谢Gumbo的建议,我尝试了一下,仔细研究电子邮件的结构,找到我想要的部分,而不是尝试使用正则表达式HTML。我终于找到了这个:http://docstore.mik.ua/orelly/webprog/pcook/ch17_04.htm,它解释了如何完全按照我的需要做。

4 个答案:

答案 0 :(得分:3)

$pattern = '/<html[^>]*>([^\00]*?)<\/html>/i';

只有在内容中有0x00个字节时才会中断,这不应该是。

答案 1 :(得分:2)

您可以使用如下的html解析器: http://php-html.sourceforge.net/

或者您可以使用strip_tags php.net/strip_tags

答案 2 :(得分:2)

[.\s]表示文字.或空格字符。您需要的是(.|\s)[\s\S],或者只需将s modifier设置为.也匹配换行符。

但除此之外,you should not use regular expressions to match HTML。 HTML的一部分不是常规的,因此您不能使用正则表达式来描述它。

但除此之外,当你有明确的分隔符时,你不应该试着猜测多部分内容的范围。但这些不是<html>…</html>。因为他们失踪怎么办?那你的尝试就会失败。使用消息本身定义的分隔符:boundary值。因此,使用边界来获取部分并在第一个CRLF + CRLF序列中将它们分开,以将标题与正文分开。

但除此之外,为什么不使用IMAP functions来获取身体?我不熟悉PHP的IMAP API,但可能有一个功能完全符合您的要求。

答案 3 :(得分:1)

您只需要添加s modifier以允许.匹配换行符:

$pattern = '/<html[^>]*>(.*?)<\/html>/si';
preg_match($pattern, $body, $matches);