【问题标题】:Split a long text with html into a teaser and a main part将带有 html 的长文本拆分为预告片和主要部分
【发布时间】:2016-05-06 23:45:49
【问题描述】:

长文本包含一些 html 标签(br、img 等)

此文本需要一个最多 400 个字符的预告片,并注意单词和 html 标记但 br 标记应替换为空格,以删除预告片中的换行符。看起来更好!

预告片后面的文本必须是减去预告片的文本,但要包含所有 html 标记和图像 br

Example text:

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy   eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. <img alt="image" src="/image.jpg"> At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. 
<br /><br />
Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. <img alt="image" src="/image.jpg"> Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
<br /><br />
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, <img alt="image" src="/image.jpg"> vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet.

我尝试了什么:

$content = $junk_of_lorem;

function teaser($string){
 $string = substr($string,0,500);
 $string = substr($string,0,strrpos($string," "))

$replacements = array(
    '|<br /><br />|' => ' '
);

$patterns = array_keys($replacements);
$replacements = array_values($replacements);

$string = preg_replace($patterns, $replacements, $string); 

 return $string;
}

$teaser = teaser($content);

现在我尝试从文本中删除 $teaser 以获取没有预告片的文本

$mainpart = str_replace(teaser($content), "", $content);

问题:

使用这个虚拟解决方案时,我遇到了问题,因为预告片仅带有 br,但主要部分具有所有 html 标签。当 char 490 周围有图像时,主要部分包含 img 标签的一半。

strip_tags with allow for br to the $teaser 工作,但我无法从 $mainpart 中删除完全匹配。

我很确定有更好的解决方案。对不起我的英语错误,请不要投票给我。我尽力解释了。

非常感谢您抽出宝贵时间帮助我。

【问题讨论】:

标签: php preg-replace substr strpos


【解决方案1】:

好的,所以我对此进行了修改,并认为我可能有一些对你有用的东西。

给你这样的字符串:

$string = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy   eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. <img alt="image" src="/image.jpg"> At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. 
<br /><br />
Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. <img alt="image" src="/image.jpg"> Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
<br /><br />
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, <img alt="image" src="/image.jpg"> vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet.';

我们可以编写一个preg_match 语句,使用PREG_OFFSET_CAPTURE 标志来记录匹配的位置,如下所示:

preg_match('~([A-z0-9 ,.]|<.*?>){1,158}(?=\s+)~', $string, $matches, PREG_OFFSET_CAPTURE);

在我有{1,158} 的地方,您可以将158 更改为您的预告片的长度。字符数不会正好是 400 或正好 500,但应该在这个数字附近。例如,如果您有 HTML 标记,它们将占用更多空间并且只会算作我们的字符之一。 (因为我告诉它给我一个字符或一个 HTML 标记 - 158 次。)

$matches 将包含这样的数组:

Array
(
    [0] => Array
        (
            [0] => Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy   eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua
            [1] => 0
        )

    [1] => Array
        (
            [0] => a
            [1] => 155
        )

)

所以我们需要$matches[0][0] 用于文本,$matches[1][1] 用于我们离开的位置。

现在,让我们利用我们拥有的信息并定义一些我们以后可以使用的变量:

$teaser = $matches[0][0];
$capture_position = $matches[1][1] + 1;
$body = substr($string, $capture_position); 

请注意,我们将$matches[1][1] 加一,因为我们希望从匹配后的字符开始...而不是匹配的最后一个字符。

接下来,我们使用substr 定义了$body,以仅获取从我们的$capture_position 转发开始的文本。

最后,我们可以打印出我们的$teaser(带有strip_tags)和$body

print '<b>'.strip_tags($teaser).'</b>';
print '<br><br>'.$body;

这是一个工作演示:

http://ideone.com/yqiTlq

下面是供您使用的正则表达式,看看更改 158 如何影响您捕获的总字符串:

https://regex101.com/r/iZ9lX1/1

说明 ([A-z0-9 ,.]|&lt;.*?&gt;){1,158}(?=\s+)

  • ([A-z0-9 ,.]|&lt;.*?&gt;) 这是一个捕获组( ... ),它将包含我们的预告片,由两个项目组成。第一个是字符类[ ... ],由大小写字母A-z、数字0-9、空格、逗号,和句点.组成。管道| 是一个“或”符号。第二项是寻找小于号&lt;,后跟任意字符.,任意次数*,直到匹配到我们匹配的下一部分?。我们匹配的下一部分将是大于号&gt;。这应该匹配任何 HTML 标记。
  • {1,158} 这是由1 的起始编号定义并经过158 的范围。这意味着我们在它之前匹配的任何内容(一个字符或一个 html 标签)都应该至少找到一次,但最多可以找到 158 次。
  • (?=\s+) 这是一个前瞻 (?= ... ),表示在匹配之后至少应该找到一个空格字符 \s 一次 +

【讨论】:

  • 非常感谢您花时间和精力帮助我解决这个问题。我试过了,它可以工作,只要断点上没有 html 标记。当在断点上添加
  • 嗯,好吧,我在复制您的问题时遇到了麻烦,但是,您可以在其中的“OR”部分添加一些内容。就像您可以添加|&lt;a.*?&gt;.*?&lt;/a&gt; 作为第三个选项。这将通过结束链接标签向上查找开始链接标签。这是整个事情([A-z0-9 ,.]|&lt;.*?&gt;|&lt;a.*?&gt;.*?&lt;/a&gt;){1,222}(?=\s+)
  • 我没有得到这个工作。以这个文本为例: $string = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua。 @Thomas。 ';将数字设置为 200 并查看 html。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-07
  • 2012-11-10
  • 2016-12-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-24
相关资源
最近更新 更多