java实现 PageRank算法

Wesley13
• 阅读 667

 PageRank算法是Google的核心搜索算法,在所有链接型文档搜索中有极大用处,而且在我们的各种关联系统中都有好的用法,比如专家评分系统,微博搜索/排名,SNS系统等。
   PageRank算法的依据或思想:
    1,被重要的网页链接的越多(外链)  ,此网页就越重要
    2,此网页对外的链接越少越重要
    这两个依据不能是独立的,是需要一起考虑的。但是问题来了,我们怎样判断本网页的外链是很重要的呢?循环判断?那不死循环了?
    解决办法是:给定阀值,让循环在此临界处停止。
   首先,我们准备了7个测试网页,这几个网页的链接情况如下:

   java实现 PageRank算法

表格的意思是 test1链接到 test2,test3 ....依次类推 ,我们大致的根据上面两个原则可以猜一下,哪个将会是排名第一的网页?哪个最不重要?
   貌似是test4和test6?
   下面我们看看怎样用java实现PageRank算法。
   首先创建html实体表示类,代码如下:

/**
 * 网页entity
 * 
 * @author  afei
 * 
 */
class HtmlEntity {

    private String path;
    private String content;
    /* 外链(本页面链接的其他页面) */
    private List<String> outLinks = new ArrayList<String>();

    /* 内链(另外页面链接本页面) */
    private List<String> inLinks = new ArrayList<String>();

    private double pr;

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public double getPr() {
        return pr;
    }

    public void setPr(double pr) {
        this.pr = pr;
    }

    public List<String> getOutLinks() {
        return outLinks;
    }

    public void setOutLinks(List<String> outLinks) {
        this.outLinks = outLinks;
    }

    public List<String> getInLinks() {
        return inLinks;
    }

    public void setInLinks(List<String> inLinks) {
        this.inLinks = inLinks;
    }

}

核心算法代码如下:

/**
 * pagerank算法实现
 * 
 * @author  afei
 * 
 */
public class HtmlPageRank {

    /* 阀值 */
    public static double MAX = 0.00000000001;

    /* 阻尼系数 */
    public static double alpha = 0.85;

    public static String htmldoc = "D:\\workspace\\Test\\WebRoot\\htmldoc";

    public static Map<String, HtmlEntity> map = new HashMap<String, HtmlEntity>();

    public static List<HtmlEntity> list = new ArrayList<HtmlEntity>();

    public static double[] init;

    public static double[] pr;

    public static void main(String[] args) throws Exception {
        loadHtml();
        pr = doPageRank();
        while (!(checkMax())) {
            System.arraycopy(pr, 0, init, 0, init.length);
            pr = doPageRank();
        }
        for (int i = 0; i < pr.length; i++) {
            HtmlEntity he=list.get(i);
            he.setPr(pr[i]);
        }
        
        List<HtmlEntity> finalList=new ArrayList<HtmlEntity>();
        Collections.sort(list,new Comparator(){

            public int compare(Object o1, Object o2) {
                HtmlEntity h1=(HtmlEntity)o1;
                HtmlEntity h2=(HtmlEntity)o2;
                int em=0;
                if(h1.getPr()> h2.getPr()){
                    em=-1;
                }else{
                    em=1;
                }
                return em;
            }
            
        });
        
        for(HtmlEntity he:list){
            System.out.println(he.getPath()+" : "+he.getPr());
        }

    }

    /* pagerank步骤 */

    /**
     * 加载文件夹下的网页文件,并且初始化pr值(即init数组),计算每个网页的外链和内链
     */
    public static void loadHtml() throws Exception {
        File file = new File(htmldoc);
        File[] htmlfiles = file.listFiles(new FileFilter() {

            public boolean accept(File pathname) {
                if (pathname.getPath().endsWith(".html")) {
                    return true;
                }
                return false;
            }

        });
        init = new double[htmlfiles.length];
        for (int i = 0; i < htmlfiles.length; i++) {
            File f = htmlfiles[i];
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    new FileInputStream(f)));
            String line = br.readLine();
            StringBuffer html = new StringBuffer();
            while (line != null) {
                line = br.readLine();
                html.append(line);
            }
            HtmlEntity he = new HtmlEntity();
            he.setPath(f.getAbsolutePath());
            he.setContent(html.toString());
            Parser parser = Parser.createParser(html.toString(), "gb2312");
            HtmlPage page = new HtmlPage(parser);
            parser.visitAllNodesWith(page);
            NodeList nodelist = page.getBody();
            nodelist = nodelist.extractAllNodesThatMatch(
                    new TagNameFilter("A"), true);
            for (int j = 0; j < nodelist.size(); j++) {
                LinkTag outlink = (LinkTag) nodelist.elementAt(j);
                he.getOutLinks().add(outlink.getAttribute("href"));
            }

            map.put(he.getPath(), he);
            list.add(he);
            init[i] = 0.0;

        }
        for (int i = 0; i < list.size(); i++) {
            HtmlEntity he = list.get(i);
            List<String> outlink = he.getOutLinks();
            for (String ol : outlink) {
                HtmlEntity he0 = map.get(ol);
                he0.getInLinks().add(he.getPath());
            }
        }

    }

    /**
     * 计算pagerank
     * 
     * @param init
     * @param alpho
     * @return 
     */
    private static double[] doPageRank() {
        double[] pr = new double[init.length];
        for (int i = 0; i < init.length; i++) {
            double temp = 0;
            HtmlEntity he0 = list.get(i);
            for (int j = 0; j < init.length; j++) {
                HtmlEntity he = list.get(j);
                // 计算对本页面链接相关总值
                if (i != j && he.getOutLinks().size() != 0
                        && he.getOutLinks().contains(he0.getPath())/*he0.getInLinks().contains(he.getPath())*/) {
                    temp = temp + init[j] / he.getOutLinks().size();
                }

            }
            //经典的pr公式
            pr[i] = alpha + (1 - alpha) * temp;
        }
        return pr;
    }

    /**
     * 判断前后两次的pr数组之间的差别是否大于我们定义的阀值 假如大于,那么返回false,继续迭代计算pr
     * 
     * @param pr
     * @param init
     * @param max
     * @return 
     */
    private static boolean checkMax() {
        boolean flag = true;
        for (int i = 0; i < pr.length; i++) {
            if (Math.abs(pr[i] - init[i]) > MAX) {
                flag = false;
                break;
            }
        }
        return flag;
    }
    
    
    

}

直接运行算法类,得到的结果如下:

D:\workspace\Test\WebRoot\htmldoc\test4.html : 1.102472450686259
D:\workspace\Test\WebRoot\htmldoc\test5.html : 1.068131842865856
D:\workspace\Test\WebRoot\htmldoc\test2.html : 1.0249590169406457
D:\workspace\Test\WebRoot\htmldoc\test3.html : 1.0046891014946187
D:\workspace\Test\WebRoot\htmldoc\test1.html : 0.9943895104008613
D:\workspace\Test\WebRoot\htmldoc\test7.html : 0.9051236225340915
D:\workspace\Test\WebRoot\htmldoc\test6.html : 0.9002344550746025

此算法可以无限改造,以满足自身要求。

By 阿飞哥 转载请说明

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
2年前
SEO SEM
SEO:搜索引擎优化SEM:搜索引擎营销SEO排名机制:搜索引擎蜘蛛权重算法排名规则搜索引擎提交入口:1.百度搜索网站登入口2.Google网站登入口3.360搜索引擎登入入口4.搜狗网站登入入口5.必应网站等等SEO优化最重要的三要素:标题关键词描述外链(如友情链接)引流
Stella981 Stella981
2年前
Spark的分区机制的应用及PageRank算法的实现
佩奇排名(PageRank),又称网页排名、谷歌左侧排名,是一种由搜索引擎根据网页之间相互的超链接计算的技术,而作为网页排名的要素之一,以Google公司创办人拉里·佩奇(LarryPage)之姓来命名。Google用它来体现网页的相关性和重要性,在搜索引擎优化操作中是经常被用来评估网页优化的成效因素之一。概念Sp
Wesley13 Wesley13
2年前
Java日期时间API系列31
  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
菜园前端 菜园前端
10个月前
什么是分而治之?
原文链接:什么是分而治之?在我们前面有学习过一系列数据结构、以及相关的一些算法,包含排序、搜索算法。而本次学习的分而治之它不是数据结构,也不是一种算法,而是算法设计中的一种方法,可以理解为是一种思想。我们可以利用这种思想去设计很多种算法。分而治之是将一个问
京东云开发者 京东云开发者
7个月前
分布式系统的主键生成方案对比 | 京东云技术团队
UUID​UUID(通用唯一识别码)是由32个十六进制数组成的无序字符串,通过一定的算法计算出来。为了保证其唯一性,UUID规范定义了包括网卡MAC地址、时间戳、名字空间(Namespace)、随机或伪随机数、时序等元素,以及从这些元素生成UUID的算法。