HTML字符串中所有字符的字符数,但仅测量20个可见字

时间:2009-09-04 01:08:05

标签: php html regex string word-count

我正在使用WordPress网站,其中一个网页列出了有关公司客户的摘录。

假设我有一个网页,其中可见文字如下所示:

"SuperAmazing.com, a subsidiary of Amazing, the leading provider of
integrated messaging and collaboration services, today announced the
availability of an enhanced version of its Enterprise Messaging
Service (CMS) 2.0, a lower cost webmail alternative to other business
email solutions such as Microsoft Exchange, GroupWise and LotusNotes
offerings."

但是,假设此文本中可能有HTML链接或图像,因此原始HTML可能如下所示:

<img src="/images/corporate/logos/super_amazing.jpg" alt="Company
logo for SuperAmazing.com" /> SuperAmazing.com, a subsidiary of
<a href="http://www.amazing.com/">Amazing</a>, the leading
provider of integrated messaging and collaboration services, today
announced the availability of an enhanced version of its Enterprise
Messaging Service (CMS) 2.0, a lower cost webmail alternative to other
business email solutions such as Microsoft Exchange, GroupWise and
LotusNotes offerings."

这是我需要做的:找出前20个可见单词中是否有链接。

这是前20个可见单词:

"SuperAmazing.com, a subsidiary of Amazing, the leading provider of
integrated messaging and collaboration services, today announced the
availability of an"

我需要将字符数(包括HTML)输出到20个可见单词,在这种情况下它将是“an”,但当然它对于页面上的每个摘录都会有所不同。

(如果这样可以让事情变得简单,我愿意将“SuperAmazing.com”视为2个单词。)

我尝试了一些用于计算单词的正则表达式,但它们都计算HTML,而不是可见单词。

那么,对于前20个可见单词,查找完整字符数(包括HTML)的正确正则表达式是什么?

4 个答案:

答案 0 :(得分:2)

我不确定使用PHP正则表达式计算单词。

假设你可以隔离变量中的可见单词,我最初的方法是在空格处爆炸/拆分它(或任何给出你认为是单词的东西)并将结果放入数组中。

拆分后,将数组限制为20个元素。

然后将正则表达式应用于每个数组元素,并确定是否匹配链接。

要获取字符数,请加入/内嵌20个单词的数组(不含空格)并找到字符串的长度。

答案 1 :(得分:2)

函数“getTextFromNode”和“getTextFromDocument”为您提供HTML的纯文本内容。函数“getFirstWords”返回文本中的第一个单词数。

function getTextFromNode($Node, $Text = "") {
    if ($Node->tagName == null)
        return $Text.$Node->textContent;

    $Node = $Node->firstChild;
    if ($Node != null)
        $Text = getTextFromNode($Node, $Text);

    while($Node->nextSibling != null) {
        $Text = getTextFromNode($Node->nextSibling, $Text);
        $Node = $Node->nextSibling;
    }
    return $Text;
}

function getTextFromDocument($DOMDoc) {
    return getTextFromNode($DOMDoc->documentElement);
}

function getFirstWords($Text, $Count = 1) {
    if (!($Count > 0))
        $Count = 1;

    $Text = trim($Text);

    $TextParts = split('[ ]+', $Text, 21);
    if (count($TextParts) == $Count)
        $TextParts[$Count - 1] = "";

    $NewText = join(" ", $TextParts);
    return $NewText;
}

你可以通过以下方式使用它:

$Doc = new DOMDocument();
$Doc->loadHTMLFile("Test.html");

$Text = getTextFromDocument($Doc);
echo "Text from HTML: ".$Text."\n";

$NewText = getFirstWords($Text, 21);
echo "First 20 words from HTML: ".$NewText."\n";

希望这有帮助。

答案 2 :(得分:2)

这是匹配前20个可见单词的相当不错的正则表达式:

'~^(?:\s*+(?:(?:[^<>\s]++|</?\w[^<>]*+>)++)){1,20}~'

这匹配一到二十个以空格分隔的标记,其中标记被定义为一个或多个不用空格分隔的单词或标签(其中“单词”被定义为除空格或尖括号以外的一个或多个字符)。例如,这将是一个标记:

<a href="http://www.amazing.com/">Amazing</a>

...但这是两个令牌:

<a href="http://www.superduper.com/">Super Duper</a>

这会将独立标记(例如示例中的<img>标记或任何被空格包围的标记)视为单独的标记,从而丢弃计数 - 它只匹配单词“ “在你的例子中。它还无法正确处理<br>标记或<p><table>等块级标记,如果它们周围有任何空格。只有你能知道会有多少问题。

编辑:如果您看到很多孤立的<img>标记,您可以预处理文本以删除其后面的空格。这将有效地将其与第一个后续“真实”令牌合并,从而产生更准确的字符数。我知道在这种情况下它只会将计数改为一个或两个字符,但如果第二十个字发生在“supercalifragilisticexpialidocious”中,你可能会注意到它的区别。 :)

答案 3 :(得分:1)

正则表达式和HTML不混合。使用正则表达式计数是不寻常的。正则表达式是您的问题的错误解决方案。使用HTML解析库来提取文本。然后使用某种形式的tokenizer来提取单词。从长远来看,你会为自己省去很多麻烦。

有什么头疼的?假设你设法构建一个可以满足你想要的怪异正则表达式。现在假设两年后有一个你没有考虑的边缘情况,你需要修改那个怪物。您将在那时希望您有一个可以轻松修改的编码解决方案。