您的位置:首页 > 编程语言 > Java开发

PageRank的初步理解和实践

2016-05-27 17:35 603 查看
关于PageRank,先看看百度百科上的说明:

PageRank,网页排名,又称网页级别、Google左侧排名或佩奇排名,是一种由[1] 根据网页之间相互的超链接计算的技术,而作为网页排名的要素之一,以Google公司创办人拉里·佩奇(Larry
Page)之姓来命名。Google用它来体现网页的相关性和重要性,在搜索引擎优化操作中是经常被用来评估网页优化的成效因素之一。Google的创始人拉里·佩奇和谢尔盖·布林于1998年在斯坦福大学发明了这项技术。

PageRank通过网络浩瀚的超链接关系来确定一个页面的等级。Google把从A页面到B页面的链接解释为A页面给B页面投票,Google根据投票来源(甚至来源的来源,即链接到A页面的页面)和投票目标的等级来决定新的等级。简单的说,一个高等级的页面可以使其他低等级页面的等级提升。

简而言之PageRank作为主流链接分析模型 提供了以下功能:

独立于查询(query-independence) 

有效防止网页欺骗

关于PageRank的基本思想,PageRank将 网页x指向网页y的链接视为x给y的一张投票。 然而PageRank 不仅仅考虑网页得票的绝对数目,它还分析投票者本身的权威性. 来自权威网页的投票能够提升被投票网页的权威性。链接是源网页对目标网页权威性的隐含表达. 网页i的入边(in-links)越多,表示i的权威性值越高。指向网页i的网页本身也有自己的权威性值对于网页i的权威性得分而言,一个具有高分值的源网页比一个低分值的源网页更加重要。换言之,若其它权威性网页指向网页i,则i也可能是权威性网页。 

网页i的权威性得分 (即i的 PageRank 值,用P(i)表示) 定义为所有指向i的网页的PageRank值之和。既然一个网页可能指向多个网页,因此它的值应该被其指向的多个网页所共享。 把Web视为一个有向图 G = (V,
E),其中V表示顶点集合(即网页集合),一条有向边(i, j) E当且仅当网页i指向网页j,n为总的网页数。但是因为许多网页没有出边(没有指向外部网页的链接),而用户也不会因为这个网页没有指向其他页面的url就停止访问,所以,我们应当再添加一个参数d(阻尼因子),这是个概率,即,用户有d的可能性在浏览这个网页时在地址输入栏输入其他地址而不是按照网页上提供的地址继续访问。

综上得出的每个网页i 的PageRank分值为 :



其中A为网页的概率转移矩阵,以下是实现的伪代码:



大概了解了PageRank的思想,接下来来试试如何实现。以下是我自己在做这个的实现过程:

1.   实现爬虫,以爬取网页内容。
维护一个队列,其中是从网页中爬取到的未访问的URL
每次从中取出一个访问,并将其中的信息存到对应的类队列中等待下一步使用
 
2.   将爬虫获取到的数据表转化为一个邻接矩阵,进行PageRank算法计算:
(1-d)E/n + dAT是一个随机矩阵,同时满足不可约和非周期性
•    令 eTP=n,则等价于:



(这段用图片代替)

3.   绘制图形
将每个web类作为一个点,围绕一个中心点,以固定半径按照顺序绘制图形。生成web邻接矩阵图图。如下,这是1000个网页所生成的图。



实现代码:
目录结构:



package count;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.text.DecimalFormat;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
/*
* code by 邦柳
* 画图类
* */
public class Draw {
public Graphics2D graphics;
public BufferedImage image;
//构造函数
public Draw(){
image = new BufferedImage(DrawSet.Width,DrawSet.Height,BufferedImage.TYPE_INT_BGR);
graphics = (Graphics2D)image.getGraphics();
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Font font=new Font(DrawSet.Font,Font.BOLD,DrawSet.FontSize);
graphics.setFont(font);
graphics.setColor(Color.WHITE) ;
graphics.fillRect(0, 0, DrawSet.Width, DrawSet.Height) ;
graphics.setColor(Color.BLACK);
float thick=DrawSet.LineTrick;
graphics.setStroke(new BasicStroke(thick, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND));
}

//基于起点x1.y1,终点,x2,y2画一条线
public void drawLine(double x1,double y1,double x2,double y2){
double x = x1-x2;
double y = y1-y2;
Line2D line = new Line2D.Double(x1,y1,x2,y2);
graphics.draw(line);
}

//绘制点
public void drawPoint(int order,double x, double y) {
float xx = (float) ((float)(x-DrawSet.CenterX)*DrawSet.FontDistance+DrawSet.CenterX);
float yy = (float) ((float)(y-DrawSet.CenterY)*DrawSet.FontDistance+DrawSet.CenterY);
graphics.drawString(String.valueOf(order),xx,yy);
}
//绘制点,重载
public void drawPoint(int order,double pageRank,double x, double y) {
float xx = (float) ((float)(x-DrawSet.CenterX)*DrawSet.FontDistance+DrawSet.CenterX);
float yy = (float) ((float)(y-DrawSet.CenterY)*DrawSet.FontDistance+DrawSet.CenterY);
graphics.drawString(String.valueOf(order),xx,yy);
DecimalFormat df = new DecimalFormat("#0.00");
xx = (float) ((float)(x-DrawSet.CenterX)*DrawSet.PageRankDistance+DrawSet.CenterX);
yy = (float) ((float)(y-DrawSet.CenterY)*DrawSet.PageRankDistance+DrawSet.CenterY);
graphics.drawString(df.format(pageRank),xx,yy);
}
//执行画图的初始化
public void createImage(String fileLocation) {
try {
FileOutputStream fos = new FileOutputStream(fileLocation);
BufferedOutputStream bos = new BufferedOutputStream(fos);
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(bos);
encoder.encode(image);
bos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
//参数配置完毕,执行画图
public void over(){
graphics.dispose();
createImage(DrawSet.WebPicture);
}
//将需要画图的参数传入
public void drawPic(int len,PageRankEntity page){
System.out.println("get into draw");
double diameter=2000;
double w=3000;
double h=3000;
double x[]=new double [len+1];
double y[]=new double [len+1];

for(int i = 0;i<len;i++){
double ii = 0.36*i;
x[i] = Math.cos(ii)*diameter+w;
y[i] = Math.sin(ii)*diameter+h;
}

for(int i =0;i<len;i++){
for(int j1=0;j1<len;j1++){
if(page.num[i][j1]!=0) {
if(i!=j1) {
drawLine(x[i],y[i],x[j1],y[j1]);
}
}
}
}
for(int i = 0;i<len;i++){
int point = i;
drawPoint(i+1,page.v[i],x[point],y[point]);
//找到那一点的坐标标上i+1
}
over();

}

}

package count;
/*
* code by 邦柳
* 画图所使用到的参数
* */
public class DrawSet {
public final static int Width = 6000;
public final static int Height = 6000;
public final static int CenterX = Width/2;
public final static int CenterY = Height/2;
public final static double Diameter = 3000;
public final static float LineTrick = 1.0f;//0.3f
public final static int FontSize = 10;
public final static String Font = "Times New Roman";
public final static double FontDistance = 1.05;
public final static double PageRankDistance = 1.1;
public final static String WebPicture = "result.png";
}

package count;

import java.util.ArrayList;

import craw.WebEntity;

public class PageRankEntity {
public double num[][];				//邻接矩阵
public double A_T[][];				//概论矩阵
public double v[];					//pagerank向量

private double d;					//阻尼因子
private int length;					//数据长度
private double e[];					//E向量
public double getD() {
return d;
}
public void setD(double d) {
this.d = d;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public double[][] getNum() {
return num;
}
public void setNum(double[][] num) {
this.num = num;
}
//初始化数据
public PageRankEntity(int len){
this.num=new double [len+1][len+1];
this.A_T=new double [len+1][len+1];
this.d=0.85;
this.length=len+1;
this.v=new double[len+1];
this.e=new double[len+1];

for(int i=0;i<len+1;i++){
v[i]=(double)(1.0/len);
e[i]=(double)(1.0/len);
}
for(int i=0;i<len+1;i++){
for(int j=0;j<len+1;j++)
num[i][j]=0;
}
}
//为概论矩阵赋值
public void giveA_T(){
double count=0;
for(int i=0;i<length;i++){
for(double t:num[i]){
if(t==1)
count++;
}
for(int j=0;j<length;j++){
if(num[i][j]==1)
A_T[j][i]=num[i][j]/count;
else
A_T[j][i]=0;
}
count=0;
}
}

public void showNum(){
for(int i=0;i<length;i++){
for(int j=0;j<length;j++){
System.out.print(num[i][j]+" ");
}
System.out.println("");
}
}
public void showA_T(){
for(int i=0;i<length;i++){
for(int j=0;j<length;j++){
System.out.print(A_T[i][j]+" ");
}
System.out.println("");
}
}
//计算pageRank的值
public void alg(){
double tmp_V[]=new double[length];
double sum_aNV=0;
double sum_aE=0;
double sum_tmp=100;
while(sum_tmp>0.001){
System.arraycopy(v, 0, tmp_V, 0, length);

for(int i=0;i<length;i++){
sum_aNV=0;
sum_aE=0;
sum_tmp=0;
for(int j=0;j<length;j++){
sum_tmp+=(A_T[i][j]*tmp_V[j]);
}
sum_aNV=sum_tmp*d;
sum_aE=(1-d)*e[i];

v[i]=sum_aNV+sum_aE;

}
sum_tmp=0;
for(int i=0;i<length;i++){
sum_tmp+=Math.abs(tmp_V[i]-v[i]);
}

}
}
public void show_V(ArrayList<WebEntity> retList){
for(int i=0;i<length-2;i++){
System.out.print(retList.get(i).Url.toString()+"  PageRank:");
System.out.println(v[i]);
}

}
public void sort_v(){
double tmp=0;int pos=0;
for(int i=0;i<length;i++){
pos=i;
for(int j=i+1;j<length;j++){
if(v[pos]<v[j])
pos=j;
}
if(pos!=i){
tmp=v[pos];
v[pos]=v[i];
v[i]=tmp;
}
}
}
//执行函数的集成
public void PageRank(){
giveA_T();
alg();

sort_v();
System.out.println("sort the pagerank");
}
}

package craw;

import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.GetMethod;
/*
* code by 邦柳
* 爬虫主体类
* */
public class Spider {
/*
* 用于匹配的正则
* */
public static String getUrl_question="question_link.+?href=\"(.+?)\"";
public static String getUrl_content="content.+?href=\"(.+?)\"";
public static String getUrl_visible="visible-expanded.+?href=\"(.+?)\"";
public static String getUrl_author="author-link.+?href=\"(.+?)\"";
public static String getUrl_editable="zm-editable-content.+?href=\"(.+?)\"";
//get请求
public String SendGet_client(String url)
{
//System.out.println("spider(20) get info from:"+url);

String ret="";

try {
HttpClient client=new HttpClient();
HttpMethod method=new GetMethod(url);
client.executeMethod(method);
int code=method.getStatusCode();
if(code==200)
ret=method.getResponseBodyAsString();
else
ret="400";
} catch (Exception e) {
// TODO: handle exception
System.out.println("function:SendGet_client error in class Spider");
e.printStackTrace();
}
return ret;
}
//执行队列,并获取web中的内容
public  ArrayList<WebEntity> getWebList(String url){
int times=0;

ArrayList<WebEntity> retList=new ArrayList<WebEntity>();
ArrayList<String> webUrlList=new ArrayList<String>();
//init
SpiderQueue queue=new SpiderQueue();

queue.addUnvisitedUrl(url);
//timse次数为所要访问的页面数量
while(!queue.unVisitedUrlsEmpty()&×<=1000){

url=(String)queue.unVisitedUrlDequeue();

String content=SendGet_client(url);
if(content.equals("400"))
continue;

queue.addVisiteUrl(url);

webUrlList.addAll(getWebUrl(content,getUrl_question));
webUrlList.addAll(getWebUrl(content,getUrl_author));
webUrlList.addAll(getWebUrl(content,getUrl_content));
webUrlList.addAll(getWebUrl(content,getUrl_editable));
webUrlList.addAll(getWebUrl(content,getUrl_visible));
WebEntity tmp=new WebEntity(url);

for(String urlTmp:webUrlList){
queue.addUnvisitedUrl(urlTmp);
tmp.addOutUrl(urlTmp);
}
retList.add(tmp);
System.out.println("times is :"+times++);
webUrlList.clear();
}
webUrlList.clear();
return retList;
}
//获取web中的url
public ArrayList<String> getWebUrl(String content,String reg){
ArrayList<String> urlList=new ArrayList<String>();

Pattern p=Pattern.compile(reg);
Matcher m=p.matcher(content);
while(m.find())
{
if(m.group(1).indexOf("http")>=0){
urlList.add(m.group(1));
//System.out.println("spider(97) get:"+m.group(1));
}
else{
urlList.add("http://www.zhihu.com"+m.group(1));
//System.out.println("spider(97) get:http://www.zhihu.com"+m.group(1));
}

}

return urlList;
}
//传入的url是否存在于retLIst中
public int webUrlContain(ArrayList<WebEntity> retList,String url){
int count=-1,len=retList.size();
for(int i=0;i<len;i++){
if(retList.get(i).getUrl().equals(url)){
count=i;
break;
}
}

return count;

}
}

package craw;

import java.util.HashSet;
import java.util.Set;
/*
* code by 邦柳
*
* 爬虫主体队列
* */
public class SpiderQueue {
private static Set<Object>visitedUrl=new HashSet<>();
private static WebQueue unVisitedUrl=new WebQueue();
public  void addVisiteUrl(String Url){
visitedUrl.add(Url);
}
public  void removeVisitedUrl(String url){
visitedUrl.remove(url);
}
public  int getVisitedUrlNum(){
return visitedUrl.size();
}
public  Object unVisitedUrlDequeue(){
return unVisitedUrl.deQueue();
}
public  void addUnvisitedUrl(String url){
if(url!=null&&!url.trim().equals("")&&!visitedUrl.contains(url)
&&!unVisitedUrl.contians(url)){
unVisitedUrl.enQueue(url);
//System.out.println("spiderQueue add to list success:"+url);
}
else if(url==null){
//System.out.println("spiderQueue url=null");
}
else if(url.trim().equals("")){
//System.out.println("spiderQueue url equals null");
}
else if(visitedUrl.contains(url)){
//System.out.println("spiderQueue vistedList alearld have");
}
else if(unVisitedUrl.contians(url)){
//System.out.println("spiderQueue unVisitedList alearld have");
}
else
System.out.println("spiderQueue something happened");

}
public  boolean unVisitedUrlsEmpty(){
return unVisitedUrl.empty();
}
public int getUnVisitedUrlNum(){
return unVisitedUrl.getNum();
}
}

package craw;

import java.util.ArrayList;
/*
* code by 邦柳
*
* web页面对应类
* */
public class WebEntity {

public ArrayList<String> outUrl;
public String Url;

public String getUrl() {
return Url;
}
public void setUrl(String url) {
Url = url;
}
public WebEntity(String url){
outUrl=new ArrayList<String>();
Url=url;

}

public int outUrlNum(){
return outUrl.size();
}

public void addOutUrl(String url){
outUrl.add(url);
}

public boolean outContians(String url){
return outUrl.contains(url);
}
}

package craw;

import java.util.LinkedList;
/*
* code by 邦柳
*
* 爬虫的队列
* */
public class WebQueue {
private LinkedList<Object>queue=new LinkedList<Object>();
public void enQueue(Object t){
queue.addLast(t);
}
public Object deQueue(){
return queue.removeFirst();
}
public boolean isQueueEmpty(){
return queue.isEmpty();
}
public boolean contians(Object t){
return queue.contains(t);
}
public boolean empty(){
return queue.isEmpty();
}
public int getNum(){
return queue.size();
}
}


package mian;

import java.util.ArrayList;

import count.Draw;
import count.PageRankEntity;
import craw.Spider;
import craw.WebEntity;
/*
* code by 邦柳
*
* */
public class Main {

public static void main(String[] args) {
// TODO Auto-generated method stub
String url="http://www.zhihu.com/explore/recommendations";
Draw draw=new Draw();
Spider spider=new Spider();
//获取地址集
ArrayList<WebEntity> retList=new ArrayList<WebEntity>();
retList.addAll(spider.getWebList(url));

int len=retList.size();

PageRankEntity page=new PageRankEntity(len+1);

//生成对应矩阵
int j=0;
for(int i=0;i<len;i++){
System.out.println(retList.get(i).Url);
for(String s:retList.get(i).outUrl){
j=spider.webUrlContain(retList, s);
if(j!=-1){
//System.out.println("get page");
page.num[i][j]=(double)1;
}

}
}

page.PageRank();
draw.drawPic(len, page);
page.show_V(retList);

System.out.println("PROGRAM END");

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 爬虫 PageRank