基于pagerank算法的运用Hbase的搜索引擎(3)——迭代计算rangkank值

输入数据:

经过数据清洗后的hbase上的数据表

整体思想:

数据格式:

清洗过后的数据的格式为:rowkey的值是本页面的url;
page:s 该页面分数;
page:iln 该页面的入链个数;
page:oln 该页面的出链个数;
il:url title 该页面的入链列表以及对应的标题;
ol:url title 该页面的出链列表以及对应的标题;

流程:

mapper类主要是对数据的ol列族进行提取,获得每个页面的输出列表,并且为每个列表赋rank值,初值都是1,后面的每个页面的输出表的rank则为该页面的输出列的个数/rank值;
reducer类则对mapper类输出的每个页面的rank值进行累加,然后放入rank列中,进行后面的迭代。

代码如下:
import java.io.IOException;
import java.util.NavigableMap;
import java.util.Map.Entry;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil;
import org.apache.hadoop.hbase.mapreduce.TableMapper;
import org.apache.hadoop.hbase.mapreduce.TableReducer;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
import org.apache.log4j.PropertyConfigurator;


public class PageRankMR extends Configured implements Tool {
    public static void main(String[] args) throws  Exception {
        ToolRunner.run(new PageRankMR(),args);
    }

    @Override
    public int run(String[] strings) throws Exception {
   //     PropertyConfigurator.configure("/GXUST_hadoop/src/main/resources/log4j.properties");
        //迭代10次
    //	for (int i = 1; i < 10; i++) {
            Configuration configuration = getConf();
            configuration.set("hbase.zookeeper.quorum", "hadoopPD:2181");
            Job job = Job.getInstance(configuration);
            job.setJobName(PageRankMR.class.getName());
            job.setJarByClass(PageRankMR.class);
            TableMapReduceUtil.initTableMapperJob(
                    Bytes.toBytes(configuration.get("table")),
                    new Scan(),
                    PageRankMR.PageRankMapper.class,
                    Text.class,
                    Text.class,
                    job);
            TableMapReduceUtil.initTableReducerJob(
            		configuration.get("table"), PageRankMR.PageRankReducer.class, job
            );

            job.waitForCompletion(true);
    //    }
        return 0;
    }

    /**
     * 现有已知数据
     *  page:s 该页面分数
     *  page:iln 该页面的入链个数
     *  page:oln 该页面的出链个数
     *  il:url title 该页面的入链列表以及对应的标题
     *  ol:url title 该页面的出链列表以及对应的标题
     *
     * */
    public static class PageRankMapper extends TableMapper{
        
        @Override
        protected void map(ImmutableBytesWritable key, Result value, Context context) throws IOException, InterruptedException {
        	//声明接收Mapper输出key value的对象
        	Text outKey=new Text();
            Text outValue=new Text();
        	//获取该页面的url即是Rowkey值
            String pageUrl=Bytes.toString(key.get());
            //获取该页面的权重值 权重值从 page:rank列中取
            byte[] rank = value.getValue(Bytes.toBytes("page"),Bytes.toBytes("rank"));
            //设置一个初始化的权重值 1,仅在第一次使用的时候生效
            if(rank == null)
            	rank = Bytes.toBytes("1");
            double r = Double.parseDouble(new Text(rank).toString());

            //计算该页面给每个出链的权重值
            //获取出链个数
            int n = Bytes.toInt(value.getValue(Bytes.toBytes("page"),Bytes.toBytes("oln")));


            //如果有此内容,则用当前权重值除以当前页面出链接个数
            r = r / n;

            //设置值给outValue
            outValue.set(String.valueOf(r));

            //获取出链列表
            NavigableMap olMap = value.getFamilyMap(Bytes.toBytes("ol"));
            


            //为每一个输出的连接 分权重
            for (Entry e : olMap.entrySet()) {
            	outKey.set(e.getKey());

                //输出格式为 出链url rank
            	context.write(outKey, outValue);
            	
            }

        }

    }

    public static class PageRankReducer extends TableReducer{
        @Override
        protected void reduce(Text key, Iterable values, Context context) throws IOException, InterruptedException {
            //计算对应的页面url的权重之和
        	double sum = 0;
        	for (Text v : values) {
        		sum += Double.parseDouble(v.toString());
        		
			}



            //  由于存在一些出链为0,也就是那些不链接任何其他网页的网, 也称为孤立网页,使得很多网页能被访问到。因此需要对 PageRank公式进行修正,即在简单公式的基础上增加了阻尼系数(damping factor)q, q一般取值q=0.85。
            //
            //      其意义是,在任意时刻,用户到达某页面后并继续向后浏览的概率。 1- q= 0.15就是用户停止点击,随机跳到新URL的概率)的算法被用到了所有页面上,估算页面可能被上网者放入书签的概率。
            //
            //      最后,即所有这些被换算为一个百分比再乘上一个系数q。由于下面的算法,没有页面的PageRank会是0。所以,Google通过数学系统给了每个页面一个最小值。
            //---------------------
            //按照阻尼系数修正之后计算出该页面的权重值
        	sum = 0.15 + 0.85 * sum ;

            //构建输出的Put
        	Put put = new Put(key.getBytes());
        	

            //设置page列族 rank列 存放本次迭代获得的 权重值
        	put.addColumn(Bytes.toBytes("page"), Bytes.toBytes("rank"),
        			(new Text(String.valueOf(sum))).getBytes());
        	

            //输出数据
            context.write(NullWritable.get(),put);
        }
    }

}


最后,打成jar包,放入linux虚拟机里面运行 Hadoop jar …(jar包的名字) …( 类全名) -D table=…(输入输出的表名)

你可能感兴趣的:(#,搜索引擎制作)