亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C# > 正文

C#實現百度網站收錄和排名查詢功能思路及實例

2020-01-24 02:09:41
字體:
來源:轉載
供稿:網友

一、前言

偶然一次在vs2012默認的項目文件夾里發現了以前自己做的一個關于SEO的類庫,主要是用來查詢某個網址的收錄次數還有網站的排行數,后來重構了下,今天拿出來寫篇文章,說說自己是如何思考的并完成的。

二、問題描述

首先需要考慮的是能夠支持哪些搜索引擎的查詢,首先是百度,然后是必應、搜狗、搜搜、360。本來想支持Google但是一想不對,根本不好訪問的,所以暫時不算在內。而我們實際要做的就是根據一個網址能夠檢索出這個網址的在各個搜索引擎的收錄次數以及在不同關鍵詞下的網址排行,這里出入的只有網址還有若干的關鍵詞,而輸出則是該網址在不同搜索引擎下的收錄次數以及在各個關鍵詞下的排行數。

但是這里有個問題,就是排行數,如果檢索的網址在前100還好,如果排名很后面,那么問題就來了,那樣會讓用戶等待很長時間才能看到結果,但是用戶可能只想知道排行前100的具體排名,而那些超過的則只要顯示100以后就可以了,而這些就需要我們前期考慮好,這樣后面的程序才好做。

三、解決思路

相信很多人都能夠想到,就是利用WebClient將將需要的頁面下載下來,然后用正則從中獲取我們感興趣的部分,然后利用程序去處理。而關鍵難度就是在這個正則的編寫,首先我們先從簡單的開始。

四、收錄次數

首先是網站的收錄次數,我們可以在百度中輸入site:www.cnblogs.com/然后我們就可以看到如下的頁面:

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

接著我們再觀察其他的搜索引擎可以發現都是類似的,所以我們的思路這個時候應該就得出了,最后就是如何組織網址,這部分我們看地址欄?wd=site%3Awww.cnblogs.com%2F這段就知道怎么寫了。

稍等這個時候我們可能心急一個一個實現,這樣后面我們就沒法集中的調用,同時也會影響以后的新增,所以我們要規定一個要實現收錄數功能的抽象類,這樣就能夠在不知曉具體實現的情況統一使用,并且還能夠在以后輕松的新增新的搜索引擎,而這種方式屬于策略模式(Stategry),下面我們來慢慢分析出這個抽象類的具體內容。

首先每個實現這個抽象類的具體類都應該是對應某個搜索引擎,那么就需要有一個基本網址,同時還要留下占位符,比如根據上面百度的這個我們就得出這樣一個字符串

http://www.baidu.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.baidu.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.Replace(",", "");
                result.IncludeCount = long.Parse(count);
            }
            SetCompleted(result);
        }
}

以此類推,其他的都是按照這種就可以了,有興趣的可以下載我的源碼查看。

五、關鍵詞排名

我們按照之前的思路,還是要先規定一個抽象類,但是其結構跟上面的抽象類很相似,所以筆者這里直接給出具體的代碼:

復制代碼 代碼如下:

/// <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.Replace(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();
        }
 

六、統一管理

有了這些我們就可以寫出一個簡潔的類來負責管理,筆者這里直接給出代碼:

復制代碼 代碼如下:

/// <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中添加已經實現的類就可以了,方面其他開發者開發出自己的實現并加入其中。

七、小節

這篇隨筆總的來說并不是講述什么高端技術的,僅僅只是提供一種大致的思路以及結構上的設計,如果讀者需要應用于實際開發中,最好加以驗證,筆者并不能保證關鍵詞的排名沒有任何誤差,因為搜索的結果會由于任何因素發生改變。

^.^我是源碼下載

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
不卡伊人av在线播放| 91精品国产网站| 午夜剧场成人观在线视频免费观看| yellow中文字幕久久| 精品欧美激情精品一区| 欧美大胆在线视频| 亚洲男人的天堂在线| 亚洲精品成人久久久| 欧美成人精品三级在线观看| 欧美激情精品久久久| 午夜精品福利在线观看| 亚洲欧美国产精品久久久久久久| 日韩在线视频观看正片免费网站| 亚洲精品福利视频| 欧美日韩一区二区精品| 午夜精品福利电影| 青青青国产精品一区二区| 中文字幕在线精品| 国产欧美日韩精品丝袜高跟鞋| 亚洲精品小视频在线观看| 亚洲精品aⅴ中文字幕乱码| 在线视频日韩精品| 亚洲精品午夜精品| 欧美另类精品xxxx孕妇| 亚洲加勒比久久88色综合| 日韩在线不卡视频| 久久精品久久久久久国产 免费| 国产精品视频永久免费播放| 欧美成人免费在线视频| 久久久91精品国产一区不卡| 欧美另类高清videos| 亚洲欧美激情四射在线日| 精品无人国产偷自产在线| 深夜精品寂寞黄网站在线观看| 精品偷拍一区二区三区在线看| 欧美午夜久久久| 日韩毛片在线观看| 国产欧美日韩视频| 色综合天天狠天天透天天伊人| 97久久超碰福利国产精品…| 亚洲va欧美va在线观看| 国产一区二区三区在线免费观看| 国产精品久久视频| 亚洲中国色老太| 欧美日韩国产精品| 午夜精品福利电影| 亚洲国产精品一区二区久| 一区二区三区四区精品| 伊人成人开心激情综合网| 国产精品影片在线观看| 久久91亚洲精品中文字幕| 成人精品网站在线观看| 亚洲欧洲国产一区| 亚洲**2019国产| 97人人做人人爱| 日韩一区二区三区xxxx| 国产精品扒开腿做爽爽爽的视频| 2019精品视频| 亚洲码在线观看| 日韩毛片中文字幕| 欧美性生活大片免费观看网址| 亚洲乱码国产乱码精品精| 国产欧美日韩亚洲精品| 国产精品老牛影院在线观看| 日本一区二区在线播放| 亚洲精品国产综合久久| 日韩视频免费在线观看| 高清一区二区三区四区五区| 丝袜美腿亚洲一区二区| 91精品啪在线观看麻豆免费| 91极品视频在线| 亚洲激情成人网| 在线精品视频视频中文字幕| 亚洲国产天堂网精品网站| 欧美日韩另类在线| 欧美疯狂做受xxxx高潮| 91在线视频免费| 海角国产乱辈乱精品视频| 色综合视频一区中文字幕| 亚洲美腿欧美激情另类| 久久亚洲一区二区三区四区五区高| 日韩精品亚洲元码| 久久久久久国产| 亚洲最大在线视频| 国产精品永久免费| 亚洲影院色在线观看免费| 欧美国产日韩二区| 萌白酱国产一区二区| 国产精品十八以下禁看| 日韩电影中文字幕av| 国产精品色午夜在线观看| 色yeye香蕉凹凸一区二区av| 欧美黄色性视频| 亚洲男人天堂网站| 国产精品永久免费观看| 国产精品视频网| 欧美性xxxxxx| 欧美第一页在线| 在线观看日韩视频| 欧美在线视频免费观看| 黑人巨大精品欧美一区二区一视频| 国产精品成人国产乱一区| 久久成人精品电影| 欧美在线视频一区二区| 色噜噜狠狠狠综合曰曰曰88av| 欧美丰满少妇xxxx| 日韩av一区在线观看| 色综合久久88| 26uuu日韩精品一区二区| 成人啪啪免费看| 高潮白浆女日韩av免费看| 一级做a爰片久久毛片美女图片| 91久久精品久久国产性色也91| 性欧美办公室18xxxxhd| 中文字幕国产精品久久| 亚洲第一网站男人都懂| 国产男人精品视频| 91性高湖久久久久久久久_久久99| 欧美成人午夜激情视频| 亚洲第一精品电影| 欧美劲爆第一页| 国产精品视频xxx| 国产精品欧美日韩久久| 久久精品99久久久香蕉| 国产精品高潮视频| 91精品久久久久久久久中文字幕| 日韩视频免费中文字幕| 在线观看日韩av| 亚洲第一免费播放区| 欲色天天网综合久久| 欧美日本精品在线| 综合网日日天干夜夜久久| 国产精品美女无圣光视频| 欧美疯狂性受xxxxx另类| 国产精品一二三在线| 欧洲s码亚洲m码精品一区| 国产九九精品视频| 欧美又大又粗又长| 日韩在线观看免费全| 亚洲欧美激情一区| 亚洲一区二区三区四区在线播放| 午夜精品久久久久久99热| 亚洲精品成人av| 亚洲第一二三四五区| 亚洲国产精品久久久久秋霞不卡| 欧美日韩国产中字| 久久精品久久久久久国产 免费| 国产欧美久久一区二区| 亚洲有声小说3d| 久久久精品电影| 91精品久久久久久| 国产美女直播视频一区| 亚洲国产欧美一区二区三区久久| 亚洲视频在线视频| 日韩毛片在线看| 国内精品久久久久久久| 亚洲精品中文字幕女同| 国产精品尤物福利片在线观看| 午夜精品www| 国产男女猛烈无遮挡91| 亚洲码在线观看| 欧美一区二区三区四区在线| 精品视频久久久久久| 国产视频丨精品|在线观看|