据我所知,这不能通过简单的字符串拆分来实现,因为正如您已经发现的那样 - 破坏 html 的可能性很高。
但是你可以:
1)按字符加载HTML字符串字符并跟踪标签的结构
2) 将 HTML 作为对象加载并计算元素的文本节点
2.1)对于加载,您可以使用
- DOM - http://php.net/manual/en/book.dom.php
- SimpleXML - http://php.net/manual/en/book.simplexml.php
- 还有更多处理 HTML 加载的 PHP 库
2.2) 遍历加载的元素并计算它们的文本节点
- 使用通过代码的算法
- 计数文本节点,直到计数达到所需长度
- 之后,清除将显示下一个的所有文本节点
至于可见字符 - PHP 本身不知道你的元素有什么 CSS - 但例如,如果你将它作为一个对象加载,你可以getAttribute('style')
在其中搜索你的“隐藏 css”:)
注意:情况 1) 和 2) 都需要一点性能,所以如果您将其应用于一些流量较高的站点,您应该考虑对这些结果进行某种缓存。
编辑:广告1)
我创建了有关如何跟踪打开标签的示例函数
注意:这个函数假定 XHTML !(期望自闭标签是<img>
自闭标签,<img />
请注意,我只是快速完成此操作,因此它可能不是最好也不是最有效的方法:)
您可以在http://ideone.com/erSDlg看到它的工作原理
//PHP
function closeTags( &$html, $length = 20 ){
$htmlLength = strlen($html);
$unclosed = array();
$counter = 0;
$i=0;
while( ($i<$htmlLength) && ($counter<$length) ){
if( $html[$i]=="<" ){
$currentTag = "";
$i++;
if( ($i<$htmlLength) && ($html[$i]!="/") ){
while( ($i<$htmlLength) && ($html[$i]!=">") && ($html[$i]!="/") ){
$currentTag .= $html[$i];
$i++;
}
if( $html[$i] == "/" ){
do{ $i++; } while( ($i<$htmlLength) && ($html[$i]!=">") );
} else {
$currentTag = explode(" ", $currentTag);
$unclosed[] = $currentTag[0];
}
} elseif( $html[$i]=="/" ){
array_pop($unclosed);
do{ $i++; } while( ($i<$htmlLength) && ($html[$i]!=">") );
}
} else{
$counter++;
}
$i++;
}
$result = substr($html, 0, $i-1);
$unclosed = array_reverse( $unclosed );
foreach( $unclosed as $tag ) $result .= '</'.$tag.'>';
print_r($result);
}
$html = "<div>123890<span>1234<img src='i.png' /></span>567890<div><div style='test' class='nice'>asfaasf";
closeTags( $html, 20 );