2

我正在一个 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

4 回答 4

2

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

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

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

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

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

于 2009-09-04T01:22:45.390 回答
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";

希望这可以帮助。

于 2009-09-04T02:47:55.593 回答
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>示例中的标签,或任何被空格包围的标签)视为单独的标记,这会忽略计数 - 它仅匹配示例中的单词“of”。如果它们周围没有任何空格,它也不会正确处理<br>标签或块级标签,如<p>and 。只有你才能知道这会有多大的问题。<table>

编辑:如果那个孤立<img>的标签是你经常看到的东西,你可以预处理文本以删除它后面的空格。这将有效地将其与第一个后续“真实”标记合并,从而产生更准确的字符计数。我知道在这种情况下它只会将计数更改一两个字符,但如果第 20 个单词恰好是“supercalifragilisticexpialidocious”,您可能会注意到差异。:)

于 2009-09-04T03:05:30.220 回答
1

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

什么头痛?假设您设法构建了一个可怕的正则表达式来满足您的需求。现在假设两年后有一个你没有考虑到的极端情况,你需要修改那个怪物。那时你会希望你有一个可以轻松修改的编码解决方案。

于 2009-09-04T01:44:06.330 回答