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

news/2024/5/12 3:02:17/文章来源:https://blog.csdn.net/weixin_33964094/article/details/86068778

一、前言

      偶然一次在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         }
View Code

 

 

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

百度为您找到相关结果约([\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     }
View Code

 

 

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

      以上是笔者在百度中搜索程序员的排名第九个的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中添加已经实现的类就可以了,方面其他开发者开发出自己的实现并加入其中。

 

 

七、小节

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

 

^.^我是源码下载

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_768114.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从头开始建网站(三)DNS

前面介绍了站点搭建所须要的两大要素&#xff1a;域名和server&#xff0c;这次要说的是域名解析&#xff0c;也就是把域名和server进行绑定的过程。 我们在訪问网络时&#xff0c;网址会被发送到DNSserver&#xff0c;然后由DNSserver返回我们所要訪问的serverIP地址&#xff…

PC比电脑好玩的秘密是什么?答案就是因为有这些神奇的网站!

五花八门小工具合集http://www.nicetool.net/ 该网站真的很“乱”&#xff01;因为里面的小功能真的很多&#xff01;无论是Gif制作、证件照换底色、还是搞笑的王思聪微博生成&#xff0c;它都能让你得心意手&#xff01; 根据你的星座推荐电影https://magicmoviesorter.com/ 如…

大型网站系统架构的演化

前言 一个成熟的大型网站&#xff08;如淘宝、天猫、腾讯等&#xff09;的系统架构并不是一开始设计时就具备完整的高性能、高可用、高伸缩等特性的&#xff0c;它是随着用户量的增加&#xff0c;业务功能的扩展逐渐演变完善的&#xff0c;在这个过程中&#xff0c;开发模式、技…

【推荐】腾讯android镜像(做Android开发的得好好利用下这个网站,国内的大公司还是可以滴……)...

原文地址&#xff1a;http://android-mirror.bugly.qq.com:8080/include/usage.html ☀ Windows I. Open Android SDK Manager II. Config User Defined Sites Add this url to "User Defined Sites": http://android-mirror.bugly.qq.com:8080/android/repository/…

小说网站爬虫

小说网站爬虫第一天 从今天开始&#xff0c;学习一下爬虫的知识&#xff0c;爬取小说网站。 第一天&#xff1a; 网站&#xff1a;http://www.bxwx9.org 小说&#xff1a;大主宰 语言&#xff1a;IDEAjava jar包&#xff1a;maven工程&#xff0c;所以放上dependencies&#xf…

证书过期?私钥泄露?掌控您的证书和私钥,维护网站安全和声誉!

数字证书&#xff0c;作为网络世界的&#xff0c;提供了一种在Internet上验证通信实体身份的方式&#xff0c;其作用类似于司机的驾驶执照或日常生活中的。譬如&#xff0c;Web Server通过提供自己的数字证书来证明自己的身份&#xff0c;用户得以确认所访问的网站就是想要访问…

高考失利,选择SEO的职业的未来之路怎么样?

通过了解各类搜索引擎如何抓取互联网页面、如何进行索引以及如何确定其对某一特定关键词的搜索结果排名等技术&#xff0c;来对网页内容进行相关的优化&#xff0c;使其符合用户浏览习惯&#xff0c;在不损害用户体验的情况下提高搜索引擎排名&#xff0c;从而提高网站访问量&a…

网站统计中的数据收集原理及实现

网站数据统计分析工具是网站站长和运营人员经常使用的一种工具&#xff0c;比较常用的有谷歌分析、百度统计和腾讯分析等等。所有这些统计分析工具的第一步都是网站访问数据的收集。目前主流的数据收集方式基本都是基于javascript的。本文将简要分析这种数据收集的原理&#xf…

如何阻止ajax自动重定向_技巧:IE访问不兼容网站时如何不重定向到Edge中打开...

微软正有条不紊地推进 Edge 迁移工作。首先自 Edge 85 开始&#xff0c;微软整合了 IE 模式&#xff0c;以便于用户兼容使用&#xff1b;对外正式公布了 IE 和经典版 Edge 的停止支持时间表&#xff0c;而现在当用户使用 IE 11 访问某些不兼容的网站时自动重定向到 Edge 浏览器…

在线学习Java的资源网站

CodeGym&#xff08;https://codegym.cc/&#xff09;&#xff1a;一个在线Java编程课程&#xff0c;80%的内容是练习&#xff0c;适合一窍不通的入门者。 CodeAcademy&#xff08;https://www.codecademy.com/&#xff09;&#xff1a;该课程注重的是在找工作时非常有用的技术…

网站服务器宕机,B站服务器宕机惊动上海消防,官微致歉

7月13日晚间&#xff0c;“b站崩了”冲上微博热搜榜第三位。消息称&#xff0c;B站官网疑似出现服务器宕机事故&#xff0c;页面提示称“非常抱歉&#xff0c;该页面暂时无法访问”。7月14日凌晨2点&#xff0c;哔哩哔哩弹幕官微更新动态称“昨晚&#xff0c;B站的部分服务器机…

想要导航首页提示页_网站建设|网站首页这么设计,用户体验更好

这是【建站百科】专栏第18篇原创内容&#xff0c;由我在建站行业从业10年、给上万公司搭建过网站的经验总结而来。hello&#xff0c;艾瑞巴蒂&#xff0c;大梦又来了&#xff0c;今天要说的是作为网站“门面”的网站首页设计。一、 网站首页的重要性作为网站全貌及重要信息、产…

基于LNMP的实验之电子商务网站

实验开始之前的环境检查&#xff1a;iptables ,selinux&#xff08;要处于关闭状态&#xff09; 实验工具&#xff1a;centos7虚拟主机一台 实验步骤如下&#xff1a; 一、安装 ①安装实验所需包 [rootcentos7 ~]# yum install mariadb mariadb-server php php-mysql php-fpm &…

alevel aqa business_学习干货 | ALevel商科学习网站总结

学生小编&#xff0c;有什么方法我可以在日常中锻炼自己的商科思维呀&#xff1f;有很多呀&#xff0c;最简单的就是浏览一些商业资讯或者观看训练商科思维的视频~英联教育学生那小编有没有一些推荐的网站&#xff1f;有有有&#xff0c;小编已经帮你整理好啦&#xff01;就等你…

SpringCloud系列(一)网站架构演变过程—什么是微服务?SpringCloud是什么?

网站架构演变过程 1、传统架构模式&#xff08;单点应用&#xff09; 一般只适合一个人或者是小团队开发 缺点&#xff1a;耦合度太高&#xff0c;一旦某个模块出问题&#xff0c;可能会影响整个服务不可用 2、分布式架构模式&#xff08;对项目进行拆分&#xff09; 由传…

软件测试必学:电子商务网站测试经验总结

有开发就有测试&#xff0c;现在软件测试行业真的很不错。测试网站也是一项很重要的工作。今天我总结了一下如何测试电子商务网站&#xff0c;总体按照两种模式进行划分总结&#xff0c;请往下看哦&#xff01; 一、按照测试类型来划分 1.兼容性1.1主要是在浏览器兼容&#x…

给你一个网站,你如何来做自动化测试的?Web网站测试流程及方法

给你一个网站&#xff0c;你如何来做自动化测试的&#xff1f;今天小编来给大家科普一下Web网站测试流程及方法。 首先&#xff0c;查找需求说明、网站设计等相关文档&#xff0c;分析测试需求。制定测试计划&#xff0c;确定测试范围和测试策略。一般包括以下几个部分&#x…

网站静态化处理

动静分离是让动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区分开来&#xff0c;动静资源做好了拆分以后&#xff0c;我们就可以根据静态资源的特点将其做缓存操作&#xff0c;这就是网站静态化处理的核心思路。由此可见&#xff0c;网站静态化处理的核心就是动…

微软正式发布Azure Storage上的静态网站

微软正式宣布了Azure Storage上的静态网站&#xff0c;提供了从托管在Azure Storage上的HTML、CSS和JavaScript文件提供内容的能力。静态网站包含内容固定的Web页面&#xff0c;同时仍然允许利用JavaScript等客户端代码来创建丰富的用户体验。 有了这个新功能&#xff0c;继用于…

使用Nginx + Node.js部署你的网站(转)

转自&#xff1a;https://www.jianshu.com/p/717f2b88d057 Nginx是一个高性能的HTTP和反向代理服务器&#xff08;反向代理就是通常所说的web服务器加速&#xff0c;它是一种通过在繁忙的web服务器和internet之间增加一个高速的web缓冲服务器来降低实际的web服务器的负载&#…