PageRank的Page可是认为是网页,表示网页排名,也可以认为是Larry Page(google 产品经理),因为他是这个算法的发明者之一,还是google CEO(^_^)。PageRank算法计算每一个网页的PageRank值,然后根据这个值的大小对网页的重要性进行排序。它的思想是模拟一个悠闲的上网者,上网者首先随机选择一个网页打开,然后在这个网页上呆了几分钟后,跳转到该网页所指向的链接,这样无所事事、漫无目的地在网页上跳来跳去,PageRank就是估计这个悠闲的上网者分布在各个网页上的概率。
二、PageRank原理 入链==投票PageRank让链接来进行”投票”, 到一个页面的超链接相当于对该页面投一票
入链的数量果一个页面节点接收到其他页面指向的入链越多,那么这个页面越重要
入链的质量指向A页面的入链质量不同,质量越高的页面指向A, 会传递更高的权重,如在董事会中, 核心董事成员可能一票相当于10票, 核心董事成员的一票肯定比普通董事成员一票更重要。 PageRank算法刚开始赋予每个网页相同的重要性得分,通过迭代递归计算来更新每个页面节点的PageRank得分,直到得分稳定为止
网络上的各个页面的链接图 PageRank的计算步骤:
1)在初始阶段:网页通过链接关系构建起链接图,每个页面设置相同的PageRank值,通过若干轮的计算,会得到每个页面所获得的最终PageRank值。随着每一轮的计算进行,网页当前的PageRank值会不断得到更新。
2)在一轮中更新页面PageRank得分的计算方法:在一轮更新页面PageRank得分的计算中,每个页面将其当前的PageRank值平均分配到本页面包含的出链上,这样每个链接即获得了相应的权值。而每个页面将所有指向本页面的入链所传入的权值求和,即可得到新的PageRank得分。当每个页面都获得了更新后的PageRank值,就完成了一轮PageRank计算。
原始数据为:
当前节点 出链节点1 出链节点2
A B D
通过迭代计算每个节点的PR值
A 0.9 B D
3.1、设置节点对象,
每个节点包含内容:
- PR值
- 出链的节点
所以创建一个节点类,具有的属性:
//每个页面的出事pr值为1.0
private double pageRank=1.0;
//该节点的出链指向的节点
private String[] adjacentNodeNames;
我们为了使用数据输出格式化, 创建一个分割符
//各个节点的分隔符
public static final char fieldSeparator = '\t';
重写头String(), 打印Node的节点信息, 输出成一个字符串 每个节点打印信息:PageRank值 出链节点1 出链节点2 …
@Override
public String toString() {//每个节点打印信息:PageRank值 出链节点1 出链节点2 ...
StringBuilder sb = new StringBuilder();
sb.append(pageRank);
if (getAdjacentNodeNames() != null) {
sb.append(fieldSeparator)
.append(StringUtils
.join(getAdjacentNodeNames(), fieldSeparator));
}
return sb.toString();
}
同时提供一个方法,通过PR值,及出链节点,将字符串信息恢复成一个Node对象。 给定的字符串:PR值 出链节点1 出链节点
/**
* @param value 给定一个字符串 value =1.0 B D
* @return 将这个字符串1封装成Node对象。
*/
public static Node fromMR(String value) throws IOException {
String[] parts = StringUtils.splitPreserveAllTokens(
value, fieldSeparator);
if (parts.length < 1) {
throw new IOException(
"Expected 1 or more parts but received " + parts.length);
}
Node node = new Node()
.setPageRank(Double.valueOf(parts[0]));
if (parts.length > 1) {
node.setAdjacentNodeNames(Arrays.copyOfRange(parts, 1,
parts.length));
}
return node;
}
节点的完整类Node:
package com.chb.pagerank;
import java.io.IOException;
import java.util.Arrays;
import org.apache.commons.lang.StringUtils;
public class Node {
//每个页面的出事pr值为1.0
private double pageRank=1.0;
//该节点的出链指向的节点
private String[] adjacentNodeNames;
//各个节点的分隔符
public static final char fieldSeparator = '\t';
public double getPageRank() {
return pageRank;
}
public Node setPageRank(double pageRank) {
this.pageRank = pageRank;
return this;
}
public String[] getAdjacentNodeNames() {
return adjacentNodeNames;
}
public Node setAdjacentNodeNames(String[] adjacentNodeNames) {
this.adjacentNodeNames = adjacentNodeNames;
return this;
}
//判断是否有出链节点
public boolean containsAdjacentNodes() {
return adjacentNodeNames != null && adjacentNodeNames.length>0;
}
@Override
public String toString() {//每个节点打印信息:PageRank值 出链节点1 出链节点2 ...
StringBuilder sb = new StringBuilder();
sb.append(pageRank);
if (getAdjacentNodeNames() != null) {
sb.append(fieldSeparator)
.append(StringUtils
.join(getAdjacentNodeNames(), fieldSeparator));
}
return sb.toString();
}
/**
* @param value 给定一个字符串 value =1.0 B D
* @return 将这个字符串1封装成Node对象。
*/
public static Node fromMR(String value) throws IOException {
String[] parts = StringUtils.splitPreserveAllTokens(
value, fieldSeparator);
if (parts.length < 1) {
throw new IOException(
"Expected 1 or more parts but received " + parts.length);
}
Node node = new Node()
.setPageRank(Double.valueOf(parts[0]));
if (parts.length > 1) {
node.setAdjacentNodeNames(Arrays.copyOfRange(parts, 1,
parts.length));
}
return node;
}
}