对HTML网页正文进行提取

写这么一个算法,能够从过滤html标签后的文本中找到正文文本的起止行号,行号之间的文本就是网页正文部分。

有一个规律:正文部分的文本密度要高出非正文部分很多。我们按照这个特性就可以很容易将算法实现,那就是基于阈(读音:yu)值去分析正文所在的位置。

那么接下来就需要解决一些问题:

  • 如何确定阈值?
  • 如何分析,一行行的分析?还是?

阈值的确定可以通过统计分析得出一个比较好的值,我在实际处理过程中,发现这个值取180是比较合适的,也就是分析文本的时候,如果所分析的文本超过了180,那么就可以认为到达了正文部分。

再有就是如何分析的问题,这个其实比较容易确定,一行行的分析效果肯定不好,如果在按行分析的过程中往下在分析几行作为一次分析效果比较好。也就是一次性分析上5行左右,将字符累加起来,看看有没有达到设定的阈值,如果达到了,那么认为已经进入正文部分了。

嗯,主要的处理逻辑就是这样。

原作者的代码:

int preTextLen = 0;         // 记录上一次统计的字符数量(lines就是去除html标签后的文本,_limitCount是阈值,_depth是我们要分析的深度,sb用于记录正文)
int startPos = -1;          // 记录文章正文的起始位置
for (int i = 0; i < lines.Length - _depth; i++)
{
    int len = 0;
    for (int j = 0; j < _depth; j++)
    {
        len += lines[i + j].Length;
    }

    if (startPos == -1)     // 还没有找到文章起始位置,需要判断起始位置
    {
        if (preTextLen > _limitCount && len > 0)    // 如果上次查找的文本数量超过了限定字数,且当前行数字符数不为0,则认为是开始位置
        {
            // 查找文章起始位置, 如果向上查找,发现2行连续的空行则认为是头部
            int emptyCount = 0;
            for (int j = i - 1; j > 0; j--)
            {
                if (String.IsNullOrEmpty(lines[j]))
                {
                    emptyCount++;
                }
                else
                {
                    emptyCount = 0;
                }
                if (emptyCount == _headEmptyLines)
                {
                    startPos = j + _headEmptyLines;
                    break;
                }
            }
            // 如果没有定位到文章头,则以当前查找位置作为文章头
            if (startPos == -1)
            {
                startPos = i;
            }
            // 填充发现的文章起始部分
            for (int j = startPos; j <= i; j++)
            {
                sb.Append(lines[j]);
            }
        }
    }
    else
    {
        if (len <= _endLimitCharCount && preTextLen < _endLimitCharCount)    // 当前长度为0,且上一个长度也为0,则认为已经结束
        {
            if (!_appendMode)
            {
                break;
            }
            startPos = -1;
        }
        sb.Append(lines[i]);
    }
    preTextLen = len;
}

自己改写成了python3的版本,感觉准确率并不是很高,同时源代码的一些部分还没看懂

    _depth = 5
    _limitCount = 180
    preTextLen = 0
    startPos = -1
    _headEmptyLines = 2
    sb = ''
    _endLimitCharCount = 0
    for i in range(len(split_list) - _depth):
        lens = 0
        for j in range(_depth):
            lens += len(split_list[i+j])

        if startPos == -1:
            if preTextLen > _limitCount and lens > 0:
                emptyCount = 0
                for j in range(i-1, 0, -1):
                    if split_list[j].isspace():
                        emptyCount += 1
                    else:
                        emptyCount = 0
                    if emptyCount == _headEmptyLines:
                        startPos = j + _headEmptyLines
                        break

                if startPos == -1:
                    startPos = i

                for j in range(startPos, i, 1):
                    sb = sb + split_list[j]

        else:
            if lens <= _endLimitCharCount and preTextLen < _endLimitCharCount:
                #if not _appendMode:
                #    break
                startPos = -1

            sb = sb + '\n' + split_list[i]

        preTextLen = lens

    print(sb)

参考资料:https://www.cnblogs.com/jasondan/p/3497757.html

你可能感兴趣的:(nlp)