程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#完成百度網站收錄和排名查詢功效思緒及實例

C#完成百度網站收錄和排名查詢功效思緒及實例

編輯:C#入門知識

C#完成百度網站收錄和排名查詢功效思緒及實例。本站提示廣大學習愛好者:(C#完成百度網站收錄和排名查詢功效思緒及實例)文章只能為提供參考,不一定能成為您想要的結果。以下是C#完成百度網站收錄和排名查詢功效思緒及實例正文


1、媒介

有時一次在vs2012默許的項目文件夾裡發明了之前本身做的一個關於SEO的類庫,重要是用來查詢某個網址的收錄次數還有網站的排行數,後來重構了下,明天拿出來寫篇文章,說說本身是若何思慮的並完成的。

2、成績描寫

起首須要斟酌的是可以或許支撐哪些搜刮引擎的查詢,起首是百度,然後是必應、搜狗、搜搜、360。原來想支撐Google然則一想纰謬,基本欠好拜訪的,所以臨時不算在內。而我們現實要做的就是依據一個網址可以或許檢索出這個網址的在各個搜刮引擎的收錄次數和在分歧症結詞下的網址排行,這裡收支的只要網址還有若干的症結詞,而輸入則是該網址在分歧搜刮引擎下的收錄次數和在各個症結詞下的排行數。

然則這裡有個成績,就是排行數,假如檢索的網址在前100還好,假如排名很前面,那末成績就來了,那樣會讓用戶期待很長時光能力看到成果,然則用戶能夠只想曉得排行前100的詳細排名,而那些跨越的則只需顯示100今後便可以了,而這些就須要我們後期斟酌好,如許前面的法式才好做。

3、處理思緒

信任許多人都可以或許想到,就是應用WebClient將將須要的頁面下載上去,然後用正則從中獲得我們感興致的部門,然後應用法式行止理。而症結難度就是在這個正則的編寫,起首我們先從簡略的開端。

4、收錄次數

起首是網站的收錄次數,我們可以在百度中輸出site:www.cnblogs.com/然後我們便可以看到以下的頁面:

而我們所須要的收錄次數就是 5,280,000 這段數字,我們接著檢查頁面元素:

接著我們再不雅察其他的搜刮引擎可以發明都是相似的,所以我們的思緒這個時刻應當就得出了,最初就是若何組織網址,這部門我們看地址欄?wd=site%3Awww.cnblogs.com%2F這段就曉得怎樣寫了。

稍等這個時刻我們能夠心急一個一個完成,如許前面我們就沒法集中的挪用,同時也會影響今後的新增,所以我們要劃定一個要完成收錄數功效的籠統類,如許就可以夠在不知曉詳細完成的情形同一應用,而且還可以或許在今後輕松的新增新的搜刮引擎,而這類方法屬於戰略形式(Stategry),上面我們來漸漸剖析出這個籠統類的詳細內容。

起首每一個完成這個籠統類的詳細類都應當是對應某個搜刮引擎,那末就須要有一個根本網址,同時還要留下占位符,好比依據下面百度的這個我們就得出如許一個字符串

http://www.百度.com/s?wd=site%3A{0}

個中{0}就是為真正須要檢索網址的占位符,獲得下載頁面的途徑是一切詳細類都須要的所以我們直接將完成放在籠統類中,好比上面的代碼:


/// <summary>
        /// 辦事供給者
        /// </summary>
        protected String SearchProvider { get; set; }

        /// <summary>
        /// 須要檢索的網址
        /// </summary>
        protected String SiteUrl { get; set; }

        /// <summary>
        /// 搜刮辦事供給網址
        /// </summary>
        protected String BaseUrl { get; set; }

        /// <summary>
        /// 後頁面網址
        /// </summary>
        /// <param name="site">須要查詢的網址</param>
        /// <returns>拼接後的網址</returns>
        protected String GetDownUrl(string site)
        {
            return string.Format(BaseUrl, HttpUtility.UrlEncode(site));
        }

個中SiteUrl和SearchProvider是用來保留檢索網址和搜刮引擎稱號。

下面我們說了將會應用WebClient來下載頁面,所以初始化WebClient的任務也在籠統類中完成,盡量的削減反復代碼,而為了避免壅塞以後線程所以我們采取了Async辦法。

詳細代碼以下所示:

/// <summary>
        /// 查詢在該搜刮引擎中的收錄次數
        /// </summary>
        /// <param name="siteurl">網站URL</param>
        public void SearchIncludeCount(string siteurl)
        {
            SiteUrl = siteurl;
            WebClient client = new WebClient();
            client.Encoding = Encoding.UTF8;
            client.DownloadStringCompleted += DownloadStringCompleted;
            client.DownloadStringAsync(new Uri(GetDownUrl(siteurl)));
        }

        /// <summary>
        /// 檢索收錄次數的詳細完成
        /// 子類必需要完成該辦法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected abstract void DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e);

當WebClient完成下載後將會回調DownloadStringCompleted辦法,而這個辦法的是籠統辦法也就意味著詳細類必需要完成這個辦法。

固然我們外部的完成是異步的然則關於其他開辟者挪用這個辦法照樣同步的,所以我們就須要借助拜托是以我們還要新建一個拜托類型:

/// <summary>
        /// 當完成一個網站的收錄查詢後回調
        /// </summary>
        public Action<SiteIncludeCountResult> OnComplatedOneSite { get; set; }

個中SiteIncludeCountResult的構造以下所示:


/// <summary>
    /// 用於網站收錄中拜托的參數
    /// </summary>
    public class SiteIncludeCountResult
    {
        /// <summary>
        /// 收錄次數
        /// </summary>
        public long IncludeCount { get; set; }

        /// <summary>
        /// 搜刮引擎類型
        /// </summary>
        public String SearchType { get; set; }

        /// <summary>
        /// 網站URL
        /// </summary>
        public String SiteUrl { get; set; }
}

最初還有一個辦法用於DownloadStringCompleted完成後回調OnComplatedOneSite拜托:
        /// <summary>
        /// 完成處置後挪用該辦法將成果前往
        /// </summary>
        /// <param name="result">網址的收錄數成果</param>
        protected void SetCompleted(SiteIncludeCountResult result)
        {
            if (OnComplatedOneSite != null)
                OnComplatedOneSite(result);
        }

如許我們須要的籠統類就完成了,上面我們便可以開端完成第一個了,經由過程下面的截圖我們可以發明要婚配這段字符串的正則表達式很簡略:

百度為您找到相干成果約([\w,]+?)個

最初再將獲得的字符串去失落逗號便可以強迫轉換了,如許成果就出來了,詳細完成就像上面如許:

/// <summary>
    /// 百度網站收錄次數查詢
    /// </summary>
    public class BaiDuSiteIncludeCount : SiteIncludeCountBase
    {
        public BaiDuSiteIncludeCount()
        {
            BaseUrl = "http://www.百度.com/s?wd=site%3A{0}";
            SearchProvider = "百度";
        }

        protected override void DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            var result = new SiteIncludeCountResult();
            result.SiteUrl = SiteUrl;
            result.SearchType = SearchProvider;
            result.IncludeCount = 0;
            Regex reg = new Regex(@"百度為您找到相干成果約([\w,]+?)個", RegexOptions.IgnoreCase | RegexOptions.Singleline);
            var matchs = reg.Matches(e.Result);
            if (matchs.Count > 0)
            {
                string count = matchs[0].Groups[1].Value.WordStr(",", "");
                result.IncludeCount = long.Parse(count);
            }
            SetCompleted(result);
        }
}

以此類推,其他的都是依照這類便可以了,有興致的可以下載我的源碼檢查。

5、症結詞排名

我們依照之前的思緒,照樣要先劃定一個籠統類,然則其構造跟下面的籠統類很類似,所以筆者這裡直接給出詳細的代碼:

/// <summary>
    /// 完成症結詞查詢必需繼續該類
    /// </summary>
    public abstract class KeyWordsSeoBase
    {
        protected String BaseUrl { get; set; }

        protected String SearchProvider { get; set; }

        protected String GetDownUrl(string keyword, string site, long current)
        {
            return String.Format(BaseUrl, HttpUtility.UrlEncode(keyword), current);
        }

        protected void SetCompleted(KeyWordsSeoResult result)
        {
            if (OnComplatedOneKeyWord != null)
            {
                OnComplatedOneKeyWord(result);
            }
        }

        /// <summary>
        /// 完成一個症結詞的查詢後回調該拜托
        /// </summary>
        public Action<KeyWordsSeoResult> OnComplatedOneKeyWord { get; set; }

        /// <summary>
        /// 查詢指定症結詞和網站在該搜刮引擎中的排行
        /// 子類須要重寫該辦法
        /// </summary>
        /// <param name="keywords">症結詞</param>
        /// <param name="site">網站URL</param>
        public abstract void SearchRanking(IEnumerable<string> keywords, string site,long count);
}

最年夜的差別在於詳細的完成全體集中在SearchRanking中,經由過程keywords參數可以看出我們會支撐多個症結詞的查詢,最初分歧的就是下載途徑的組織,由於觸及到翻頁所以多了一個參數。

個中KeyWordsSeoResult的構造以下所示:

/// <summary>
    /// 用於症結詞排行查詢的拜托參數
    /// </summary>
    public class KeyWordsSeoResult
    {
        /// <summary>
        /// 搜刮引擎類型
        /// </summary>
        public String SearchType { get; set; }

        /// <summary>
        /// 症結詞
        /// </summary>
        public String KeyWord { get; set; }

        /// <summary>
        /// 排行
        /// </summary>
        public long Ranking { get; set; }
    }

空話不多說,我們來看百度的搜刮成果頁:

以上是筆者在百度中搜刮法式員的排名第九個的html構造,也許你會認為很簡略只需獲得div的id和網址便可以了,然則許多搜刮引擎的途徑其實不是直接的途徑,而是會先鏈到百度然後重定向的,假如非要婚配我們就須要多做一件事就是拜訪這個途徑獲得真實的途徑,那樣就會加年夜這中央的期待時光,所以筆者采取的是直接截取上圖中的<span class=”g”>前面的內容,如許就防止了一次要求。(不曉得現在筆者怎樣想的,完成的時刻並沒有采取id誰人值而是在外部遞增,估量這個id的序號在翻頁後會湧現成績吧),最初亮出我們神聖的正則表達式:

<span\s+class=""(?:g|c-showurl)"">([^/&]*)

認為如許就年夜通知布告成了?錯了,在某些成果外面百度會給這個網址加上b標簽,而筆者則采取全體斬草除根的方法,應用正則全體刪失落(橫豎又不看頁面,只需拿到我想要的就OK了),完成的時刻我們可不克不及直接完成多個症結詞的判明,應當是完成一個症結詞的,然後輪回挪用便可了,上面是筆者的單個症結詞的完成:

protected KeyWordsSeoResult SearchFunc(string key, string siteurl, long total)
        {
            var result = new KeyWordsSeoResult();
            result.KeyWord = key;
            result.Ranking = total + 1;
            var reg = new Regex(@"<span\s+class=""(?:g|c-showurl)"">([^/&]*)", RegexOptions.IgnoreCase | RegexOptions.Singleline);
            var replace = new Regex("</?b>", RegexOptions.IgnoreCase | RegexOptions.Singleline);
            var client = new WebClient();
            long current = 0;
            long pos = 0;
            for (; ; )
            {
                String url = GetDownUrl(key, siteurl, current);
                String downstr = client.DownloadString(url);
                downstr = replace.WordStr(downstr, "");
                var matchs = reg.Matches(downstr);
                foreach (Match match in matchs)
                {
                    pos++;
                    string suburl = match.Groups[1].Value;
                    try
                    {
                        if (suburl.ToLower() == siteurl.ToLower())
                        {
                            result.Ranking = pos;
                            return result;
                        }
                    }
                    catch
                    {
                        continue;
                    }
                }
                current += 10;
                if (current > total)
                {
                    current -= 10;
                    if (current >= total)
                    {
                        break;
                    }
                    current = total;
                }
            }
            return result;
        }

 留意for輪回的停止部門,這裡是用來處置分頁的,以翻到下一頁持續檢索。其他的年夜體部門都跟筆者說的一樣,下載頁面->正則婚配->依據婚配成果斷定。剩下的就是SearchRanking的完成,就是輪回症結詞,只是這裡筆者為每一個搜刮引擎新建線程來完成,固然這不怎樣好,所以讀者可以改用更好的方法來做:

 
 public override void SearchRanking(IEnumerable<string> keywords, string site, long count)
        {
            new Thread(() =>
            {
                foreach (string key in keywords)
                {
                    KeyWordsSeoResult result = SearchFunc(key, site, count);
                    result.SearchType = SearchProvider;
                    SetCompleted(result);
                }
            }).Start();
        }
 

6、同一治理

有了這些我們便可以寫出一個簡練的類來擔任治理,筆者這裡直接給出代碼:

/// <summary>
    /// 查詢網站的收錄次數和排行
    /// </summary>
    public class RankingAndIncludeSeo
    {
        /// <summary>
        /// 症結詞列表
        /// </summary>
        public IList<KeyWordsSeoBase> KeyWordsSeoList { get; private set; }
       
        /// <summary>
        /// 收錄次數列表
        /// </summary>
        public IList<SiteIncludeCountBase> SiteIncludeCountList { get; private set; }

        public RankingAndIncludeSeo()
        {
            KeyWordsSeoList = new List<KeyWordsSeoBase>();
            SiteIncludeCountList = new List<SiteIncludeCountBase>();
        }

        /// <summary>
        /// 當完成一個症結詞的查詢後回調該拜托
        /// </summary>
        public Action<KeyWordsSeoResult> OnComplatedAnyKeyWordsSearch { get; set; }

        /// <summary>
        /// 當完成一個網站的收錄次數查詢後回調該拜托
        /// </summary>
        public Action<SiteIncludeCountResult> OnComplatedAnySiteIncludeSearch { get; set; }

        /// <summary>
        /// 查詢網址的排行
        /// </summary>
        /// <param name="keywords">症結詞組</param>
        /// <param name="siteurl">查詢的網址</param>
        /// <param name="count">最年夜限制排行數</param>
        public void SearchKeyWordsRanking(IEnumerable<string> keywords, string siteurl, long count = 100)
        {
            if (keywords == null)
                throw new ArgumentNullException("keywords", "必需存在症結詞");
            if (siteurl == null)
                throw new ArgumentNullException("siteurl", "必需存在網站URL");
            foreach (KeyWordsSeoBase kwsb in KeyWordsSeoList)
            {
                kwsb.OnComplatedOneKeyWord = kwsb.OnComplatedOneKeyWord ?? OnComplatedAnyKeyWordsSearch;
                kwsb.SearchRanking(keywords, siteurl, count);
            }
        }

        /// <summary>
        /// 查詢網址的收錄次數
        /// </summary>
        /// <param name="siteurl">查詢的網址</param>
        public void SearchSiteIncludeCount(string siteurl)
        {
            if (siteurl == null)
                throw new ArgumentNullException("siteurl", "必需指定網站");
            foreach (SiteIncludeCountBase sicb in SiteIncludeCountList)
            {
                sicb.OnComplatedOneSite = sicb.OnComplatedOneSite ?? OnComplatedAnySiteIncludeSearch;
                sicb.SearchIncludeCount(siteurl);
            }
        }
}

RankingAndIncludeSeo中供給了公共的拜托,假如單個搜刮引擎沒有供給拜托那末就采取這個公共的,假如曾經指定了零丁的拜托就不會被賦值了,而其他開辟者挪用的時刻只需向KeyWordsSeoList和SiteIncludeCountList中添加曾經完成的類便可以了,方面其他開辟者開辟出本身的完成並參加個中。

7、末節

這篇漫筆總的來講其實不是講述甚麼高端技巧的,僅僅只是供給一種年夜致的思緒和構造上的設計,假如讀者須要運用於現實開辟中,最好加以驗證,筆者其實不能包管症結詞的排名沒有任何誤差,由於搜刮的成果會因為任何身分產生轉變。

^.^我是源碼下載

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved