2011年7月4日

从网页中分析正文探讨(一)

做网站的朋友们不免都会涉及到要从其他网站抓取一些信息。

 1. 常用的办法是用正则表达式来获取

  优点:比较精准,一蹴而就,不会遗漏你需要的内容

 缺点:全中国这么多网页,如果写正则表达式要写到发疯! 如果目标网页一旦改版就要重新写正则表达式,人工排查工作太大。


2. 我们要讨论的是是否能自动分析网页正文 (标题在下一章节讲)

  有两个思路 第一是:关键字匹配法(本次主要讲述此方法,仅思路,因商业原因不提供源代码)  第二个是:文本区域获取法

   关键字匹配法

  每个新闻页面都充斥着大量的文字要素,干扰因素非常多,本人查阅了很多关于分析正文的文章,很复杂,不适合我们草根程序员使用,而且算法完成后精确度不怎么样,效率也不是很高。于是个人山寨了一个关键字匹配法.

  准备工作 :

  1.准备一个分词类库 这里使用的是 shotseg 1.0   效果很一般 但是还可以用用了。

  2.稍微看一下  tf-idf 的概念(TF-IDF是一种统计方法,用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正 比增加,但同时会随着它在语料库中出现的频率成反比下降。TF-IDF加权的各种形式常被搜索引擎应用,作为文件与用户查询之间相关程度的度量或评级。除 了TF-IDF以外,互联网上的搜寻引擎还会使用基于连结分析的评级方法,以确定文件在搜寻结果中出现的顺序。)

  3.自己写代码实现根据 url 获取 html源代码的方法,由于太简单 这里不讨论。

   4.过滤html源码中的所有超级链接和脚本 以及图片(图片过滤方法本文不讨论,后面会讲), 因为新闻详细页中的超级链接我们是不需要的,我们需要的是文字信息。


 接下来开始思路讲解:

  1.过滤完成后的文本,按照回车进行切割,会变成一个文本数组, 里面包含了空行和文本信息, 这里的空行在本文中没什么用处,但是在下一章节中就很有用了

  结果 会出现 这样  string[] strList={ "   ",

         "\t    ",

       "今天气温到达了40度",

     " 摘要:江南地区温度急速上升"

    "请发表评论",

    "内容:经过气象台预测,可能今日江苏地区气温会上升到40度左右。",

    "请广大网民做好防暑工作,尽量减少在高温下进行体力工作",

     "\t    ",

   "\t    ",

   "\t    ",

   "版权所有:测试新闻网 ",

                                                            }

  对于这段文字 我们需要的是 今气温到达了40度 内容:经过气象台预测,可能今日江苏地区气温会上升到40度左右。请广大网民做好防暑工作,尽量减少在高温下进行提供作".    其他的内容都不要 .

    通过使用 shootseg 分出关键字(稍作处理), 则获得如下关键字 气温,今天,摘要,江南地区,温度,评论,内容,气象台,预测,江苏,地区,网民,防暑,减少,高温,版权,新闻

   然后分别计算 这些关键字的tf-idf 值,(语料库 要自己准备,数据库中数据越多,语料库越完善) ,经过计算

  获取tf idf 值最有价值的关键字  气温,防暑,体力,  这里需要你在实践中设置阀值 ,既tf idf值的认可系数。


  于是接下来的事情 就比较简单了, 循环所有 列表 ,抽取 包含上述 “最有价值” 关键字的 段落 然后进行拼接  于是就得到了最终 的网页正文。


 至于标题, 这里使用的 是  正则表达式 获取 <title></title>的 内容,这样可以很有效的过滤掉 干扰因素



经过我程序测试 ,大部分新闻网站都能正确 抓取。  因为 大部分新闻 段落 都和本文的的关键字直接有关。然后 有种情况经常会遗漏。

如我看到一篇公告 页面 内容如下 

四、周边环境
1.商业:常州购物中心、文化宫、天宁商都
2.娱乐配套:黄金大酒店、东方明珠KTV、文笔山庄
3.其他:红梅公园、常州火车站、常州长途汽车客运站

五、注意事项
1.竞买资格:具有完全民事行为能力的自然人或法人
2.标的需要一次性付款,贷款合作银行为中国建设银行常州分行营业部

六、联系方式
王先生 1399XXX


    正文就不贴了, 正文是 一段对该公告在该地区的介绍,用上述方法能正确获取, 然而 像上述段落属于要素信息,和新闻正文似乎没有太大关系,这些段落的关键字tfidf 值都很低,那么如果我要获取到该如何, 下一章 讲 “文本区域法获取正文的方法” 待续.....

posted @ 2011-07-04 17:23 沈逸 阅读(1561) 评论(4) 编辑

2009年12月28日

从产品角度技术化优秀员工的评定

 一个软件产品做的好不好,从用户角度至少会有三个因素:产品的价格、性能、服务(用户体验)。以前很多用户往往只关注前面两个因素,现在的用户对产品的服务以及用户体验的重视程度已经远远高于前两项。就像我们到超市去购买消费品,如果你是个会过日子的人,那么性价比是你最重视,而不是哪样便宜买哪样。现在政府采购软件也是需要对各家供应商提供的产品进行综合评分,当然涉及到的因素不止上述三项,但是都包含上述三项。

    接近年底,公司要对优秀员工进行评比。既然是评比免不了要进行员工投票,既然有投票肯定有权重的区分。事实上全员投票带来一个很明显的弊端就是,被投员工所在部门员工数占人员总数较多的话,该被投员工相对要占光的多;同时部门领导和公司高级管理者投票的票额权重肯定要大,譬如A员工和B员工得到的员工票数一样,那么如果A员工平时比较内向不合群,而B比较得到领导的欢心那么在管理者投票的过程中一定会有人情分在里面。

    这两天和公司同事在讨论优秀员工评比唱票一事,基本上大家都比较认可一个公式:员工的票数*系数+公司管理者票数*系数。当然公司管理者的票数不是一人一票制度,而是公司管理者投票数/公司管理者总票数的商再乘以公司全体员工总票数的结果。一般来说假如2个员工得到的员工票数一样,那么决定权就在公司管理者票数里面。

    为了好理解,我们做一个例子:假设公司总员工100个人, A员工参与优秀员工评选,公司普通员工投票获得50票,系数是0.3,结果是15;公司中级管理者假设20个人有10个人投票给A员工 ,则A获得中级管理者投票是(10/20)*100,假设系数也是0.3,则结果为15票;假设公司高级管理者10人5票投了A员工,系数0.4,则结果是20。最后A的总分(不是总票)是50。

 

      接下来我们用另外一个角度思考上述问题:

 

     其实上面的公式在计算是充分考虑到了权重、人数比例和系数问题。一般来说得到的结果不会有太大误差,但事实上有几个因素很难设置的公正:

       1。系数-----没有充分依据可以证明公式的系数为0.3,0.3,0.4分配

       2. 假设2个员工3项投票(普通员工、中级管理者、高级管理者)得到的结果都不一样,但总合是一样的那么如何区分孰高孰低。

 

      事实上优秀员工的评定,和第一段中产品的评定很类似。也可以从三个角度来看,还是以A员工为例子,大家靠的最近的同事对A相对比较了解,也就是价格比较了解;部门领导对A的工作响应程度、执行力比较了解,也就是性能;公司高级管理者对A接触很少,只能从侧面、宏观上了解A的一些产品实施、开发上的情况也就是高级领导的用户体验。

     

      为了节省篇幅接下用1,2,3,4代表我的话:

      1.优秀员工的评定应该至少3个因素

      2.各个因素都要能对最后成绩产生足够影响。误差不能太大。这点是最重要的。

      

      于是我考虑了以下一个方案,思路如下:

 

       1.不能因为3项投票的某一项特别高分导致结果特别高,导致出现拉分情况。

       2.要3项投票同时决定最后成绩,不应该设置系数。

       3.管理者得分子公式不变,管理者分值权重依然需要保留,否则总分无任何意义。

       4.3项分值总合的二分值都应该大于三项得分的分值每一项得分。譬如三项得分分别是50,0,30  则表示无效投票,这样防止员工拉票或者人情分在里面

       5.我们可以把3项得分的值看成“由这3根分值线组成的三角形”  (第四个条件是第五个条件成立的前提)

        于是方案结论基本可以看出来,最后的得分的评定标准是这个三角形的面积大小,同时也解决了当发现总分一样(既周长一样)的情况下如何区分高低.至于为何这么设定以后我会给出论证。

        于是我们拿出小学或者初中就学过的公式:海伦公式

        假设A员工获得普通员工投票40票,中层票数是30票,高层票数是20票。则他的最终得分是:

           假设p=(40+30+20)/2=45

            则结果=(p*(p-a)*(p-b)*(p-c))的结果开根号(不知道怎么打符号)=290.4

 

   以上是一种理想化的思路,在实际情况中往往会出现很多情况,会导致上述的三角形结构不成立,事实上一个产品只有性能、价格、服务都比较均衡并且带来的性价比相对较高时,才能认为这是一个好产品,优秀员工的评比也应该如此。

 

             欢迎拍砖或者提供更好的思路。


posted @ 2009-12-28 11:05 沈逸 阅读(1637) 评论(0) 编辑

2008年5月20日

利用回调实现脚本实体类和模拟Ajax

这里有几点。 我们用asp.net开发数据库应用时。时常要建立一些实体如
 public class UserEntity
{
   
public string UserName
   
{
     
get{
     
return "";}

    }

   
public string UserEmail
    
{
      
get{
       
return "" ;}

     }

}

      下面要讲的是如何使用脚本来模拟这种实体

     首先 要讲解概念 要返还类似这种实体脚本可以这么写 

 

   UserEntity=function()
{
  
return {"UserName":"shenyi","UserEmail":"shenyi@csdn.net"}
}

     这样我们在 脚本中只要写

   var scriptEntity=new UserEntity();
  scriptEntity.UserName;
  scriptEntity.UserEmail;

   就可以引用到,好  脚本实体构建好了。接下来我们要从服务器取数据如下

    新建一个aspx页面 假如叫 getData.aspx 在代码里写

   public void Page_load()
  
{
   
int userid=int.parse(Request.QueryString["uid"].ToString());
      
string sql="select * from Users where userid="+userid.ToString();
     
using(DataTable dt=SqlHelper.ExecuteDataSet(sql).Tables[0])   //SqlHelper 不要告诉我 不知道是什么
    {
        
// 这里构建一个 字符 令 一个 脚本变量 等于 {"UserName":dt.rows[0]["username].......}
        
//如  Response.Write("userReturnValue={.......//这里自己拼接}");
       Response.End();
    }

  }

 

    以下是如何把脚本和这个 aspx页面建立联系  如下直接是代码

   

 var UserReturnValue=""  //这个很重要一定要定义 因为在服务端要对其赋值 

ComJS
=function()
{
   
   
this.GetEntitying=function(uid,callback)
   
{
   
var scriptObj=document.createElement("script");
    scriptObj.type
="text/javascript";
    scriptObj.src
="getData.aspx?uid="+uid
     document.getElementsByTagName(
"head")[0].appendChild(scriptObj);
 
 
       scriptObj.onreadystatechange
=function()
        
{
            
if(scriptObj.readyState=="loaded")
            
{
                  
                 callback.EndGetEntity(UserReturnValue);
            }

        }

        
    }

}

 

    这里使用 callback回调 是最重要的一步 当脚本加载完毕后才会对UserReturnValue 进行赋值 因此我们不能直接获得这个实体.

  上面脚本写完后 我们在页面要开始获得这个 实体

 

  var cjs=new ComJS();  //初始化我们的脚本对象
   function BeginGetEntity()
      
{
         
this.EndGetEntity=function(entityDataList)
           
{
            
//entityDataList   这个就是最终的实体对象 你可以直接 用 entityDataList.UserName 或者 entityDataList.表里字段名
        
//来获取这个实体的对象
      
// 注意  业务操作 要在这个 函数内执行。因为这是一个回调。也就是当服务端把数据取到了 这边才开始执行
严格来说就是异步获取数据。类似Ajax  但是不使用 xmlhttp对象 
          }

      }

    
     var bge
=new BeginGetEntity();
        cjs.GetEntity(
"3",bgelist);  //这里的3代表我要取用户id等于3的 数据

 

    好/ 整个用脚本构建实体的方法写好 希望对大家尤其是初学者 会有点用。其实在脚本中要实现ajax不光只有xmlhttp可以实现 很普通的脚本也能实现

posted @ 2008-05-20 10:00 沈逸 阅读(2183) 评论(8) 编辑

数据挖掘初探-用简单公式预测下月数据

posted @ 2008-05-20 09:53 沈逸 阅读(2519) 评论(12) 编辑

导航

<2012年2月>
2930311234
567891011
12131415161718
19202122232425
26272829123
45678910

公告

昵称:沈逸
园龄:3年8个月
粉丝:3
关注:0

搜索

 
 

常用链接

我的标签

随笔档案

最新评论