8

所以我试图获取我网页中使用的所有单词的数组。

应该很容易吧?

我遇到的问题是$("body").text().split(" ")返回一个数组,其中一个元素的开头和另一个元素的结尾处的单词连接为一个。

IE:

<div id="1">Hello
    <div id="2">World</div>
</div>

["HelloWorld"]当我希望它返回时返回["Hello", "World"]

我也试过:

wordArr = [];

function getText(target)
{    
    if($(this).children())
    {
        $(this).children(function(){getText(this)});
    }
    else
    {
        var testArr = $(this).text().split(" ");
        for(var i =0; i < testArr.length; i++)
            wordArr.push(testArr[i]);
    }

}

getText("body");

$(node).children()对于 DOM 中存在的任何节点都是真实的,所以这不起作用。

我确定我遗漏了一些明显的东西,所以我会很感激多一双眼睛。

对于它的价值,我不需要唯一的单词,只需要文档正文中的每个单词作为数组中的一个元素。我正在尝试使用它来生成上下文和与另一组单词的词汇共现,因此仅复制给定单词的上下文重要性。

提前感谢您的任何想法。

小提琴

4

4 回答 4

6

这样的事情怎么样?

 var res = $('body  *').contents().map(function () {
    if (this.nodeType == 3 && this.nodeValue.trim() != "") 
        return this.nodeValue.trim();
}).get().join(" ");
console.log(res);

演示

获取单词数组:

var res = $('body  *').contents().map(function () {
    if (this.nodeType == 3 && this.nodeValue.trim() != "") //check for nodetype text and ignore empty text nodes
        return this.nodeValue.trim().split(/\W+/);  //split the nodevalue to get words.
}).get(); //get the array of words.

console.log(res);

演示

于 2013-06-03T21:59:29.497 回答
3
function getText(target) {
    var wordArr = [];
    $('*',target).add(target).each(function(k,v) {
        var words  = $('*',v.cloneNode(true)).remove().end().text().split(/(\s+|\n)/);
        wordArr = wordArr.concat(words.filter(function(n){return n.trim()}));
    });
    return wordArr;
}

小提琴

于 2013-06-03T22:12:34.487 回答
1

该问题假设单词内部没有被元素分隔。如果您只是创建一个由空格和元素分隔的单词数组,您将得到:

Fr<b>e</b>d

被读作

['Fr', 'e', 'd']; 

要考虑的另一件事是标点符号。你如何处理:“他们三个:马克、苏和汤姆。他们并不引人注目。一个——红头——在中间。” 你会删除所有标点符号吗?或者在修剪之前用空白替换它?您如何重新连接被标记或可能是单词间或单词内标点符号的字符分割的单词?请注意,虽然在单词之间用空格写破折号很流行,但“正确”标点符号使用不带空格的 m 破折号。

没那么简单…

无论如何,一种仅使用递归分割空间和元素并在没有任何库支持的情况下在任何正在使用的浏览器中工作的方法是:

function getWords(element) {
  element = element || document.body;
  var node, nodes = element.childNodes;
  var words = [];
  var text, i=0;

    while (node = nodes[i++]) {

    if (node.nodeType == 1) {
      words = words.concat(getWords(node));

    } else if (node.nodeType == 3) {
      text = node.data.replace(/^\s+|\s+$/g,'').replace(/\s+/g,' ');
      words = !text.length? words : words.concat(text.split(/\s/));
    }
  }
  return words;
}

但它不处理上述问题。

编辑

要避免脚本元素,请更改:

    if (node.nodeType == 1) {

    if (node.nodeType == 1 && node.tagName.toLowerCase() != 'script') {

任何应该避免的元素都可以添加到条件中。如果应避免使用多种元素类型,您可以执行以下操作:

var elementsToAvoid = {script:'script', button:'button'};
...
    if (node.nodeType == 1 && node.tagName && !(node.tagName.toLowerCase() in elementsToAvoid)) {
于 2013-06-04T00:06:44.623 回答
1

你可以这样做

function getwords(e){
    e.contents().each(function(){
        if ( $(this).children().length > 0 ) {
            getwords($(this))
        }
        else if($.trim($(this).text())!=""){
            words=words.concat($.trim($(this).text()).split(/\W+/))
        }
    });
}    

http://jsfiddle.net/R55eM/

于 2013-06-03T23:02:31.853 回答