然并卵?试着用js来抽取网页的正文

然并卵啊,有时候需要抽取网页正文,在网上也看了很多算法,但效果感觉都不好,有的根本打不开无法看到效果,于是自己就试着写了一个,效果还不错,支持图片和Flash和文字一并抽取。
方法就是适用打分机制,把正文文字和标签的比例、标点符号、换行等因素累加起来,打分最高的就是正文,当然肯定有识别不出来的,这个是任何算法都无法避免的。
感兴趣的同学可以看看,代码很短:

然并卵?试着用js来抽取网页的正文

/**
*@Extract Content
*/
var extractor = {iframe: null, iDoc: null};

extractor.extract = function(html)
{
    if(!extractor.iDoc)
    {
        return "";
    }
    
    var arr = html.replace(/\r|\n/g, "").match(/<body(.*)<\/body>/i);
    if(!arr || !arr.length)
    {
        return "";
    }

    html = arr[0].replace(/<iframe.*?<\/iframe>/ig, "");
    html = html.replace(/<link.*?\/?>/ig, "");
    html = html.replace(/<!--.*?-->/g, "");
    html = html.replace(/<style.*?<\/style>/ig, "");
    html = html.replace(/<script.*?<\/script>/ig, "");

    html = html.replace(/<embed.*?\/?>/ig, function(data)
    {
        return data.replace(/<embed/i, "<hide$embed");
    });
    
    html = html.replace(/<img.*?\/?>/ig, function(data)
    {
        return data.replace(/<img/i, "<hide$img");
    });
    
    html = html.replace(/<object.*?<\/object>/ig, function(data)
    {
        var ret = data.replace(/<object/i, "<hide$object");
        return ret.replace(/<\/object/i, "</hide$object");
    });

    extractor.iDoc.body.innerHTML = html;
    return extractor.process(extractor.iDoc.body);
};

extractor.getWordRatio = function(itemStr)
{
    itemStr = itemStr.replace(/\s/g, "");
    itemStr = itemStr.replace(/<a.*?<\/a>/ig, "");
    itemStr = itemStr.replace(/<hide\$embed.*?>/g, "");
    itemStr = itemStr.replace(/<hide\$img.*?>/g, "");
    itemStr = itemStr.replace(/<hide\$object.*?<\/hide\$object>/g, "");

    var stack = [];
    var m = 0, inTag = false;
    for(var i=0;i<itemStr.length;i++)
    {
        var c = itemStr.charCodeAt(i);
        if(c == 62)
        {
            inTag = false;
        }
        
        if(c == 60)
        {
            if(m > 4)
            {
                stack.push(m);
            }
            m = 0;
            inTag = true;
        }

        if(!inTag)
        {
            m++;
        }
    }
    stack.push(m);
    
    var t = 0;
    for(var i=0;i<stack.length;i++)
    {
        t += stack[i];
    }

    return t + t/stack.length;
};

extractor.process = function(body)
{
    var items = body.getElementsByTagName("article");
    if(!items || !items.length)
    {
        items = body.getElementsByTagName("div");
    }

    if(!items || !items.length)
    {
        items = body.getElementsByTagName("table");
    }

    if(!items || !items.length)
    {
        items = body.getElementsByTagName("p");
    }

    if(!items || !items.length)
    {
        return "";
    }
    
    var mostItemStr = null, mostRatio = 0;
    for(var i=0;i<items.length;i++)
    {
        var item = items[i];
        var itemStr = item.innerHTML;
        itemStr = itemStr.replace(/<\/hide\$embed>/g, "");
        itemStr = itemStr.replace(/<\/hide\$img>/g, "");
        if(itemStr.length < 32)
        {
            continue;
        }
        
        var div = item.getElementsByTagName("div");
        if(div && div.length > 48)
        {
            continue;
        }

        if(itemStr.indexOf("<textarea") > -1)
        {
            continue;
        }

        if(/(&copy;?)|(All Rights Reserved)|(Powered By)|(备[0-9]{5,}号)|(版权所有)/ig.test(itemStr))
        {
            continue;
        }

        var ratio = extractor.getWordRatio(itemStr);
        if(ratio >= mostRatio)
        {
            //alert(ratio +",===============,"+ itemStr);
            mostRatio = ratio;
            mostItemStr = itemStr;
        }
    }
    
    if(mostItemStr)
    {
        mostItemStr = mostItemStr.replace(/<hide\$embed/g, "<embed");
        mostItemStr = mostItemStr.replace(/<hide\$img/g, "<img");
        mostItemStr = mostItemStr.replace(/<hide\$object/g, "<object");
        mostItemStr = mostItemStr.replace(/<\/hide\$object/g, "</object");
        
        return mostItemStr;
    }

    return "";
};

extractor.init = function()
{
    if(extractor.iframe)
    {
        return;
    }

    extractor.iframe = document.createElement("iframe");
    extractor.iframe.src = "about:blank";
    extractor.iframe.id = "extractor-iframe";
    extractor.iframe.style.display = "none";
    document.body.appendChild(extractor.iframe);

    extractor.iDoc = extractor.iframe.contentDocument;
    if(!extractor.iDoc)
    {
        extractor.iDoc = extractor.iframe.document;
    }
};

(function(){
    if(!document.body)
    {
        return;
    }
    extractor.init();
})();