MapReduce实战PageRank

本文参考章鱼大数据平台   https://www.ipieuvre.com/e/190/311/9539

 

PageRank:网页排名,右脚网页级别。是以Google 公司创始人Larry Page 之姓来命名。PageRank 计算每一个网页的PageRank值,并根据PageRank值的大小对网页的重要性进行排序。

PageRank的基本思想:

1.如果一个网页被很多其他网页链接到的话说明这个网页比较重要,也就是PageRank值会相对较高

2.如果一个PageRank值很高的网页链接到一个其他的网页,那么被链接到的网页的PageRank值会相应地因此而提高。

PageRank的算法原理:

PageRank算法总的来说就是预先给每个网页一个PR值,由于PR值物理意义上为一个网页被访问概率,所以一般是1/N,其中N为网页总数。另外,一般情况下,所有网页的PR值的总和为1。如果不为1的话也不是不行,最后算出来的不同网页之间PR值的大小关系仍然是正确的,只是不能直接地反映概率了。

 

 

实现代码:

package mr_pagerank;  
import java.io.IOException;  
import java.util.StringTokenizer;  
import org.apache.hadoop.conf.Configuration;  
import org.apache.hadoop.fs.Path;  
import org.apache.hadoop.io.Text;  
import org.apache.hadoop.mapreduce.Job;  
import org.apache.hadoop.mapreduce.Mapper;  
import org.apache.hadoop.mapreduce.Reducer;  
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;  
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;  
public class PageRank {  
    /*map过程*/  
    public static class mapper extends Mapper{  
        private String id;  
        private float pr;  
        private int count;  
        private float average_pr;  
        public void map(Object key,Text value,Context context)  
            throws IOException,InterruptedException{  
            StringTokenizer str = new StringTokenizer(value.toString());//对value进行解析  
            id =str.nextToken();//id为解析的第一个词,代表当前网页  
            pr = Float.parseFloat(str.nextToken());//pr为解析的第二个词,转换为float类型,代表PageRank值  
            count = str.countTokens();//count为剩余词的个数,代表当前网页的出链网页个数  
            average_pr = pr/count;//求出当前网页对出链网页的贡献值  
            String linkids ="&";//下面是输出的两类,分别有'@'和'&'区分  
            while(str.hasMoreTokens()){  
                String linkid = str.nextToken();  
                context.write(new Text(linkid),new Text("@"+average_pr));//输出的是<出链网页,获得的贡献值>  
                linkids +=" "+ linkid;  
            }  
            context.write(new Text(id), new Text(linkids));//输出的是<当前网页,所有出链网页>  
        }  
    }  
    /*reduce过程*/  
    public static class reduce extends Reducer{  
        public void reduce(Text key,Iterable values,Context context)  
    throws IOException,InterruptedException{  
    String link = "";  
    float pr = 0;  
    /*对values中的每一个value进行分析,通过其第一个字符是'@'还是'&'进行判断 
    通过这个循环,可以求出当前网页获得的贡献值之和,也即是新的PageRank值;同时求出当前 
    网页的所有出链网页 */  
    for(Text val:values){  
    if(val.toString().substring(0,1).equals("@")){  
    pr += Float.parseFloat(val.toString().substring(1));  
    }  
    else if(val.toString().substring(0,1).equals("&")){  
    link += val.toString().substring(1);  
    }  
    }  
    pr = 0.8f*pr + 0.2f*0.25f;//加入跳转因子,进行平滑处理  
    String result = pr+link;  
    context.write(key, new Text(result));  
    }  
    }  
  
  
    public static void main(String[] args) throws Exception{  
    Configuration conf = new Configuration();  
    conf.set("mapred.job.tracker", "hdfs://127.0.0.1:9000");  
    //设置数据输入路径  
    String pathIn ="hdfs://127.0.0.1:9000/pagerank/input";  
    //设置数据输出路径  
    String pathOut="hdfs://127.0.0.1:9000/pagerank/output/pr";  
    for(int i=1;i<100;i++){      //加入for循环,最大循环100次  
    Job job = new Job(conf,"page rank");  
    job.setJarByClass(PageRank.class);  
    job.setMapperClass(mapper.class);  
    job.setReducerClass(reduce.class);  
    job.setOutputKeyClass(Text.class);  
    job.setOutputValueClass(Text.class);  
    FileInputFormat.addInputPath(job, new Path(pathIn));  
    FileOutputFormat.setOutputPath(job, new Path(pathOut));  
    pathIn = pathOut;//把输出的地址改成下一次迭代的输入地址  
    pathOut = pathOut+'-'+i;//把下一次的输出设置成一个新地址。  
    System.out.println("正在执行第"+i+"次");  
    job.waitForCompletion(true);//把System.exit()去掉  
    //由于PageRank通常迭代30~40次,就可以收敛,这里我们设置循环35次  
    if(i == 35){  
    System.out.println("总共执行了"+i+"次之后收敛");  
    break;  
    }  
    }  
    }  
  
    }  

 

你可能感兴趣的:(大数据技术)