百度搜索指定网站内容(vs2012如何查询某个网址的收录次数5,280,000这段)

优采云 发布时间: 2022-02-16 14:00

  百度搜索指定网站内容(vs2012如何查询某个网址的收录次数5,280,000这段)

  一、前言

  偶然在vs2012的默认项目文件夹中发现了一个我之前做的关于SEO的类库。主要用于查询某网站收录的数量和网站的排名数量。后来经过重构,今天拿出来写了一篇文章文章,告诉我我是怎么想的,怎么完成的。

  二、问题描述

  首先要考虑的是可以支持哪些搜索引擎查询,首先是百度,然后是必应、搜狗、搜搜、360。本来想支持谷歌的,但是没想到,不好访问全部,所以暂时不包括在内。我们真正需要做的是,根据一个URL,检索这个URL在各个搜索引擎中的收录次数,以及不同关键词下的URL排名。只有 URL 和几个 关键词 进出。@关键词,输出为该URL在不同搜索引擎下的收录次数和每个关键词下的排名次数。

  但是这里有一个问题,就是排名的数量。如果检索到的 URL 在前 100 位,那就没问题了。如果排名很低,那么问题就来了,这会让用户等待很长时间才能看到结果,但用户可能只想知道前100名的具体排名,超过100名的只需要展示出来,这些都需要前期考虑好,方便后续的流程。

  三、解决方案

  相信很多人都能想到,就是用WebClient下载需要的页面,然后用正则得到我们感兴趣的部分,再用程序进行处理。关键难点在这个正则的写法上,首先我们从一个简单的说起。

  四、收录次数

  首先是网站的收录的编号,我们可以在百度中输入site:,然后可以看到如下页面:

  

  而我们需要收录的次数是5,280,000,那么我们来看一下页面元素:

  

  然后我们再看其他搜索引擎,发现都差不多,所以这个时候我们的思路就应该画出来了,最后就是如何组织URL。在这部分,我们看看地址栏?wd=site%3A%2F 就知道怎么写了。

  这时候我们可能会迫不及待地一一实现,这样以后就不能集中调用了,也会影响以后的添加,所以需要指定一个抽象类来实现收录@ > number 函数,这样就可以在不知道具体实现的情况下统一使用,而且以后可以方便的添加新的搜索引擎,这种方式属于策略模式(Stategry)。让我们慢慢分析这个抽象类的具体内容。

  首先,实现这个抽象类的每个具体类都应该对应某个搜索引擎,所以它需要有一个基本的URL,并留一个占位符。比如根据上面的百度,我们可以得到这样一个字符串

  %3A{0}

  其中,{0} 是真正需要检索的 URL 的占位符。获取下载页面的路径是所有具体类都需要的,所以我们直接把实现放到抽象类中,比如下面的代码:

  复制代码代码如下:

  ///

  /// 服务供应商

  ///

  受保护的字符串 SearchProvider { get; 放; }

  ///

  /// 要检索的 URL

  ///

  受保护的字符串 SiteUrl { 获取;放; }

  ///

  /// 搜索服务提供者 URL

  ///

  受保护的字符串 BaseUrl { 获取;放; }

  ///

  /// 后页地址

  ///

  ///

  要查询的网址

  /// 连接的 URL

  受保护的字符串 GetDownUrl(字符串站点)

  {

  return string.Format(BaseUrl, HttpUtility.UrlEncode(site));

  }

  其中,SiteUrl 和 SearchProvider 用于保存检索 URL 和搜索引擎名称。

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

  具体代码如下:

  复制代码代码如下:

  ///

  /// 此搜索引擎中 收录 查询的数量

  ///

  ///

  网站网址

  公共无效 SearchIncludeCount(字符串站点网址)

  {

  网站网址 = 网站网址;

  WebClient 客户端 = 新 WebClient();

  client.Encoding = Encoding.UTF8;

  client.DownloadStringCompleted += DownloadStringCompleted;

  client.DownloadStringAsync(new Uri(GetDownUrl(siteurl)));

  }

  ///

  /// 检索次数的具体实现 收录

  /// 子类必须实现这个方法

  ///

  ///

  ///

  受保护的抽象无效DownloadStringCompleted(对象发送者,Dow​​nloadStringCompletedEventArgs e);

  当WebClient完成下载后,会回调DownloadStringCompleted方法,这个方法是抽象方法,也就是说具体的类必须实现这个方法。

  虽然我们的内部实现是异步的,但是其他开发者调用这个方法仍然是同步的,所以我们需要使用委托,所以我们还需要创建一个新的委托类型:

  复制代码代码如下:

  ///

  /// 网站的收录查询完成时回调

  ///

  公共操作 OnComplatedOneSite { 获取;放; }

  SiteIncludeCountResult 的结构如下:

  复制代码代码如下:

  ///

  /// 网站收录 中代表的参数

  ///

  公共类 SiteIncludeCountResult

  {

  ///

  /// 收录次数

  ///

  公共长包括计数 { 得到;放; }

  ///

  /// 搜索引擎类型

  ///

  公共字符串搜索类型 { 获取;放; }

  ///

  /// 网站网址

  ///

  公共字符串 SiteUrl { 获取;放; }

  }

  最后还有一个方法可以在 DownloadStringCompleted 完成时回调 OnComplatedOneSite 委托:

  ///

  /// 处理后调用该方法返回结果

  ///

  ///

  收录 URL 的计数结果

  protected void SetCompleted(SiteIncludeCountResult 结果)

  {

  如果(OnComplatedOneSite != null)

  OnComplatedOneSite(结果);

  }

  这样,我们需要的抽象类就完成了。现在我们可以开始实现第一个。从上面的截图中,我们可以发现匹配这个字符串的正则表达式非常简单:

  复制代码代码如下:

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

  最后,你可以通过从获得的字符串中删除逗号来强制转换,结果就会出来。具体实现如下:

  复制代码代码如下:

  ///

  /// 百度网站收录次查询

  ///

  公共类 BaiDuSiteIncludeCount : SiteIncludeCountBase

  {

  public BaiDuSiteIncludeCount()

  {

  BaseUrl = "{0}";

  SearchProvider = "百度";

  }

  protected override void DownloadStringCompleted(对象发送者,Dow​​nloadStringCompletedEventArgs e)

  {

  var 结果 = 新 SiteIncludeCountResult();

  结果.SiteUrl = SiteUrl;

  结果.SearchType = SearchProvider;

  结果.IncludeCount = 0;

  Regex reg = new Regex(@"百度为你找到了大约([\w,]+?)个相关结果", RegexOptions.IgnoreCase | RegexOptions.Singleline);

  var 匹配 = reg.Matches(e.Result);

  if (matchs.Count > 0)

  {

  字符串计数 = 匹配[0].Groups[1].Value.Replace(",", "");

  result.IncludeCount = long.Parse(count);

  }

  设置完成(结果);

  }

  }

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

  五、关键词排名

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

  复制代码代码如下:

  ///

  /// 实现 关键词 查询必须继承这个类

  ///

  公共抽象类 KeyWordsSeoBase

  {

  受保护的字符串 BaseUrl { 获取;放; }

  受保护的字符串 SearchProvider { get; 放; }

  protected String GetDownUrl(字符串关键字,字符串站点,长电流)

  {

  return String.Format(BaseUrl, HttpUtility.UrlEncode(keyword), current);

  }

  protected void SetCompleted(KeyWordsSeoResult 结果)

  {

  如果(OnComplatedOneKeyWord != null)

  {

  OnComplatedOneKeyWord(结果);

  }

  }

  ///

  /// 完成 关键词 查询后回调委托

  ///

  公共操作 OnComplatedOneKeyWord { 获取;放; }

  ///

  /// 查询指定关键词和网站在搜索引擎中的排名

  /// 子类需要重写这个方法

  ///

  ///

  关键词

  ///

  网站网址

  public abstract void SearchRanking(IEnumerable keywords, string site, long count);

  }

  最大的不同是具体实现都集中在SearchRanking。从keywords参数可以看出,我们将支持多个关键词查询。最后一个区别是下载路径的组织。因为它涉及翻页,所以有一个额*敏*感*词*。

  KeyWordsSeoResult 的结构如下:

  复制代码代码如下:

  ///

  /// 关键词 排名查询的委托参数

  ///

  公共类 KeyWordsSeoResult

  {

  ///

  /// 搜索引擎类型

  ///

  公共字符串搜索类型 { 获取;放; }

  ///

  /// 关键词

  ///

  公共字符串关键字 { 获取;放; }

  ///

  /// 排行

  ///

  public long Ranking { 得到;放; }

  }

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

  

  以上是笔者在百度搜索程序员的第九个html结构。您可能认为获取 div 的 id 和 URL 非常简单。但是很多搜索引擎的路径并不是直接路径,而是会先链接到百度,然后再重定向。如果一定要匹配,我们还需要做一件事:访问这条路径获取真实路径,中间会增加等待时间,所以作者使用了上面的截图。中的后者内容,从而避免了请求。(不知道作者一开始是怎么想的,实现中并没有用到id值,而是内部自增,估计翻页后这个id的序号会有问题),最后展示我们神圣的正则表达式:

  复制代码代码如下:

  ([^/&]*)

  你认为这是一个重大的公告吗?错了,在某些结果中,百度会在这个网址上加ab标签,作者采用了全部杀掉的方法,使用正则规则全部删除(反正我不看页面,只要得到我要的,没关系),实现的时候不能直接实现多个关键词的识别,应该是实现一个关键词,然后循环调用。以下是作者单关键词的实现:

  复制代码代码如下:

  protected KeyWordsSeoResult SearchFunc(字符串键,字符串 siteurl,长总计)

  {

  var 结果 = 新的 KeyWordsSeoResult();

  结果.KeyWord =键;

  结果.排名=总+1;

  var reg = new Regex(@"([^/&]*)", RegexOptions.IgnoreCase | RegexOptions.Singleline);

  var replace = new Regex("", RegexOptions.IgnoreCase | RegexOptions.Singleline);

  var client = new WebClient();

  长电流 = 0;

  长位置 = 0;

  为了 (; ; )

  {

  字符串 url = GetDownUrl(key, siteurl, current);

  String downstr = client.DownloadString(url);

  downstr = replace.Replace(downstr, "");

  var 匹配 = reg.Matches(downstr);

  foreach(匹配中的匹配)

  {

  正++;

  字符串 suburl = match.Groups[1].Value;

  尝试

  {

  if (suburl.ToLower() == siteurl.ToLower())

  {

  结果.Ranking = pos;

  返回结果;

  }

  }

  抓住

  {

  继续;

  }

  }

  当前 += 10;

  如果(当前>总计)

  {

  当前-= 10;

  如果(当前 >= 总计)

  {

  休息;

  }

  当前=总计;

  }

  }

  返回结果;

  }

  注意for循环的结束,用于处理分页,以便翻到下一页继续检索。其他通用部分和作者说的一样,下载页面->正则匹配->根据匹配结果判断。剩下的就是SearchRanking的实现,也就是循环关键词,不过这里我为每个搜索引擎新建一个线程来实现,当然这样不太好,读者可以用更好的方式来做它:

  复制代码代码如下:

  public override void SearchRanking(IEnumerable keywords, string site, long count)

  {

  新线程(()=>

  {

  foreach(关键字中的字符串键)

  {

  KeyWordsSeoResult 结果 = SearchFunc(key, site, count);

  结果.SearchType = SearchProvider;

  设置完成(结果);

  }

  })。开始();

  }

  六、统一管理

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

  复制代码代码如下:

  ///

  /// 查询网站的收录的个数和排名

  ///

  公共类RankingAndIncludeSeo

  {

  ///

  /// 关键词列表

  ///

  公共 IList KeyWordsSeoList { 获取;私人套装;}

  ///

  /// 收录时间列表

  ///

  公共 IList SiteIncludeCountList { 获取;私人套装;}

  公共 RankingAndIncludeSeo()

  {

  KeyWordsSeoList = new List();

  SiteIncludeCountList = new List();

  }

  ///

  /// 当 关键词 查询完成时回调委托

  ///

  公共操作 OnComplatedAnyKeyWordsSearch { 获取;放; }

  ///

  /// 完成收录次网站的查询后回调delegate

  ///

  公共操作 OnComplatedAnySiteIncludeSearch { 获取;放; }

  ///

  /// 查询URL的排名

  ///

  ///

  关键词组

  ///

  查询网址

  ///

  最大等级数

  public void SearchKeyWordsRanking(IEnumerable 关键字,字符串 siteurl,长计数 = 100)

  {

  如果(关键字 == 空)

  throw new ArgumentNullException("keywords", "必须存在 关键词");

  如果(网站网址 == 空)

  throw new ArgumentNullException("siteurl", "必须存在 网站URL");

  foreach(KeyWordsSeoList 中的 KeyWordsSeoBase kwsb)

  {

  kwsb.OnComplatedOneKeyWord = kwsb.OnComplatedOneKeyWord ?? OnComplatedAnyKeyWordsSearch;

  kwsb.SearchRanking(关键字,站点网址,计数);

  }

  }

  ///

  /// 收录 查询 URL 的数量

  ///

  ///

  查询网址

  公共无效 SearchSiteIncludeCount(字符串网站网址)

  {

  如果(网站网址 == 空)

  throw new ArgumentNullException("siteurl", "必须指定 网站");

  foreach(SiteIncludeCountBase sicb 中的 SiteIncludeCountList)

  {

  sicb.OnComplatedOneSite = sicb.OnComplatedOneSite ?? OnComplatedAnySiteIncludeSearch;

  sicb.SearchIncludeCount(siteurl);

  }

  }

  }

  RankingAndIncludeSeo 提供了一个公共代表。如果单个搜索引擎不提供委托,则使用此公共委托。如果指定了单独的delegate,就不会分配了,其他开发者只需要在调用时添加到KeyWordsSeoList和SiteIncludeCountList中已经实现的类即可,其他开发者自己开发实现加入即可。

  七、部分

  一般来说,这篇文章不是关于高端技术的,而只是提供一个大致的想法和结构设计。如果读者需要在实际开发中应用,最好验证一下。作者不保证关键词的排名没有错误,因为搜索结果可能因任何因素而发生变化。

  ^.^我是源代码下载

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线