个人家园,纯属虚构

蛙蛙牌正文提取算法

上一篇 / 下一篇  2008-04-13 18:27:05 / 个人分类:程序学习

转载自朋友的blog,原文地址:http://www.cnblogs.com/onlytiancai/archive/2008/04/12/getmaincontent.html

这是关于关于蜘蛛程序提取html正文的一个方法,感觉还不错,部分利用了人工神经网络的算法

原文如下:

摘要:
上次和大家讨论了一些正文提取的细节问题,这次我把一些关键问题解决了,给大家上一下代码,并做了演示,能提取不少网站的正文了,当然在功能和代码组织上还有不少改进的地方。

思路:
1、抓取远程网页源码,这里要实现自动判断网页编码,否则有可能抓到乱码。我是先看应答的http头的chareset,一般这个很准,但像csdn的新闻比较变态http应答的头里的chareset和网页的meta里声明的chareset不一致,所以我手工加了一下判断,如果不一致再在内存流里用网页声明的编码读取一遍源码
2、把网页分割成几大块。试用了一下tidy的.net包装及HtmlParse的.net版本,都不太好用。于是我自己写了个算法,可以把网页里的div块,td块等都提取出来,支持嵌套的情况。一般只提取div的文字块儿就行了。
3、把汉字少于200的文本块去了,一般少于200字的文本块不会是正文,即便是正文,一般来说也不会有太多的价值,我直接去掉。
4、因为div支持嵌套,所以剩下的文本块,有可能是重复的,一个是另一个的父节点,所以要把最里层的文本块找出来,最里层的文本块肯定是汉字最多的,而其它文本最少的,所以要计算出剩余文本块中汉字占所有字符比例最高的文本块,基本上它就是正文的文本块了。当然有的网页正文里也可能还有div的文本块,这时候可能会判断错误,但只要正文嵌套的Div文本块的汉字少于200字,我的算法还是能准确提取正文文本块的。这一步我用写了一个自定义的方法传递给List的Sort方法。
5、把<p><br>等标签替换成特殊占位符[p][br]等,因为最终的正文需要保留段落和回车换行等格式。这一步用正则实现。
6、把最后剩下的文本块的html标签去掉,我用正则过滤的。
7、吧[p]替换成回车换行加俩空格,吧[br]替换成回车换行,这步也用正则。到此,正文提取完毕
主要代码:

public class GetMainContentHelper
{
    
/// <summary>
    
/// 判断两段儿文本里哪个中文占的比例高
    
/// </summary>
    
/// <param name="x"></param>
    
/// <param name="y"></param>
    
/// <returns></returns>

    public static int CompareDinosByChineseLength(string x, string y)
    
{
        
if (x == null)
        
{
            
if (y == null)
            
{
                
return 0;
            }

            
else
            
{
                
return -1;
            }

        }

        
else
        
{
            
if (y == null)
            
{
                
return 1;
            }

            
else
            
{
                Regex r 
= new Regex("[\u4e00-\u9fa5]");
                
float xCount = (float)(r.Matches(x).Count) / (float)x.Length;
                
float yCount = (float)(r.Matches(y).Count) / (float)y.Length;

                
int retval = xCount.CompareTo(yCount);

                
if (retval != 0)
                
{
                    
return retval;
                }

                
else
                
{
                    
return x.CompareTo(y);
                }

            }

        }

    }


    
/// <summary>
    
/// 获取一个网页源码中的标签列表,支持嵌套,一般或去div,td等容器
    
/// </summary>
    
/// <param name="input"></param>
    
/// <param name="tag"></param>
    
/// <returns></returns>

    public static List<string> GetTags(string input, string tag)
    
{
        StringReader strReader 
= new StringReader(input);
        
int lowerThanCharCounter = 0;
        
int lowerThanCharPos = 0;
        Stack
<int> tagPos = new Stack<int>();
        List
<string> taglist = new List<string>();
        
int i = 0;
        
while (true)
        
{
            
try
            
{
                
int intCharacter = strReader.Read();
                
if (intCharacter == -1break;

                
char convertedCharacter = Convert.ToChar(intCharacter);

                
if (lowerThanCharCounter > 0)
                
{
                    
if (convertedCharacter == '>')
                    
{
                        lowerThanCharCounter
--;

                        
string biaoqian = input.Substring(lowerThanCharPos, i - lowerThanCharPos + 1);
                        
if (biaoqian.StartsWith(string.Format("<{0}", tag)))
                        
{
                            tagPos.Push(lowerThanCharPos);
                        }

                        
if (biaoqian.StartsWith(string.Format("</{0}", tag)))
                        
{
                            
if (tagPos.Count < 1)
                                
continue;
                            
int tempTagPos = tagPos.Pop();
                            
string strdiv = input.Substring(tempTagPos, i - tempTagPos + 1);
                            taglist.Add(strdiv);
                        }

                    }

                }


                
if (convertedCharacter == '<')
                
{
                    lowerThanCharCounter
++;
                    lowerThanCharPos 
= i;
                }

            }

            
finally
            
{
                i
++;
            }

        }

        
return taglist;
    }


    
/// <summary>
    
/// 获取指定网页的源码,支持编码自动识别
    
/// </summary>
    
/// <param name="url"></param>
    
/// <returns></returns>

    public static string getDataFromUrl(string url)
    
{
        
string str = string.Empty;
        HttpWebRequest request 
= (HttpWebRequest)HttpWebRequest.Create(url);

        
//设置http头
        request.AllowAutoRedirect =

TAG: 正文提取

 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

日历

« 2009-01-06  
    123
45678910
11121314151617
18192021222324
25262728293031

数据统计

  • 访问量: 262
  • 日志数: 25
  • 图片数: 1
  • 文件数: 3
  • 建立时间: 2008-02-25
  • 更新时间: 2008-10-20

RSS订阅