C#爬虫(04):HtmlAgilityPack解析html文档
一、爬虫概述
C#(99):HttpClient网络HTTP请求和相应
1、使用浏览器获取页面源码
2、HTML解析组件
- HtmlAgilityPack:https://github.com/zzzprojects/html-agility-pack/
- Fizzler.Systems.HtmlAgilityPack: https://www.nuget.org/packages/Fizzler.Systems.HtmlAgilityPack
Fizzler是用于文档层次结构的W3C选择器解析器和通用选择器框架。这个包使Fizzler优于HTMLAgilityPack,为HtmlNode对象添加了QuerySelector和QuerySelectorAll(来自选择器API Level 1)。 - Jumony(2014年不更新了):https://github.com/Ivony/Jumony
二、HtmlAgilityPack介绍
参考:
GitHub:https://github.com/zzzprojects/html-agility-pack/releases
官网:https://html-agility-pack.net/
https://www.nuget.org/packages/HtmlAgilityPack/
HtmlAgilityPack(以下简称HAP)是一个基于.Net的、第三方免费开源的微型类库,主要用于在服务器端解析html文档。
HtmlAgilityPack为网页提供了标准的DOM API和XPath导航 。使用WebBrowser和HttpWebRequest下载的网页可以用Html Agility Pack来解析。
Xpath表达式的参考文档可见:https://www.cnblogs.com/springsnow/p/11810458.html#_label0
三、属性和方法
HtmlAgilityPack中的HtmlNode类与XmlNode类差不多,HtmlDocument类与XmlDocument类差不多。
参考:https://www.cnblogs.com/springsnow/p/12883050.html
1、属性:
- OwnerDocument:节点所在的HtmlDocument文档
- Attributes: 获取节点的属性集合
- ParentNode:获取该节点的父节点
- ChildNodes:获取子节点集合(包括文本节点)
- FirstChild: 获取第一个子节点
- LastChild: 获取最后一个子节点
- Id: 获取该节点的Id属性
- Name:Html元素名
- NodeType: 获取该节点的节点类型
- InnerHtml: 获取该节点的Html代码
- InnerText: 获取该节点的内容,与InnerHtml不同的地方在于它会过滤掉Html代码,而InnerHtml是连Html代码一起输出
- OuterHtml: 整个节点的代码
- PreviousSibling: 获取前一个兄弟节点
- NextSibling: 获取下一个兄弟节点
- HasAttributes :判断该节点是否含有属性
- HasChildNodes: 判断该节点是否含有子节点
- HasClosingAttributes : 判断该节点的关闭标签是否含有属性(</xxx class="xxx">)
- Closed:该节点是否已关闭(</xxx>)
- ClosingAttributes在关闭标签的属性集合StreamPosition: 该节点位于整个Html文档的字符位置
- XPath: 根据节点返回该节点的XPath
2、方法:
- Load (string path): 从路径中加载一个文档
- SelectNodes (string xpath): 根据XPath获取一个节点集合
- SelectSingleNode (string xpath): 根据XPath获取唯一的一个节
- Ancestors (): 返回此元素的所有上级节点的集合。
- DescendantNodes (): 获取所有子代节点
- Element (string name): 根据参数名获取一个元素
- Elements (string name): 根据参数名获取匹配的元素集合
- GetAttributeValue(string name, bool def): 帮助方法,用来获取此节点的属性的值(布尔类型)。如果未找到该属性,则将返回默认值。
- ChildAttributes(string name): 获取所有子元素的属性(参数名要与元素名匹配)
- IsEmptyElement(string name): 确定是否一个空的元素节点。
- IsOverlappedClosingElement(string text): 确定是否文本对应于一个节点可以保留重叠的结束标记。
- AppendChild(HtmlNode newChild): 将参数元素追加到为调用元素的子元素(追加在最后)
- PrependChild(HtmlNode newChild): 将参数中的元素作为子元素,放在调用元素的最前面
- Clone(): 本节点克隆到一个新的节点
- CopyFrom(HtmlNode node): 创建重复的节点和其下的子树。
- CreateNavigator(): 返回的一个对于此文档的XPathNavigator
- CreateNode(string html): 静态方法,允许用字符串创建一个新节点
- CreateRootNavigator(): 创建一个根路径的XPathNavigator
- InsertAfter(HtmlNode newChild, HtmlNode refChild): 将一个节点插入到第二个参数节点的后面,与第二个参数是兄弟关系
- InsertBefore(HtmlNode newChild, HtmlNode refChild): 将一个节点插入到第二个参数节点的后面,与第二个参数是兄弟关系
- Remove(): 从父集合中移除调用节点
- SetAttributeValue(string name, string value): 设置调用节点的属性
- WriteContentTo(): 将该节点的所有子级都保存到一个字符串中。
- WriteTo(): 将当前节点保存到一个字符串中。
- Save(string filename): 将HTML文档保存到指定的路径
四、用法举例
下面是几个简单使用说明:
1、获取网页title:
doc.DocumentNode.SelectSingleNode("//title").InnerText;//XPath中:“//title”表示所有title节点。SelectSingleNode用于获取满足条件的唯一的节点。
2、获取所有的超链接:
doc.DocumentNode.Descendants("a")
3、获取name为kw的input,也就是相当于getElementsByName():
var kwBox = doc.DocumentNode.SelectSingleNode("//input[@name='kw']");
示例:
private void Form1_Load(object sender, EventArgs e)
{
List<Result> list = new List<Result>();
HtmlWeb htmlWeb = new HtmlWeb();
htmlWeb.OverrideEncoding = Encoding.UTF8;//编码,这里网上有些很多写法都不正确
HtmlAgilityPack.HtmlDocument htmlDoc = htmlWeb.Load(@http://www.cnblogs.com/);
//选择博客园首页文章列表
htmlDoc.DocumentNode.SelectNodes("//div[@id='post_list']/div[@class='post_item']").//双斜杠“//”表示从跟节点开始查找
AsParallel().ToList().ForEach(ac =>
{
//抓取图片,因为有空的,所以拿变量存起来
HtmlNode node = ac.SelectSingleNode(".//p[@class='post_item_summary']/a/img");
list.Add(new Result
{
url = ac.SelectSingleNode(".//a[@class='titlelnk']").Attributes["href"].Value,
title = ac.SelectSingleNode(".//a[@class='titlelnk']").InnerText,
//图片如果为空,显示默认图片
img = node == null ? "http ://www.cnblogs.com//Content/img/avatar.png" : node.Attributes["src"].Value,
content = ac.SelectSingleNode(".//p[@class='post_item_summary']").InnerText
});
}); foreach (Result item in list)
{
this.listBox1.Items.Add(item.title);
}
}
/// <summary>
/// 页面抓取结果
/// </summary>
public class Result
{
/// <summary>
/// 链接
/// </summary>
public string url { get; set; }
/// <summary>
/// 标题
/// </summary>
public string title { get; set; }
/// <summary>
/// 头像地址
/// </summary>
public string img { get; set; }
/// <summary>
/// 正文内容
/// </summary>
public string content { get; set; }
}
示例2:下载微软文档
using HtmlAgilityPack;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text; namespace ConsoleApp4
{
internal class Program
{
private static void Main(string[] args)
{
//网页地址:
string Url = "https://docs.microsoft.com/zh-cn/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/implementing-inheritance-with-the-entity-framework-in-an-asp-net-mvc-application"; List<string> list = new List<string>(); ;
HtmlWeb htmlWeb = new HtmlWeb();
htmlWeb.OverrideEncoding = Encoding.UTF8; HtmlDocument htmlDoc = htmlWeb.Load(Url); HtmlNode node = htmlDoc.DocumentNode.SelectSingleNode("//main[@id='main']"); //去掉英文翻译
var a = node.SelectNodes("//span[@class='sxs-lookup']");
foreach (HtmlNode b in a) {
b.Remove();
} string src = "";
//图片相对路径改成绝对路径
var imgNode = node.SelectNodes("//img[@data-linktype='relative-path']");
foreach (HtmlNode node1 in imgNode)
{
src = node1.GetAttributeValue("src", "");
var url = new Uri(htmlWeb.ResponseUri, src);
node1.SetAttributeValue("src", url.AbsoluteUri);
} //链接路径转换
var hrefNode = node.SelectNodes("//a[@data-linktype='relative-path']|//a[@data-linktype='absolute-path']");
foreach (HtmlNode node1 in hrefNode)
{
src = node1.GetAttributeValue("href", "");
var url = new Uri(htmlWeb.ResponseUri, src);
node1.SetAttributeValue("href", url.AbsoluteUri);
} //找到所有的H2标签,然后加上顺序。
var h2Node = node.SelectNodes("//h2");
var arr = new string[] { "一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "二十" };
if (h2Node != null)
{
for (int i = 0; i < h2Node.Count; i++)
{
h2Node[i].InnerHtml = arr[i] + "、" + h2Node[i].InnerHtml;
//找到所有的H3标签,然后加上顺序。 var h3Node = h2Node[i].SelectNodes("following-sibling::h2|following-sibling::h3");
if (h3Node is null)
break;
for (int j = 0; j < h3Node.Count; j++)
{
if (h3Node[j].Name == "h2")
break;
else
h3Node[j].InnerHtml = (j + 1) + "、" + h3Node[j].InnerHtml;
}
}
}
HtmlNode myNOde = htmlDoc.CreateElement("div"); //去掉前面无用的部分
var OK = node.SelectNodes("nav[1]/following-sibling::*");
myNOde.AppendChildren(OK); //添加原文连接:
HtmlNode nodeOriUrl = htmlDoc.CreateElement("p");
nodeOriUrl.InnerHtml = "原文:<a href='" + htmlWeb.ResponseUri + "'>" + htmlWeb.ResponseUri + "</a>";
myNOde.PrependChild(nodeOriUrl); //写入到本地文件
TextWriter wr = new StreamWriter(@"aa.html");
myNOde.WriteTo(wr);
wr.Close();
}
}
}
五、Fizzler.Systems.HtmlAgilityPack:
Hazz为HTMLAgilityPack实现CSS选择器。它基于Fizzler,一个通用的CSS选择器解析器和生成器库。
Hazz以前称为Fizzler.Systems.HtmlAgilityPack。
// Load the document using HTMLAgilityPack as normal
var html = new HtmlDocument();
html.LoadHtml(@"
<html>
<head></head>
<body>
<div>
<p class='content'>Fizzler</p>
<p>CSS Selector Engine</p></div>
</body>
</html>"); // Fizzler for HtmlAgilityPack is implemented as the
// QuerySelectorAll extension method on HtmlNode var document = html.DocumentNode; // yields: [<p class="content">Fizzler</p>]
document.QuerySelectorAll(".content"); // yields: [<p class="content">Fizzler</p>,<p>CSS Selector Engine</p>]
document.QuerySelectorAll("p"); // yields empty sequence
document.QuerySelectorAll("body>p"); // yields [<p class="content">Fizzler</p>,<p>CSS Selector Engine</p>]
document.QuerySelectorAll("body p"); // yields [<p class="content">Fizzler</p>]
document.QuerySelectorAll("p:first-child");
C#爬虫(04):HtmlAgilityPack解析html文档的更多相关文章
- HtmlAgilityPack解析html文档
一.概述 HtmlAgilityPack(以下简称HAP)是一个基于.Net的.第三方免费开源的微型类库,主要用于在服务器端解析html文档. HtmlAgilityPack为网页提供了标准的DOM ...
- #爬虫必备,解析html文档----beautifulsoup的简单用法
#出处:http://mp.weixin.qq.com/s?__biz=MjM5NzU0MzU0Nw==&mid=201820961&idx=2&sn=b729466f334d ...
- .Net解析html文档类库HtmlAgilityPack完整使用说明
在前几篇文章中([搜房网房产数据采集程序demo--GeckoWebBrowser实例] )都有提到一个解析html的C#类库HtmlAgilityPack, 今天终于有时间整理一下,并把Demo分享 ...
- 网络电视精灵~分析~~~~~~简单工厂模式,继承和多态,解析XML文档,视频项目
小总结: 所用技术: 01.C/S架构,数据存储在XML文件中 02.简单工厂模式 03.继承和多态 04.解析XML文档技术 05.深入剖析内存中数据的走向 06.TreeView控件的使用 核心: ...
- Apache-Tika解析Word文档
通常在使用爬虫时,爬取到网上的文章都是各式各样的格式处理起来比较麻烦,这里我们使用Apache-Tika来处理Word格式的文章,如下: package com.mengyao.tika.app; i ...
- Apache-Tika解析HTML文档
通常在使用爬虫时,爬取到网上的文章都是各式各样的格式处理起来比较麻烦,这里我们使用Apache-Tika来处理HTML格式的文章,如下: package com.mengyao.tika.app; i ...
- Apache-Tika解析XML文档
通常在使用爬虫时,爬取到网上的文章都是各式各样的格式处理起来比较麻烦,这里我们使用Apache-Tika来处理XML格式的文章,如下: package com.mengyao.tika.app; im ...
- Apache-Tika解析Excell文档
通常在使用爬虫时,爬取到网上的文章都是各式各样的格式处理起来比较麻烦,这里我们使用Apache-Tika来处理Excell格式的文章,如下: package com.mengyao.tika.app; ...
- Apache-Tika解析PDF文档
通常在使用爬虫时,爬取到网上的文章都是各式各样的格式处理起来比较麻烦,这里我们使用Apache-Tika来处理PDF格式的文章,如下: package com.mengyao.tika.app; im ...
随机推荐
- java多态概述特点转型I
1 package face_09; 2 3 import com.sun.jdi.Method; 4 5 /* 6 * 对象的多态性. 7 * class 动物 8 * {} 9 * 10 * cl ...
- 业务驱动的全景监控体系在阿里的应用 | 阿里巴巴DevOps实践指南
编者按:本文源自阿里云云效团队出品的<阿里巴巴DevOps实践指南>,扫描上方二维码或前往:https://developer.aliyun.com/topic/devops,下载完整版电 ...
- JVM诊断及工具笔记(2)使用arthas定位哪里执行了System#gc()
笔者是汽车之家实时计算平台的一名小伙伴.负责flink平台,数据湖及kafka平台的设计与开发.平时擅长做平台设计,定位及解决各种疑难杂症.第二篇文章,讲的点依旧很小,但是这次图多!!! 在这里感谢支 ...
- Java 继承01
继承 ●示例 class Person { public String name; Person(){ System.out.println("Person Constrctor...&qu ...
- js源码-数组中的push()和unshift()方法的源码实现
人话不多,直接上代码,在代码中解析,不足之处请谅解: push() Array.prototype._push=function(...value){//在Array原型链上添加_push方法 for ...
- STL priority_queue 优先队列 小记
今天做题发现一个很有趣的地方,竟然还是头一次发现,唉,还是太菜了. 做图论用STL里的priority_queue去优化prim,由于特殊需求,我需要记录生成树中是用的哪些边. 于是,我定义的优先队列 ...
- StarUML官网地址 http://staruml.io/
StarUML官网地址 http://staruml.io/
- Maven 警告 expected START_TAG or END_TAG not TEXT
原因 在Maven警告提示区域存在空格等不规范字符,在网上复制到项目中时经常出现类似问题. pop.xml文件,setting.xml文件极易出现此类问题. 解决 将空格删除,规范一下格式就好了. 示 ...
- js修改css
转载请注明来源:https://www.cnblogs.com/hookjc/ <style type="text/css"> .style{font-size:9pt ...
- CSS:第1课
CSS选择器有:id选择器.派生选择器 1.id选择器 id 选择器可以为标有特定 id 的 HTML 元素指定特定的样式. id 选择器以 "#" 来定义. #red {colo ...