记一次网站收录数和排名的实现

一、前言

偶然一次在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}就是为真正需要检索网址的占位符,获取下载页面的路径是所有具体类都需要的所以我们直接将实现放在抽象类中,比如下面的代码:

 1        /// <summary>
 2         /// 服务提供者
 3         /// </summary>
 4         protected String SearchProvider { get; set; }
 5
 6         /// <summary>
 7         /// 需要检索的网址
 8         /// </summary>
 9         protected String SiteUrl { get; set; }
10
11         /// <summary>
12         /// 搜索服务提供网址
13         /// </summary>
14         protected String BaseUrl { get; set; }
15
16         /// <summary>
17         /// 后页面网址
18         /// </summary>
19         /// <param name="site">需要查询的网址</param>
20         /// <returns>拼接后的网址</returns>
21         protected String GetDownUrl(string site)
22         {
23             return string.Format(BaseUrl, HttpUtility.UrlEncode(site));
24         }

其中SiteUrlSearchProvider是用来保存检索网址和搜索引擎名称。

上面我们说了将会利用WebClient来下载页面,所以初始化WebClient的工作也在抽象类中完成,尽可能的减少重复代码,而为了防止阻塞当前线程所以我们采用了Async方法。

具体代码如下所示:

 1         /// <summary>
 2         /// 查询在该搜索引擎中的收录次数
 3         /// </summary>
 4         /// <param name="siteurl">网站URL</param>
 5         public void SearchIncludeCount(string siteurl)
 6         {
 7             SiteUrl = siteurl;
 8             WebClient client = new WebClient();
 9             client.Encoding = Encoding.UTF8;
10             client.DownloadStringCompleted += DownloadStringCompleted;
11             client.DownloadStringAsync(new Uri(GetDownUrl(siteurl)));
12         }
13
14         /// <summary>
15         /// 检索收录次数的具体实现
16         /// 子类必须要实现该方法
17         /// </summary>
18         /// <param name="sender"></param>
19         /// <param name="e"></param>
20         protected abstract void DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e);

WebClient完成下载后将会回调DownloadStringCompleted方法,而这个方法的是抽象方法也就意味着具体类必须要实现这个方法。

虽然我们内部的实现是异步的但是对于其他开发者调用这个方法还是同步的,所以我们就需要借助委托因此我们还要新建一个委托类型:

        /// <summary>
        /// 当完成一个网站的收录查询后回调
        /// </summary>
        public Action<SiteIncludeCountResult> OnComplatedOneSite { get; set; }

其中SiteIncludeCountResult的结构如下所示:

 1     /// <summary>
 2     /// 用于网站收录中委托的参数
 3     /// </summary>
 4     public class SiteIncludeCountResult
 5     {
 6         /// <summary>
 7         /// 收录次数
 8         /// </summary>
 9         public long IncludeCount { get; set; }
10
11         /// <summary>
12         /// 搜索引擎类型
13         /// </summary>
14         public String SearchType { get; set; }
15
16         /// <summary>
17         /// 网站URL
18         /// </summary>
19         public String SiteUrl { get; set; }
20 }
21
22 最后还有一个方法用于DownloadStringCompleted完成后回调OnComplatedOneSite委托:
23         /// <summary>
24         /// 完成处理后调用该方法将结果返回
25         /// </summary>
26         /// <param name="result">网址的收录数结果</param>
27         protected void SetCompleted(SiteIncludeCountResult result)
28         {
29             if (OnComplatedOneSite != null)
30                 OnComplatedOneSite(result);
31         }

这样我们需要的抽象类就完成了,下面我们就可以开始实现第一个了,通过上面的截图我们可以发现要匹配这段字符串的正则表达式很简单:

百度为您找到相关结果约([\w,]+?)个

最后再将获取的字符串去掉逗号就可以强制转换了,这样结果就出来了,具体实现就像下面这样:

 1     /// <summary>
 2     /// 百度网站收录次数查询
 3     /// </summary>
 4     public class BaiDuSiteIncludeCount : SiteIncludeCountBase
 5     {
 6         public BaiDuSiteIncludeCount()
 7         {
 8             BaseUrl = "http://www.baidu.com/s?wd=site%3A{0}";
 9             SearchProvider = "百度";
10         }
11
12         protected override void DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
13         {
14             var result = new SiteIncludeCountResult();
15             result.SiteUrl = SiteUrl;
16             result.SearchType = SearchProvider;
17             result.IncludeCount = 0;
18             Regex reg = new Regex(@"百度为您找到相关结果约([\w,]+?)个", RegexOptions.IgnoreCase | RegexOptions.Singleline);
19             var matchs = reg.Matches(e.Result);
20             if (matchs.Count > 0)
21             {
22                 string count = matchs[0].Groups[1].Value.Replace(",", "");
23                 result.IncludeCount = long.Parse(count);
24             }
25             SetCompleted(result);
26         }
27 }

以此类推,其他的都是按照这种就可以了,有兴趣的可以下载我的源码查看。

五、关键词排名

我们按照之前的思路,还是要先规定一个抽象类,但是其结构跟上面的抽象类很相似,所以笔者这里直接给出具体的代码:

 1     /// <summary>
 2     /// 实现关键词查询必须继承该类
 3     /// </summary>
 4     public abstract class KeyWordsSeoBase
 5     {
 6         protected String BaseUrl { get; set; }
 7
 8         protected String SearchProvider { get; set; }
 9
10         protected String GetDownUrl(string keyword, string site, long current)
11         {
12             return String.Format(BaseUrl, HttpUtility.UrlEncode(keyword), current);
13         }
14
15         protected void SetCompleted(KeyWordsSeoResult result)
16         {
17             if (OnComplatedOneKeyWord != null)
18             {
19                 OnComplatedOneKeyWord(result);
20             }
21         }
22
23         /// <summary>
24         /// 完成一个关键词的查询后回调该委托
25         /// </summary>
26         public Action<KeyWordsSeoResult> OnComplatedOneKeyWord { get; set; }
27
28         /// <summary>
29         /// 查询指定关键词和网站在该搜索引擎中的排行
30         /// 子类需要重写该方法
31         /// </summary>
32         /// <param name="keywords">关键词</param>
33         /// <param name="site">网站URL</param>
34         public abstract void SearchRanking(IEnumerable<string> keywords, string site,long count);
35 }

最大的区别在于具体的实现全部集中在SearchRanking中,通过keywords参数可以看出我们会支持多个关键词的查询,最后不同的就是下载路径的组织,因为涉及到翻页所以多了一个参数。

其中KeyWordsSeoResult的结构如下所示:

 1     /// <summary>
 2     /// 用于关键词排行查询的委托参数
 3     /// </summary>
 4     public class KeyWordsSeoResult
 5     {
 6         /// <summary>
 7         /// 搜索引擎类型
 8         /// </summary>
 9         public String SearchType { get; set; }
10
11         /// <summary>
12         /// 关键词
13         /// </summary>
14         public String KeyWord { get; set; }
15
16         /// <summary>
17         /// 排行
18         /// </summary>
19         public long Ranking { get; set; }
20     }

废话不多说,我们来看百度的搜索结果页:

以上是笔者在百度中搜索程序员的排名第九个的html结构,或许你会觉得很简单只要获取div的id以及网址就可以了,但是很多搜索引擎的路径并不是直接的路径,而是会先链到百度然后重定向的,如果非要匹配我们就需要多做一件事就是访问这个路径得到真实的路径,那样就会加大这中间的等待时间,所以笔者采用的是直接截取上图中的<span class=”g”>后面的内容,这样就避免了一次请求。(不知道当初笔者怎么想的,实现的时候并没有采用id那个值而是在内部递增,估计这个id的序号在翻页后会出现问题吧),最后亮出我们神圣的正则表达式:

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

以为这样就大公告成了?错了,在某些结果里面百度会给这个网址加上b标签,而笔者则采用全部赶尽杀绝的方式,利用正则全部删掉(反正又不看页面,只要拿到我想要的就OK了),实现的时候我们可不能直接实现多个关键词的判明,应该是实现一个关键词的,然后循环调用即可了,下面是笔者的单个关键词的实现:

 1         protected KeyWordsSeoResult SearchFunc(string key, string siteurl, long total)
 2         {
 3             var result = new KeyWordsSeoResult();
 4             result.KeyWord = key;
 5             result.Ranking = total + 1;
 6             var reg = new Regex(@"<span\s+class=""(?:g|c-showurl)"">([^/&]*)", RegexOptions.IgnoreCase | RegexOptions.Singleline);
 7             var replace = new Regex("</?b>", RegexOptions.IgnoreCase | RegexOptions.Singleline);
 8             var client = new WebClient();
 9             long current = 0;
10             long pos = 0;
11             for (; ; )
12             {
13                 String url = GetDownUrl(key, siteurl, current);
14                 String downstr = client.DownloadString(url);
15                 downstr = replace.Replace(downstr, "");
16                 var matchs = reg.Matches(downstr);
17                 foreach (Match match in matchs)
18                 {
19                     pos++;
20                     string suburl = match.Groups[1].Value;
21                     try
22                     {
23                         if (suburl.ToLower() == siteurl.ToLower())
24                         {
25                             result.Ranking = pos;
26                             return result;
27                         }
28                     }
29                     catch
30                     {
31                         continue;
32                     }
33                 }
34                 current += 10;
35                 if (current > total)
36                 {
37                     current -= 10;
38                     if (current >= total)
39                     {
40                         break;
41                     }
42                     current = total;
43                 }
44             }
45             return result;
46         }

注意for循环的结束部分,这里是用来处理分页的,以翻到下一页继续检索。其他的大体部分都跟笔者说的一样,下载页面->正则匹配->根据匹配结果判断。剩下的就是SearchRanking的实现,就是循环关键词,只是这里笔者为每个搜索引擎新建线程来实现,当然这不怎么好,所以读者可以改用更好的方式来做:

 1         public override void SearchRanking(IEnumerable<string> keywords, string site, long count)
 2         {
 3             new Thread(() =>
 4             {
 5                 foreach (string key in keywords)
 6                 {
 7                     KeyWordsSeoResult result = SearchFunc(key, site, count);
 8                     result.SearchType = SearchProvider;
 9                     SetCompleted(result);
10                 }
11             }).Start();
12         }

六、统一管理

有了这些我们就可以写出一个简洁的类来负责管理,笔者这里直接给出代码:

 1     /// <summary>
 2     /// 查询网站的收录次数以及排行
 3     /// </summary>
 4     public class RankingAndIncludeSeo
 5     {
 6         /// <summary>
 7         /// 关键词列表
 8         /// </summary>
 9         public IList<KeyWordsSeoBase> KeyWordsSeoList { get; private set; }
10
11         /// <summary>
12         /// 收录次数列表
13         /// </summary>
14         public IList<SiteIncludeCountBase> SiteIncludeCountList { get; private set; }
15
16         public RankingAndIncludeSeo()
17         {
18             KeyWordsSeoList = new List<KeyWordsSeoBase>();
19             SiteIncludeCountList = new List<SiteIncludeCountBase>();
20         }
21
22         /// <summary>
23         /// 当完成一个关键词的查询后回调该委托
24         /// </summary>
25         public Action<KeyWordsSeoResult> OnComplatedAnyKeyWordsSearch { get; set; }
26
27         /// <summary>
28         /// 当完成一个网站的收录次数查询后回调该委托
29         /// </summary>
30         public Action<SiteIncludeCountResult> OnComplatedAnySiteIncludeSearch { get; set; }
31
32         /// <summary>
33         /// 查询网址的排行
34         /// </summary>
35         /// <param name="keywords">关键词组</param>
36         /// <param name="siteurl">查询的网址</param>
37         /// <param name="count">最大限制排行数</param>
38         public void SearchKeyWordsRanking(IEnumerable<string> keywords, string siteurl, long count = 100)
39         {
40             if (keywords == null)
41                 throw new ArgumentNullException("keywords", "必须存在关键词");
42             if (siteurl == null)
43                 throw new ArgumentNullException("siteurl", "必须存在网站URL");
44             foreach (KeyWordsSeoBase kwsb in KeyWordsSeoList)
45             {
46                 kwsb.OnComplatedOneKeyWord = kwsb.OnComplatedOneKeyWord ?? OnComplatedAnyKeyWordsSearch;
47                 kwsb.SearchRanking(keywords, siteurl, count);
48             }
49         }
50
51         /// <summary>
52         /// 查询网址的收录次数
53         /// </summary>
54         /// <param name="siteurl">查询的网址</param>
55         public void SearchSiteIncludeCount(string siteurl)
56         {
57             if (siteurl == null)
58                 throw new ArgumentNullException("siteurl", "必须指定网站");
59             foreach (SiteIncludeCountBase sicb in SiteIncludeCountList)
60             {
61                 sicb.OnComplatedOneSite = sicb.OnComplatedOneSite ?? OnComplatedAnySiteIncludeSearch;
62                 sicb.SearchIncludeCount(siteurl);
63             }
64         }
65 }

RankingAndIncludeSeo中提供了公共的委托,如果单个搜索引擎没有提供委托那么就采用这个公共的,如果已经指定了单独的委托就不会被赋值了,而其他开发者调用的时候只要向KeyWordsSeoListSiteIncludeCountList中添加已经实现的类就可以了,方面其他开发者开发出自己的实现并加入其中。

七、小节

这篇随笔总的来说并不是讲述什么高端技术的,仅仅只是提供一种大致的思路以及结构上的设计,如果读者需要应用于实际开发中,最好加以验证,笔者并不能保证关键词的排名没有任何误差,因为搜索的结果会由于任何因素发生改变。

^.^我是源码下载

时间: 2024-10-09 09:39:05

记一次网站收录数和排名的实现的相关文章

C#实现百度网站收录和排名查询功能思路及实例

一.前言 偶然一次在vs2012默认的项目文件夹里发现了以前自己做的一个关于SEO的类库,主要是用来查询某个网址的收录次数还有网站的排行数,后来重构了下,今天拿出来写篇文章,说说自己是如何思考的并完成的. 二.问题描述 首先需要考虑的是能够支持哪些搜索引擎的查询,首先是百度,然后是必应.搜狗.搜搜.360.本来想支持Google但是一想不对,根本不好访问的,所以暂时不算在内.而我们实际要做的就是根据一个网址能够检索出这个网址的在各个搜索引擎的收录次数以及在不同关键词下的网址排行,这里出入的只有网

新上线的网站想要获得排名没有什么捷径,简单的事情重复做

1.查看网站快照情况 对于交换链接,我们首先要看的就是网站要有快照,不管网站快照慢还是快照隔天的,但是第一条肯定是网站要有快照,最好是当天,次之隔天,最差3天内,超过一周的基本不考虑. 2.考虑PR值和PR输出值 对于这点,出站链接最好少于30,最高不超过50,也许很多人说谷歌PR已经退出中国市场了,那么为什么我们还需要看网站的PR值呢?虽然说谷歌PR曾经退出过,但是谷歌官方后来还是承认谷歌PR的存在,所以网站的PR值是交换友链的标准之一,不一定都要比自己高的,只要相当就可以了,当然,能换到PR

新站长必备 各大网站收录入口,各大搜索引擎提交, 搜索引擎提交地址

网站建设完成之后,第一件事情就是向各大搜索引擎提交新网站.已更好的分享自己的文章,获取更多的访客. 搜索引擎提交包括提交给搜索引擎爬虫和提交给分类目录. 提交给搜索引擎爬虫的目的是让搜索引擎将网站收录到索引数据库.检验网站是否被搜索引擎收录的办法是直接在搜索引擎中搜索网址,查看能否找到网站结果,也可以通过输入命令”site:hoar.me”获得具体的页面收录数量. 提交给搜索引擎分类目录有两个目的:一是为了用户通过分类目录检索到网站,二是为网站获得一个高质量的外部链接,有助于增加网站的链接广度.

如何增加增加网站收录量

做SEO总是围绕着一个问题,就是网站的收录问题,网站收录分别有站内和站外收录.但是有时有收录的情况却不是很理想,所以小编我总结的一些经验,建议大家针对网站收录不好的情况下,我们可以用一些在网上有的一些资源来吸引蜘蛛收录爬行网站,以下是我的经验分享给大家(本文来自e良师益友网,elsyy.com): 一.如何更新站内文章提高收录量 其实我们做SEO工作时,每天都要更新4-6篇文章,而每天要让搜索引擎收录3-4篇文章才算正常,所以收录少的站内文章网站,可能你更新文章的方法不对,所以导致站内文章收录情

网站权重与搜索排名的关系

很多站长觉得网站权重就是排名,其实权重和排名还是有区别的. 网站权重:网站权重说明一个网站的权威性.也可以理解为网站的知名度. 排名:排名只能理解为企业的产品.相同的产品不同的品牌其价值也就不同,这也就是权重和排名的关系. 网站权重对网站排名还是有着很大的关系,一个权重高的网站,网页的排名也就高.权重高的网站搜索引擎更新的 也快.如和讯博客在百度的权重就很高,在和讯博客发表一篇博文2个小时左右百度就可以收录. 很多站长只在意主页的排名,通过各种手段把几个关键词排上去,虽然流量上来了,但排名不稳定

常用的SEO检测工具和网站收录集锦 希望对大家有所帮助 QQ交流群 72931205

PR值,即PageRank,网页的级别技术.一般来说,是google提供的判断网站重要性的一个标准.你的pr为0的原因可能有两个原因1.你的网站很垃圾,就是传说中的垃圾站.2.你的网站是新站,google需要给你的网站一个定位,通常需要几个月后pr值更新时才会给你pr值网站pr能到4已经是非常不错了,一般网站都是2或者3比较多,垃圾点的只有1或0. 能够有效快速收录网站的途径有以下几项. 1 百度站长工具(http://zhanzhang.baidu.com/) 小编在百度站长工具添加了自己的网

网站收录页面数量减少原因及分析

很多网络优化人员在网站优化工程中肯定都遇到过网页收录数量突然大量减少问题,那么通常的这种网页收录数量减少都是什么原因造成的呢? 1.搜索引擎算法的更新.        在历次搜索引擎算法更新中,很多网站都会出现网站排名不稳定,网站收录数量变化等情况,这时候大家可以对其他网站的数据进行对比,如果其他网站都有该情况,就可以视为正常,有时候这样的网站收录数量的减少反而对网站优化推广来说是个好事. 2.网站的内容复制粘贴或者大量采集,毫无原创性.      有一些网站管理人员为了减少网站的打理时间或者网

新网站收录低或不收录的原因有哪些

我网站一直坚持更新原创内容,发布外链.蜘蛛也有来抓取,但是一直没有收录是为什么呢?一个新站的收录期在1~3个月,前两个月的收录和排名说明不了什么,只有在第三个月基本上就稳定了排名和收录.收录也存在很多影响因素,比如文章质量问题,是否优化过度等 我网站一直坚持更新原创内容,发布外链.蜘蛛也有来抓取,但是一直没有收录是为什么呢?一个新站的收录期在1~3个月,前两个月的收录和排名说明不了什么,只有在第三个月基本上就稳定了排名和收录.收录也存在很多影响因素,比如文章质量问题,是否优化过度等等... 网站

个人博客网站收录突然减少的原因分析

最近良家佐言发现个人博客网站收录突然急剧下降,从收录的124条一直降到72条,登录百度资源平台通过索引工具的趋势图才发现,近20天良家佐言的个人博客网站的索引量走势图波动非常的大,从上个月中旬到这个月初5号,索引量才开始慢慢回升:良家佐言个人博客网站是去年10月中旬注册,11月份才上线的,通过一些优化手段,收录呈现正常形态,从百度搜索资源平台索引工具反映出来的信息来看,近三周索引走势图变化开始呈现不规律现象,仔细想想这三周的所作所为,良家佐言发现了一些原因. 一.网站站内文章更新不规律 搜索引擎