.NET Core实践爬虫系统:解析网页内容

优采云 发布时间: 2022-06-06 20:24

  .NET Core实践爬虫系统:解析网页内容

  ///

  public long View { get; set; }

  ///

  ///明细

  ///

  public string Detail { get; set; }

  ///

  ///作者

  ///

  public string Author { get; set; }

  ///

  /// 作者链接

  ///

  public string AuthorUrl { get; set; }

  }

  然后根据网页结构,查看XPath路径,采集内容

  ///

  /// 解析

  ///

  ///

  public List ParseCnBlogs()

  {

  var url = "";

  HtmlWeb web = new HtmlWeb();

  //1.支持从web或本地path加载html

  var htmlDoc = web.Load(url);

  var post_listnode = htmlDoc.DocumentNode.SelectSingleNode("//div[@id='post_list']");

  Console.WriteLine("Node Name: " + post_listnode.Name + "\n" + post_listnode.OuterHtml);

  var postitemsNodes = post_listnode.SelectNodes("//div[@class='post_item']");

  var articles = new List();

  var digitRegex = @"[^0-9]+";

  foreach (var item in postitemsNodes)

  {

  var article = new Article();

  var diggnumnode = item.SelectSingleNode("//span[@class='diggnum']");

  //body

  var post_item_bodynode = item.SelectSingleNode("//div[@class='post_item_body']");

  var titlenode = post_item_bodynode.SelectSingleNode("//a[@class='titlelnk']");

  var summarynode post_item_bodynode.SelectSingleNode("//p[@class='post_item_summary']");

  //foot

  var footnode = item.SelectSingleNode("//div[@class='post_item_foot']");

  var authornode = footnode.ChildNodes[1];

  var commentnode = item.SelectSingleNode("//span[@class='article_comment']");

  var viewnode = item.SelectSingleNode("//span[@class='article_view']");

  article.Diggit = int.Parse(diggnumnode.InnerText);

  article.Title = titlenode.InnerText;

  article.Url = titlenode.Attributes["href"].Value;

  article.Summary = titlenode.InnerHtml;

  article.Author = authornode.InnerText;

  article.AuthorUrl = authornode.Attributes["href"].Value;

  article.Comment = int.Parse(Regex.Replace(commentnode.ChildNodes[0].InnerText, digitRegex, ""));

  article.View = int.Parse(Regex.Replace(viewnode.ChildNodes[0].InnerText, digitRegex, ""));

  articles.Add(article);

  }

  return articles;

  }

  查看采集结果

  看到结果就惊呆了,竟然全是重复的。难道是Xpath语法理解不对么? 采集结果

  

  重温下XPath语法

  XPath 使用路径表达式在 XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的

  

  XPath 通配符可用来选取未知的 XML 元素

  

  我测试了几个语法如:

  //例1,会返回20个

  var titlenodes = post_item_bodynode.SelectNodes("//a[@class='titlelnk']");

  //会报错,因为这个a并不直接在bodynode下面,而是在子级h3元素的子级。

  var titlenodes = post_item_bodynode.SelectNodes("a[@class='titlelnk']");

  然后又实验了一种:

  //Bingo,这个可以,但是强烈指定了下级h3,这就稍微麻烦了点。

  var titlenodes = post_item_bodynode.SelectNodes("h3//a[@class='titlelnk']");

  这里就引申出了一个小问题:如何定位子级的子级?用通配符*可以么?

  //返回1个。

  var titlenodes= post_item_bodynode.SelectNodes("*//a[@class='titlelnk']")

  能正确返回1,应该是可以了,我们改下代码看下效果。

  

  然后和博客园首页数据对比,结果吻合。 所以我们可以得出结论:

  改过后代码如下:

  public List ParseCnBlogs()

  {

  var url = "";

  HtmlWeb web = new HtmlWeb();

  //1.支持从web或本地path加载html

  var htmlDoc = web.Load(url);

  var post_listnode = htmlDoc.DocumentNode.SelectSingleNode("//div[@id='post_list']");

  //Console.WriteLine("Node Name: " + post_listnode.Name + "\n" + post_listnode.OuterHtml);

  var postitemsNodes = post_listnode.SelectNodes("div[@class='post_item']");

  var articles = new List();

  var digitRegex = @"[^0-9]+";

  foreach (var item in postitemsNodes)

  {

  var article = new Article();

  var diggnumnode = item.SelectSingleNode("*//span[@class='diggnum']");

  //body

  var post_item_bodynode = item.SelectSingleNode("div[@class='post_item_body']");

  var titlenode = post_item_bodynode.SelectSingleNode("*//a[@class='titlelnk']");

  var summarynode = post_item_bodynode.SelectSingleNode("p[@class='post_item_summary']");

  //foot

  var footnode = post_item_bodynode.SelectSingleNode("div[@class='post_item_foot']");

  var authornode = footnode.ChildNodes[1];

  var commentnode = footnode.SelectSingleNode("span[@class='article_comment']");

  var viewnode = footnode.SelectSingleNode("span[@class='article_view']");

  article.Diggit = int.Parse(diggnumnode.InnerText);

  article.Title = titlenode.InnerText;

  article.Url = titlenode.Attributes["href"].Value;

  article.Summary = titlenode.InnerHtml;

  article.Author = authornode.InnerText;

  article.AuthorUrl = authornode.Attributes["href"].Value;

  article.Comment = int.Parse(Regex.Replace(commentnode.ChildNodes[0].InnerText, digitRegex, ""));

  article.View = int.Parse(Regex.Replace(viewnode.ChildNodes[0].InnerText, digitRegex, ""));

  articles.Add(article);

  }

  return articles;

  }

  源码

  代码已上传至 GitHub:

  总结

  Demo到此结束,下篇继续构思如何构建自定义规则,让用户可以在页面自己填写规则去识别。

  看完本文有收获?请转发分享给更多人

  关注「DotNet」,提升.Net技能

  

  

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线