首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 實作 Google PageRank 查詢與 Checksum 算法完整代碼

     編輯:關於C語言

前言

早期開發者常需從第三方網站查詢 Google PageRank (PR) 值。本文分享一個 .NET 類庫,包含 C# 與 VB.NET 兩個版本的原始碼,並附上核心的 Checksum 算法實現,方便直接整合至專案中。

功能展示

程式運行截圖如下:

Google PR 查詢示例

核心 Checksum 算法原始碼

以下為 PRCrack.PageRank.CheckSum 類別的完整實現,包含新舊版本 Toolbar 相容的計算邏輯:

using System;

namespace PRCrack
{
    /// 
    /// Google PageRank 的 Checksum 算法實現。
    /// 
    class CheckSum
    {
        public CheckSum() { }

        private const uint GOOGLE_MAGIC = 0xE6359A60;

        /// 
        /// 無符號右移輔助方法。
        /// 
        private uint ZeroFill(uint a, int b)
        {
            checked
            {
                uint z = 0x80000000;
                if (Convert.ToBoolean(z & a))
                {
                    a = (a >> 1);
                    a &= (~z);
                    a |= 0x40000000;
                    a = (a >> (b - 1));
                }
                else
                {
                    a = (a >> b);
                }
            }
            return a;
        }

        /// 
        /// 混淆運算核心。
        /// 
        private uint[] Mix(uint a, uint b, uint c)
        {
            a -= b; a -= c; a ^= (uint)(ZeroFill(c, 13));
            b -= c; b -= a; b ^= (uint)(a << 8);
            c -= a; c -= b; c ^= (uint)(ZeroFill(b, 13));
            a -= b; a -= c; a ^= (uint)(ZeroFill(c, 12));
            b -= c; b -= a; b ^= (uint)(a << 16);
            c -= a; c -= b; c ^= (uint)(ZeroFill(b, 5));
            a -= b; a -= c; a ^= (uint)(ZeroFill(c, 3));
            b -= c; b -= a; b ^= (uint)(a << 10);
            c -= a; c -= b; c ^= (uint)(ZeroFill(b, 15));
            return new uint[3] { a, b, c };
        }

        /// 
        /// 核心雜湊計算。
        /// 
        private uint GoogleCH(uint[] url, uint length, uint init)
        {
            if (length == 0) length = (uint)url.Length;
            uint a = 0x9E3779B9, b = 0x9E3779B9, c = init;
            int k = 0;
            uint len = length;
            uint[] m_mix = new uint[3];

            while (len >= 12)
            {
                a += (uint)(url[k + 0] + (url[k + 1] << 8) + (url[k + 2] << 16) + (url[k + 3] << 24));
                b += (uint)(url[k + 4] + (url[k + 5] << 8) + (url[k + 6] << 16) + (url[k + 7] << 24));
                c += (uint)(url[k + 8] + (url[k + 9] << 8) + (url[k + 10] << 16) + (url[k + 11] << 24));
                m_mix = Mix(a, b, c);
                a = m_mix[0]; b = m_mix[1]; c = m_mix[2];
                k += 12; len -= 12;
            }

            c += length;
            switch (len)
            {
                case 11: c += (uint)(url[k + 10] << 24); goto case 10;
                case 10: c += (uint)(url[k + 9] << 16); goto case 9;
                case 9: c += (uint)(url[k + 8] << 8); goto case 8;
                case 8: b += (uint)(url[k + 7] << 24); goto case 7;
                case 7: b += (uint)(url[k + 6] << 16); goto case 6;
                case 6: b += (uint)(url[k + 5] << 8); goto case 5;
                case 5: b += (uint)(url[k + 4]); goto case 4;
                case 4: a += (uint)(url[k + 3] << 24); goto case 3;
                case 3: a += (uint)(url[k + 2] << 16); goto case 2;
                case 2: a += (uint)(url[k + 1] << 8); goto case 1;
                case 1: a += (uint)(url[k + 0]); break;
            }

            m_mix = Mix(a, b, c);
            return m_mix[2];
        }

        private uint GoogleCH(string url, uint length)
        {
            uint[] m_urluint = new uint[url.Length];
            for (int i = 0; i < url.Length; i++) m_urluint[i] = url[i];
            return GoogleCH(m_urluint, length, GOOGLE_MAGIC);
        }

        private uint GoogleCH(string sURL) => GoogleCH(sURL, 0);
        private uint GoogleCH(uint[] url, uint length) => GoogleCH(url, length, GOOGLE_MAGIC);

        private uint[] C32to8bit(uint[] arr32)
        {
            uint[] arr8 = new uint[arr32.GetLength(0) * 4 + 3];
            for (int i = 0; i < arr32.GetLength(0); i++)
            {
                for (int bitOrder = i * 4; bitOrder <= i * 4 + 3; bitOrder++)
                {
                    arr8[bitOrder] = arr32[i] & 255;
                    arr32[i] = ZeroFill(arr32[i], 8);
                }
            }
            return arr8;
        }

        /// 
        /// 新版算法 (Toolbar >= 2.0.114)
        /// 
        public string CalculateChecksum(string sURL)
        {
            uint ch = GoogleCH("info:" + sURL);
            ch = (((ch / 7) << 2) | (((uint)(ch % 13)) & 7));
            uint[] prbuf = new uint[20];
            prbuf[0] = ch;
            for (int i = 1; i < 20; i++) prbuf[i] = prbuf[i - 1] - 9;
            ch = GoogleCH(C32to8bit(prbuf), 80);
            return string.Format("6{0}", ch);
        }

        /// 
        /// 舊版算法 (Toolbar < 2.0.114)
        /// 
        public string CalculateChecksumOld(string sURL)
        {
            uint ch = GoogleCH("info:" + sURL);
            return "6" + Convert.ToString(ch);
        }
    }
}

使用範例

// 取得 PageRank 值
Console.WriteLine(PRCrack.PageRank.CheckPR("https://www.google.com"));
// 取得 Checksum (1=新版, 0=舊版)
Console.WriteLine(PRCrack.PageRank.OutputCheckSum("https://www.google.com", 1));

此類庫已封裝好 CheckPR 與 OutputCheckSum 兩個靜態方法,可直接呼叫。注意:Google 已停止公開 PageRank 服務,此代碼僅供學習算法原理參考。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved