代码之家  ›  专栏  ›  技术社区  ›  cerhovice

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

  •  2
  • cerhovice  · 技术社区  · 17 年前

    我正在一个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”,当然对于页面上的每一个摘录都是不同的。

    (我愿意把“superawarding.com”算作两个单词,如果这样做容易的话。)

    我尝试了许多正则表达式来计算单词,但它们都计算HTML,而不是可见的单词。

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

    4 回复  |  直到 11 年前
        1
  •  2
  •   Alan Moore Chris Ballance    17 年前

    下面是一个相当好的正则表达式,用于匹配前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> 和 <table> ,如果他们 不要 周围有空白。只有你知道会有多少问题。

    编辑:如果是孤立的 <IMG & GT; 标记是您经常看到的东西,您可以对文本进行预处理以删除后面的空白。这将有效地将其与第一个后续的“real”标记合并,从而产生更准确的字符计数。我知道在这种情况下,它只会改变一到两个字符的计数,但是如果第二十个单词发生在“超级脆弱性”的experiodiocious上,你可能会注意到这个区别。:)

        2
  •  2
  •   pavium    17 年前

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

    假设您可以隔离一个变量中的可见词,我的初始方法是在空格处(或者您认为是单词的任何给定内容)分解它,并将结果放入一个数组中。

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

    然后对每个数组元素应用正则表达式,并决定是否有匹配的链接。

    要获得字符数,请连接/内爆20个单词的数组(不带空格),并找到字符串的长度。

        3
  •  2
  •   NawaMan    17 年前

    函数“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";
    

    希望这有帮助。

        4
  •  1
  •   jmucchiello    17 年前

    regex和html不能混合。使用regex计数是不常见的。regex是解决问题的错误方法。使用HTML分析库提取文本。然后使用某种形式的标记器来提取单词。从长远来看,你会省去很多头痛。

    什么头痛?假设你设法构建了一个做你想做的事情的可怕的regex。现在假设两年后,有一个你没有解释的边缘案例,你需要修改这个怪物。此时,您希望您有一个可以轻松修改的编码解决方案。