如何优化 jQuery tag:contains() 选择器?

Posted

技术标签:

【中文标题】如何优化 jQuery tag:contains() 选择器?【英文标题】:How to optimize jQuery tag:contains() selector? 【发布时间】:2020-06-21 17:36:15 【问题描述】:

我正在尝试从包含给定单词集的网页中提取所有元素。例如。鉴于我有一个随机单词数组

words = ["sky", "element", "dry", "smooth", "java", "running", "illness", "lake", "soothing", "cardio", "gymnastic"]

并假设它们都存在于 DOM 中。这意味着我需要检查每个可能的标签是否存在。以下是我正在搜索的标签。

// 14 essential tags 
items = ["p", "li", "h2", "h3", "h4", "h5", "h6", "b", "small", "td", "span", "strong", "blockquote", "div"] 

我还需要确保单词的空白边界。因此,对于每个单词,我需要在 jquery contains() 选择器中定义 3 个检查,如下所示。

tagName:contains('sky '), tagName:contains(' sky'), tagName:contains(' sky ')`

因此,上述场景的最终查询总共使words.length * items.length * 3 14*11*3 = 462 个选择器。这本身就是一个大型查询,随着单词数组开始增长,我的查询如下所示。

$(p:icontains('ACCESSIBLE '), p:icontains(' ACCESSIBLE'), p:icontains(' ACCESSIBLE '), li:icontains('ACCESSIBLE '), li:icontains(' ACCESSIBLE'), li:icontains(' ACCESSIBLE '), h3:icontains('ACCESSIBLE '), h3:icontains(' ACCESSIBLE'), h3:icontains(' ACCESSIBLE '), h4:icontains('ACCESSIBLE '), h4:icontains(' ACCESSIBLE'), h4:icontains(' ACCESSIBLE '), h5:icontains('ACCESSIBLE '), h5:icontains(' ACCESSIBLE'), h5:icontains(' ACCESSIBLE '), b:icontains('ACCESSIBLE '), b:icontains(' ACCESSIBLE'), b:icontains(' ACCESSIBLE '), td:icontains('ACCESSIBLE '), td:icontains(' ACCESSIBLE'), td:icontains(' ACCESSIBLE '), span:icontains('ACCESSIBLE '), span:icontains(' ACCESSIBLE'), span:icontains(' ACCESSIBLE '), strong:icontains('ACCESSIBLE '), strong:icontains(' ACCESSIBLE'), strong:icontains(' ACCESSIBLE '), div:icontains('ACCESSIBLE '), div:icontains(' ACCESSIBLE'), div:icontains(' ACCESSIBLE ')p:icontains('ADDRESS '), p:icontains(' ADDRESS'), p:icontains(' ADDRESS '), li:icontains('ADDRESS '), li:icontains(' ADDRESS'), li:icontains(' ADDRESS '), h3:icontains('ADDRESS '), h3:icontains(' ADDRESS'), h3:icontains(' ADDRESS '), h4:icontains('ADDRESS '), h4:icontains(' ADDRESS'), h4:icontains(' ADDRESS '), h5:icontains('ADDRESS '), h5:icontains(' ADDRESS'), h5:icontains(' ADDRESS '), b:icontains('ADDRESS '), b:icontains(' ADDRESS'), b:icontains(' ADDRESS '), td:icontains('ADDRESS '), td:icontains(' ADDRESS'), td:icontains(' ADDRESS '), span:icontains('ADDRESS '), span:icontains(' ADDRESS'), span:icontains(' ADDRESS '), strong:icontains('ADDRESS '), strong:icontains(' ADDRESS'), strong:icontains(' ADDRESS '), div:icontains('ADDRESS '), div:icontains(' ADDRESS'), div:icontains(' ADDRESS ')p:icontains('ANTIEMETICS '), p:icontains(' ANTIEMETICS'), p:icontains(' ANTIEMETICS '), li:icontains('ANTIEMETICS '), li:icontains(' ANTIEMETICS'), li:icontains(' ANTIEMETICS '), h3:icontains('ANTIEMETICS '), h3:icontains(' ANTIEMETICS'), h3:icontains(' ANTIEMETICS '), h4:icontains('ANTIEMETICS '), h4:icontains(' ANTIEMETICS'), h4:icontains(' ANTIEMETICS '), h5:icontains('ANTIEMETICS '), h5:icontains(' ANTIEMETICS'), h5:icontains(' ANTIEMETICS '), b:icontains('ANTIEMETICS '), b:icontains(' ANTIEMETICS'), b:icontains(' ANTIEMETICS '), td:icontains('ANTIEMETICS '), td:icontains(' ANTIEMETICS'), td:icontains(' ANTIEMETICS '), span:icontains('ANTIEMETICS '), span:icontains(' ANTIEMETICS'), span:icontains(' ANTIEMETICS '), strong:icontains('ANTIEMETICS '), strong:icontains(' ANTIEMETICS'), strong:icontains(' ANTIEMETICS '), div:icontains('ANTIEMETICS '), div:icontains(' ANTIEMETICS'), div:icontains(' ANTIEMETICS ')p:icontains('BRAND '), p:icontains(' BRAND'), p:icontains(' BRAND '), li:icontains('BRAND '), li:icontains(' BRAND'), li:icontains(' BRAND '), h3:icontains('BRAND '), h3:icontains(' BRAND'), h3:icontains(' BRAND '), h4:icontains('BRAND '), h4:icontains(' BRAND'), h4:icontains(' BRAND '), h5:icontains('BRAND '), h5:icontains(' BRAND'), h5:icontains(' BRAND '), b:icontains('BRAND '), b:icontains(' BRAND'), b:icontains(' BRAND '), td:icontains('BRAND '), td:icontains(' BRAND'), td:icontains(' BRAND '), span:icontains('BRAND '), span:icontains(' BRAND'), span:icontains(' BRAND '), strong:icontains('BRAND '), strong:icontains(' BRAND'), strong:icontains(' BRAND '), div:icontains('BRAND '), div:icontains(' BRAND'), div:icontains(' BRAND ')p:icontains('CAPABLE '), p:icontains(' CAPABLE'), p:icontains(' CAPABLE '), li:icontains('CAPABLE '), li:icontains(' CAPABLE'), li:icontains(' CAPABLE '), h3:icontains('CAPABLE '), h3:icontains(' CAPABLE'), h3:icontains(' CAPABLE '), h4:icontains('CAPABLE '), h4:icontains(' CAPABLE'), h4:icontains(' CAPABLE '), h5:icontains('CAPABLE '), h5:icontains(' CAPABLE'), h5:icontains(' CAPABLE '), b:icontains('CAPABLE '), b:icontains(' CAPABLE'), b:icontains(' CAPABLE '), td:icontains('CAPABLE '), td:icontains(' CAPABLE'), td:icontains(' CAPABLE '), span:icontains('CAPABLE '), span:icontains(' CAPABLE'), span:icontains(' CAPABLE '), strong:icontains('CAPABLE '), strong:icontains(' CAPABLE'), strong:icontains(' CAPABLE '), div:icontains('CAPABLE '), div:icontains(' CAPABLE'), div:icontains(' CAPABLE ')p:icontains('COMMAND '), p:icontains(' COMMAND'), p:icontains(' COMMAND '), li:icontains('COMMAND '), li:icontains(' COMMAND'), li:icontains(' COMMAND '), h3:icontains('COMMAND '), h3:icontains(' COMMAND'), h3:icontains(' COMMAND '), h4:icontains('COMMAND '), h4:icontains(' COMMAND'), h4:icontains(' COMMAND '), h5:icontains('COMMAND '), h5:icontains(' COMMAND'), h5:icontains(' COMMAND '), b:icontains('COMMAND '), b:icontains(' COMMAND'), b:icontains(' COMMAND '), td:icontains('COMMAND '), td:icontains(' COMMAND'), td:icontains(' COMMAND '), span:icontains('COMMAND '), span:icontains(' COMMAND'), span:icontains(' COMMAND '), strong:icontains('COMMAND '), strong:icontains(' COMMAND'), strong:icontains(' COMMAND '), div:icontains('COMMAND '), div:icontains(' COMMAND'), div:icontains(' COMMAND ')p:icontains('CONFLUENCE ') ....

一个包含 87Kb 选择器的查询,在一个页面上执行大约需要 30-40 秒。有没有办法优化它。在进行查询之前,我已经消除了页面中不存在的标签。

编辑:我不能用正则表达式进行整页文本解析的原因是我需要在解析后用一些 html 替换那些匹配的单词,这类似于通过在页面上注入一些 HTML 来突出显示这些单词。如果我执行正则表达式,我将失去对 HTML 元素及其位置的控制。正则表达式替换也不能保证文本节点。它还替换标题属性和其他属性(如果存在)中写入的单词。

【问题讨论】:

我相信这个问题更适合codereview.stackexchange.com 最有可能更好的问题是为什么你需要这样的东西。对我来说,这似乎是早期阶段的设计错误。 @Sirko 帮我解决这个问题。我没有得到更好的主意。我需要在解析后用一些 HTML 替换那些匹配的单词,这类似于通过在它们的位置注入一些 HTML 来突出显示页面上的这些单词。如果你知道的话,给我建议一个更好的解决方法.. @Sirko 请检查编辑了解更多详情 【参考方案1】:

相反,为什么不直接使用整个页面 html,并针对单词数组使用正则表达式?

测试 HTML:

<div id='container'>
<p>Chess</p>
<span>Chess and Checkers</span>
<h1> Chess and Checkers</h1>
</div>

javascript

$("document").ready(function() 
    var html = $("#container").html();
    var words = ["Chess", "checkers"];

    $.each(words, function() 
      var phrase = this;    
      html = html.replace(new RegExp(phrase, "gim"), "foo");
    );
    $("#container").html(html);
);

输出:

富和富

foo 和 foo

【讨论】:

这在我的情况下不起作用。由于我需要在解析后用一些 HTML 替换那些匹配的单词,这类似于通过在它们的位置注入一些 HTML 来突出显示页面上的这些单词。通过执行正则表达式,我无法将元素放在它们的确切位置。正则表达式有很多问题,因为它还替换了我不想要的标题属性中写的单词。 我不需要替换属性内写的单词的原因是,我需要用 HTML 替换。将 HTML 元素代替 title 属性中的单词会破坏整个元素。例如。 &lt;div title="this is WORD"&gt; This is word&lt;/div&gt; 变成 &lt;div title="this is &lt;span&gt;replacement&lt;/span&gt;"&gt;This is &lt;span&gt; replacement&lt;/span&gt; &lt;/div&gt; 没有意义。

以上是关于如何优化 jQuery tag:contains() 选择器?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 jQuery 日期选择器优化引导输入标签

如何使用 rails 和 jquery 优化 ajax 搜索

ES中的内置对象--jquery如何优化代码,少用$进行查找,减少查找次数的方法

js、jquery 如何隐藏浏览器地址栏(网页优化,手机可以,ipad mini不可以,求大神指教)

jQuery性能优化

前端性能优化:jquery性能优化