写在前面
HtmlAgilityPack是一个HTML解析类库,日常用法就是爬虫获取到内容后,先用XPath获取目标节点,再用正则进行匹配;使用XPath的目的主要是将目标节点或内容限定在一个较小的范围,如果一上来就用正则那效率肯定不行,因为正则的规则设计耗时较长;而XPath直接可以用浏览器F12开发者工具窗口,鼠标右键复制XPath获得,非常方便。但在微观内容的操作上XPath就显得太粗糙了,这时候就需要用正则来匹配,由于范围已经用XPath做过了筛选,所以此时的正则规则的设计要考虑的就很少了;两者结合效率就大大提升了,解析HTML源码实在是个耗时费力的体力活。
老套路通过NuGet获取类库
代码实现
using HtmlAgilityPack;public static class HtmlDocumentMgr{#region Public Methodspublic static HtmlNodeCollection GetNodes(string xPath){var body = BrowserController.GetFrameBody();var doc = GetHtmlDocument(body);return doc.DocumentNode.SelectNodes(xPath);}public static HtmlNode GetNode(string xPath){var body = BrowserController.GetFrameBody();var doc = GetHtmlDocument(body);return doc.DocumentNode.SelectSingleNode(xPath);}public static HtmlDocument GetHtmlDocument(string html){var doc = new HtmlDocument();doc.LoadHtml(html);return doc;}#endregion}
HTML 内容可以是独立爬虫直接获取的,也可以从内嵌浏览器中获得,本文采用内嵌浏览器的方式,获得HTML的代码如下,仅做参考示意。
public static string GetFrameBody(){var js = "document.querySelector('body').outerHTML";var evalRet = Browser.MainFrame.EvaluateScriptAsync(js);evalRet.Wait();if (evalRet.Result != null){var ret = evalRet.Result.Result;return ret.ToNormalString();}return string.Empty;}
调用示例
public static HtmlNode GetDescribeNode(string describe){var body = BrowserController.GetFrameBody();var doc = new HtmlDocument();doc.LoadHtml(body);var match = string.Format(".//label[contains(text(), \"{0}\")]", describe);var labelNode = doc.DocumentNode.SelectSingleNode(match);if (labelNode == null && describe.Contains(" ")){describe = describe.Replace(" ", " ");match = string.Format(".//label[contains(text(), \"{0}\")]", describe);labelNode = doc.DocumentNode.SelectSingleNode(match);}return labelNode;}