以对象的方式访问html中的标签,比正则表达式更好用的方式获取html中的内容,linq方式直接获取所有的链接,更加先进的c#版本爬虫开源库

  • 以对象的方式访问html中的标签,比正则表达式更好用的方式获取html中的内容,linq方式直接获取所有的链接,更加先进的c#版本爬虫开源库已关闭评论
  • 29 次浏览
  • A+
所属分类:.NET技术
摘要

这是我本人自己写的一个开源库,现已经发布到nuget,可以直接在vs的nuget包管理中搜索到,或者可以到nuget官网下载:https://www.nuget.org/packages/ZmjConvert/,也可以到我的个人网站上下载源码:https://www.zhaimaojun.cn/P/C%23%e6%a0%87%e7%ad%be%e7%b1%bb%e6%96%87%e6%9c%ac%e5%ba%8f%e5%88%97%e5%8c%96%e5%ba%93/

这是我本人自己写的一个开源库,现已经发布到nuget,可以直接在vs的nuget包管理中搜索到,或者可以到nuget官网下载:https://www.nuget.org/packages/ZmjConvert/,也可以到我的个人网站上下载源码:https://www.zhaimaojun.cn/P/C%23%e6%a0%87%e7%ad%be%e7%b1%bb%e6%96%87%e6%9c%ac%e5%ba%8f%e5%88%97%e5%8c%96%e5%ba%93/

本包是.NET standard标准库包,可以在.NET core,.NET,.NET framework等多种项目中直接使用,我本人也是在多种环境中使用这个包,没有任何问题的,我本人主要用来提取网页上的链接,图片,可显示文本等内容。

先安装这个包,然后就可以使用了,下面给出了一些使用方式的模板:

第一步 序列化html

/**这是html源码的序列化*/
1
var dts = GetSource();//获取html源码,可以现下或者读取html文件,dts需要是string类型的html内容 2 if (!HtmlElement.TryParse(dts, out var eles, out var err)) 3 { 4 OnDownloadErrorHappend($"无法序列化url:{surl}");//反序列化失败 5 return; 6 } 7 var srcurl = new Uri(surl);//这是html的源地址的当前文档的url,用于将当前所有节点中相对路径解析为绝对路径时使用 8 eles = HtmlElement.GetAllElement(eles);//列出所有的子元素,就是将所有的节点提取为一个list,方便使用linq,或者使用foreach循环来遍历,当然原来的标签结构是不会改变的。

 1 /**这是部分html标签源码的反序列化,比如富文本编辑器的内容*/  2 try  3 {  4     var labstr = Gethtmlstr();//获取部分标签的html源码,比如富文本编辑器  5     var eles = CHtmlElement<HtmlElement>.Parse(htmlstr);//反序列化标签组  6     return eles;//反序列化成功后返回结构对象  7 }  8 catch (Exception e)  9 { 10     throw e;//反序列化失败 11 }

第二步 获取html文档的标题

1 var title = HtmlElement.GetWebTitle(eles);

1 /**获取文档的keywords*/ 2 eles.FirstOrDefault(x => x.TagName == "meta" && x.Attributes.ContainsKey("name") && x.Attributes["name"].ToLower() == "keywords").Attributes.TryGetValue("content", out var keywords); 3 /**获取文档的description*/ 4 eles.FirstOrDefault(x => x.TagName == "meta" && x.Attributes.ContainsKey("name") && x.Attributes["name"].ToLower() == "description").Attributes.TryGetValue("content", out var description);

第三步 提取所有的img标签的src,也就是获取所有页面上的图片

1 /**这是获取所有img标签的src属性内容*/ 2 var imgs = new List<string>(); 3 foreach (var e in eles.Where(x => x.TagName == "img" && x.Attributes.ContainsKey("src") && !string.IsNullOrWhiteSpace(x.Attributes["src"]))) 4 {//封面图片或者其他图片 5     var furl = HttpUtility.HtmlDecode(e.Attributes["src"]); 6     var furi = new Uri(srcurl, furl); 7     imgs.Add(furi.AbsoluteUri); 8 }

/**这是提取所有img标签的data-src属性,因为有些网站为了降低流量成本,img标签的src属性中使用的是缩略图,而data-src中使用的才是原图*/
1
var imgs = new List<string>(); 2 foreach (var e in eles.Where(x => x.TagName == "img" && x.Attributes.ContainsKey("data-src") && !string.IsNullOrWhiteSpace(x.Attributes["data-src"]))) 3 {//封面图片或者其他图片 4 var furl = HttpUtility.HtmlDecode(e.Attributes["data-src"]); 5 var furi = new Uri(srcurl, furl); 6 imgs.Add(furi.AbsoluteUri); 7 }

第四步 提取所有的a标签的href,也就是获取所有页面上的链接

1 /**获取所有的链接及链接的文本内容*/ 2 var links = new Dictionary<string, string>(); 3 foreach (var e in eles.Where(x => x.TagName == "a" && x.Attributes.ContainsKey("href") && !string.IsNullOrWhiteSpace(x.Attributes["href"]))) 4 { 5     links.Add(WebUtility.HtmlDecode(e.InnerText), WebUtility.HtmlDecode(e.Attributes["href"])); 6 }

第五步 提取所有可视文本,并保持换行,并且保持链接的有效

 1 /**提取所有的可视文本*/  2 var tsts = new List<string>();//这是按行存储的提取到的所有可视内容  3 var sb = new StringBuilder();//这是中间使用的拼接对象  4 foreach (var item in eles)//eles为整个html反序列化后的列表,如果需要对指定的一个div或者p的可视内容提取,可以先找到这个标签对象,然后在通过HtmlElement.GetAllElement(e.Children)可提取他的所有子标签,就可以提取所有可视内容了  5 {  6     var tgs = new[] { "br", "div", "li", };//这是强迫换行的标签列举,可根据需求添加或减少  7     if (tgs.Contains(item.TagName))  8     {  9         sb.Append(HttpUtility.HtmlDecode(item.InnerText)); 10         var innt = sb.ToString(); 11         tsts.Add(innt); 12         sb.Clear(); 13     } 14     else if (item.TagName == "a" && item.Attributes.ContainsKey("href") && !item.Attributes["href"].Contains("f95")) sb.Append($"<a href="{WebUtility.HtmlDecode(item.Attributes["href"])}">{WebUtility.HtmlDecode(item.InnerText)}</a>"); 15     else if (!item.InnerText.Contains('<')) sb.Append(HttpUtility.HtmlDecode(item.InnerText)); 16 }

第六步 找到特定的标签

1 /**查找包含main-content样式类的div*/ 2 var e = eles.FirstOrDefault(x => x.TagName == "div" && x.Attributes.ContainsKey("class") && x.Attributes["class"].ToLower().Contains("main-content"));

/**查找id为mainp的p标签*/ var e = eles.FirstOrDefault(x => x.TagName == "p" && x.Attributes.ContainsKey("id") && x.Attributes["id"].ToLower() == "mainp");

第七步 请随意发挥~