1

我有一个博客条目,有时会包含很多文本/图像,我想从该博客中截取一段。更具体地说,我想匹配所有内容,直到第二个图像标签之后

下面是一些示例文本。

我尝试过像这样的负面预测

/[\w\r\n;:',."&\s*<>=-_]+(?!<img)/i

但我想不出一种方法将前瞻应用于“+”修饰符。谁有任何线索,我将不胜感激。

*override*
I've been stuck in a room lately, and though it's hard to stay creative all the time,         sometimes you need that extra kick. Well for some us we have to throw pictures of true creative genius at ourselves to stimulate us.

So sit back and soak in some inspiration I've come across the past year.

&nbsp;

&nbsp;

&nbsp;

<figure>
    <a href="">
    <img class="aligncenter" src="http://funnypagenet.com/wp-content/uploads/2011/07/Talesandminimalism_12_www.funnypagenet.com_.jpg" alt="" width="574" height="838" />
    </a>
    <figcaption></figcaption>
</figure>

&nbsp;

&nbsp;

&nbsp;

&nbsp;
<h4 style="text-align: center;">
    <a href="http://funnypagenet.com/tales-and-minimalism/">source</a>
</h4>
Couldn't find who did this, but couldn't explain the movie any simpler

&nbsp;

&nbsp;

&nbsp;

&nbsp;

&nbsp;

&nbsp;

&nbsp;

&nbsp;

&nbsp;

<figure>
    <img class="aligncenter" src="http://brickhut.files.wordpress.com/2011/05/theempirestrikesback1.jpg" alt="" width="540" height="800" />
    <figcaption></figcaption>
</figure>

&nbsp;

&nbsp;

&nbsp;
4

3 回答 3

3

显然,直接的字符串切割不适合您的第二张图片:

...
<figure>
    <img class="aligncenter" src="http://brickhut.files.wordpress.com/2011/05/theempirestrikesback1.jpg" alt="" width="540" height="800" />
    <figcaption></figcaption>
</figure>

在图像之后切割会留下未闭合的元素:

...
<figure>
    <img class="aligncenter" src="http://brickhut.files.wordpress.com/2011/05/theempirestrikesback1.jpg" alt="" width="540" height="800" />

这可能会破坏浏览器内页面的呈现。preg_match如果您在此处使用正则表达式或某些字符串函数,它不会发挥作用。

您需要的是一个DOMDocument能够处理 HTML 的 DOM 解析器:

给定一些与您的问题类似的示例 HTML 代码:

$html = <<<HTML
dolor sit amet, consectetuer adipiscing elit. <img src="http://example.com/img-a.jpg"> Aenean commodo 
ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, 
nascetur ridiculus mus.

<figure>
    <img src="http://example.com/img-b.jpg">
    <figcaption>Figure Caption</figcaption>
</figure>

Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut.
HTML;

您现在可以使用DOMDocument该类在标签内加载 HTML 块<body>- 因为它是您用于操作的整个 html 正文。当您使用非标准 HTML 标签 ( <figure>& <figcaption>) 时,您应该在加载字符串时禁用警告libxml_use_internal_errors

$doc = new DOMDocument();
libxml_use_internal_errors(1);
$doc->loadHTML(sprintf('<body>%s</body>', $html));

这是 DOM 解析器的基本设置,您的 HTML 现在位于解析器中。现在是有趣的部分。您要创建摘录,直到文档的第二个图像。这意味着,应该删除该元素之后的所有内容。听起来就像剪切一个我们知道不起作用的字符串一样简单,但这次 DOM 解析器为我们完成了所有工作。

您只需要获取所有节点(<tag>, Text, <!-- comments -->, ...)并删除它们。<img>中第二个标签之后的所有节点(以下文档顺序)。这样的事情可以用XPath来表达:

/descendant::img[position()=2]/following::node()

PHP 的 DOM 解析器带有 XPath,所以让我们这样做:

$xp = new DOMXPath($doc);
$delete = $xp->query('/descendant::img[position()=2]/following::node()');
foreach ($delete as $node)
{
    $node->parentNode->removeChild($node);
}

剩下的唯一事情是获取(示例输出)剩下的摘录。正如我们所知,这一切都在<body>标签内:

foreach ($doc->getElementsByTagName('body')->item(0)->childNodes as $child)
{
    echo $doc->saveHTML($child);
}

这将为您提供以下信息:

dolor sit amet, consectetuer adipiscing elit. <img src="http://example.com/img-a.jpg"> Aenean commodo 
ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, 
nascetur ridiculus mus.

<figure><img src="http://example.com/img-b.jpg"></figure>

如本例所示,<figure>标签现在已正确关闭。

类似的场景是在特定文本长度或字数之后创建摘录:Wordwrap / Cut Text in HTML string

于 2012-02-24T20:21:38.573 回答
1

好吧,它不是正则表达式,但它应该可以工作:

$post = str_ireplace('<img', '!!!<img', $post);
list($p1, $p2) = explode('!!!', $post);
$keep = $p1 . $p2;

在图像标签 ( !!!) 之前放置一个分割标记,在它们上分割并保留前两个块,这应该是直到第二个图像标签的所有内容。不需要正则表达式。

编辑:因为这是摘录,您可能希望strip_tags()在结果上运行。如果您不这样做,您可能会有一些打开的 HTML 标记永远不会关闭。

于 2012-02-24T19:40:23.537 回答
0

如果您真的想要基于正则表达式的解决方案,那么这里是:

// assuming $str is your full HTML text
if ( preg_match_all('~^(.*?<img\s.*?<img\s[^>]*>)~si', $str, $m) )
    print_r ( $m[1] );
于 2012-02-24T19:41:22.210 回答