如何从Twitter正确加粗搜索词,JS中的奇怪的正则表达式案例

时间:2015-02-26 18:57:25

标签: javascript jquery regex twitter

我正在使用Twitter API从Twitter检索推文并将其显示在我自己的客户端中。

但是,我在正确突出正确的搜索字词时遇到了一些困难。我希望得到如下效果:

You can see search terms are properly bolded

我在JS中尝试这样做的方法是使用一个名为highlightSearchTerms()的函数,该函数将tweet的文本和一个关键字数组作为参数加粗。它返回固定推文的文本。我通过将关键字包装在具有类.search-term。

的类中来加粗关键字

我遇到很多问题,包括:

  • 运行简单替换不会保留大小写
  • 与href标签中的关键字存在很多冲突
  • 如果我尝试使用替换执行for循环,我不知道如何只修改不在href中的搜索词,并且我还没有用上面的span填充

我希望能够处理的示例推文:

Input:

This is a keyword. This is a <a href="http://search.twitter.com/q=%23keyword">
#keyword</a> with a hashtag. This is a link with kEyWoRd: 
<a href="http://thiskeyword.com">http://thiskeyword.com</a>.

Expected Output:

This is a 
<span class="search-term">keyword</span>
. This is a <a href="http://search.twitter.com/q=%23keyword"> #
<span class="search-term">keyword</span>
</a> with a hashtag. This is a link with 
<span class="search-term">kEyWoRd</span>
:<a href="http://thiskeyword.com">http://this
<span class="search-term>keyword.com</span>
</a>.

我尝试了很多东西,但不幸的是我找不到解决问题的正确方法。任何建议都将非常感谢。

这是我的代码适用于某些情况,但最终没有做我想要的。当关键字位于链接的后半部分时(例如http://twitter.com/this_keyword),它无法处理。有时奇怪的是它也会在关键字之前突出显示2个字符。我怀疑最好的解决方案太像我的代码了。

function _highlightSearchTerms(text, keywords){

    for (var i=0;i<keywords.length;i++) {

    // create regex to find all instances of the keyword, catch the links that potentially come before so we can filter them out in the next step
    var searchString = new RegExp("[http://twitter.com/||q=%23]*"+keywords[i], "ig");

    // create an array of all the matched keyword terms in the tweet, we can't simply run a replace all as we need them to retain their initial case
    var keywordOccurencesInitial = text.match(searchString);

    // create an array of the keyword occurences we want to actually use, I'm sure there's a better way to create this array but rather than try to optimize, I just worked with code I know should work because my problem isn't centered around this block
    var keywordOccurences = [];
    if (keywordOccurencesInitial != null) {
        for(var i3=0;i3<keywordOccurencesInitial.length;i3++){
            if (keywordOccurencesInitial[i3].indexOf("http://twitter.com/") > -1 || keywordOccurencesInitial[i3].indexOf("q=%23") > -1) 
                continue;
            else
                keywordOccurences.push(keywordOccurencesInitial[i3]);
        }
    }

    // replace our matches with search term
    // the regex should ensure to NOT catch terms we've already wrapped in the span
    // i took the negative lookbehind workaround from http://stackoverflow.com/a/642746/1610101
    if (keywordOccurences != null) {
        for(var i2=0;i2<keywordOccurences.length;i2++){
            var searchString2 = new RegExp("(q=%23||http://twitter.com/||<span class='search-term'>)?"+keywordOccurences[i2].trim(), "g"); // don't replace what we've alrdy replaced
            text = text.replace(searchString2, 
                function($0,$1){ 
                    return $1?$0:"<span class='search-term'>"+keywordOccurences[i2].trim()+"</span>";
                });
        }
    }

    return text;
}

1 个答案:

答案 0 :(得分:1)

您可以使用

Here's something

var getv = document.getElementById('tekt').value;
var keywords = "keyword,big elephant"; // comma delimited keyword list
var rekeywords = "(" + keywords.replace(/\, ?/ig,"|") + ")"; // wraps keywords in ( and ), and changes , to a pipe (character for regex alternation)

var keyrex = new RegExp("(#?\\b" + rekeywords + "\\b)(?=[^>]*?<[^>]*>|(?![^>]*>))","igm")

alert(keyrex);
document.getElementById('tekt').value =  document.getElementById('tekt').value.replace(keyrex,"<span class=\"search-term\">$1</span>");

And here是一种试图处理单词形式的变体。如果单词以ed,es,s,ing等结尾,则会将其删除,并且在查找单词末尾的单词边界时,它还会查找以通用后缀结尾的单词。它并不完美,例如过去的骑行时间就是骑行。如果没有让自己达到大量的假阳性,那么使用正则表达式来解释这一点几乎是不可能的。

var getv = document.getElementById('tekt').value;
var keywords = "keywords,big elephant";
var rekeywords = "(" + keywords.replace(/(es|ing|ed|d|s|e)?\b(\s*,\s*|$)/ig,"(es|ing|ed|d|s|e)?$2").replace(/,/g,"|") + ")";

var keyrex = new RegExp("(#?\\b" + rekeywords + "\\b)(?=[^>]*?<[^>]*>|(?![^>]*>))","igm")

console.log(keyrex);

document.getElementById('tekt').value =  document.getElementById('tekt').value.replace(keyrex,"<span class=\"search-term\">$1</span>");

修改

  

这几乎是完美的。你知道怎么稍微修改它,所以thiskeyword.com中的关键字也会突出显示吗?

更改此行

var keyrex = new RegExp("(#?\\b" + rekeywords + "\\b)(?=[^>]*?<[^>]*>|(?![^>]*>))","igm")

to(我所做的就是删除\\b):

var keyrex = new RegExp("(#?" + rekeywords + ")(?=[^>]*?<[^>]*>|(?![^>]*>))","igm")

但要注意,你会遇到smiles最终为英里的问题(如果用户搜索英里),并且正则表达式无法做到这一点。正则表达式对单词的定义是字母数字字符,它没有要检查的字典。