无法在 HtmlAgilityPack C# 中使用 X-Path 获取 html 元素
Unable to get html element by using X-Path in HtmlAgilityPack C#
我正在尝试使用 x-path 树元素获取元素但显示为空,并且这种类型的 x-path 对我来说适用于其他站点,只有 2% 的站点这种类型的 X-Path 不工作,也我也尝试了来自 chrome 的 x-path,但是当我的 x-path 无法正常工作时 chrome x-path 也无法正常工作。
public static void Main()
{
string url = "http://www.ndrf.gov.in/tender";
HtmlWeb web = new HtmlWeb();
var htmlDoc = web.Load(url);
var nodetest1 = htmlDoc.DocumentNode.SelectSingleNode("/html[1]/body[1]/section[2]/div[1]/div[1]/div[1]/div[1]/div[2]/table[1]"); // i want this type // not wroking
//var nodetest2 = htmlDoc.DocumentNode.SelectSingleNode("//*[@id=\"content\"]/div/div[1]/div[2]/table"); // from Google chrome // not wroking
//var nodetest3 = htmlDoc.DocumentNode.SelectSingleNode("//*[@id=\"content\"]"); // by ID but i don't want this type // wroking
Console.WriteLine(nodetest1.InnerText); //fail
//Console.WriteLine(nodetest2.InnerText); //fail
//Console.WriteLine(nodetest3.InnerText); //proper but I don't want this type
}
在浏览器中使用时,您的 xpath 会选择整个 table。您可以缩短并使用如下 (fiddle):
using System;
using HtmlAgilityPack;
public class Program
{
public static void Main()
{
string url = "http://www.ndrf.gov.in/tender";
HtmlWeb web = new HtmlWeb();
var htmlDoc = web.Load(url);
var nodetest1 = htmlDoc.DocumentNode.SelectSingleNode("//table");
Console.WriteLine(nodetest1.InnerText);
}
}
使用Fizzler.Systems.HtmlAgilityPack
详情在这里:https://www.nuget.org/packages/Fizzler.Systems.HtmlAgilityPack/
这个库添加了名为 QuerySelector 和 QuerySelectorAll 的扩展方法,它们采用 CSS 选择器而不是 XPath。
@QHarr 建议的答案非常有效,但是使用正确的 x 路径得到 null 的原因是存在 a javascript file in the header of the site,它在 [= 周围添加了一个包装器 div
24=],并且由于在 HtmlAgilityPack 中获取结果似乎没有加载或执行 js,因此 x-path returns null.
js运行后你观察到的是:
<div class="view-content">
<div class="guide-text">
...
</div>
<div class="scroll-table1">
<!-- Your table is here -->
</div>
</div>
但是如果没有那个 js,您实际上得到的是:
<div class="view-content">
<!-- Your table is here -->
</div>
因此你的 x 路径应该是:
var nodetest1 = htmlDoc.DocumentNode.SelectSingleNode("/html[1]/body[1]/section[2]/div[1]/div[1]/div[1]/div[1]/table[1]");
Ali Bordbar 完美捕获,当我在 WebBrowser 控件中导航 URL 时,此 Url 添加了一个包装器 div 加载了所有 JavaScript 文件,
但是当我使用 HtmlWeb 加载 URL 时,加载了 JavaScript 文件的 none。
HtmlWeb 检索服务器发送的静态 HTML 响应,并且不执行任何 javascript,而 WebBrowser 会。
所以 WebBrowser 控件 HTML DOM 数据 XPath 和 HtmlWeb HTML DOM 数据 XPath 不匹配。
我的以下代码非常适合此转换
HtmlWeb web = new HtmlWeb();
web.AutoDetectEncoding = true;
HtmlAgilityPack.HtmlDocument theDoc1 = web.Load("http://www.ndrf.gov.in/tender");
var HtmlDoc = new HtmlAgilityPack.HtmlDocument();
var bodytag = theDoc1.DocumentNode.SelectSingleNode("//html");
HtmlDoc.LoadHtml(bodytag.OuterHtml);
var xpathHtmldata = HtmlDoc.DocumentNode.SelectSingleNode(savexpath); //savexpath is my first xpath make from HTML DOM data of WebBrowser control which is work for most url.
if (xpathHtmldata == null)
{
//take last tag name from first xpath
string mainele = savexpath.Substring(savexpath.LastIndexOf("/") + 1);
if (mainele.Contains("[")) { mainele = mainele.Remove(mainele.IndexOf("[")); }
//collect all tag name with name of which is sotre in mainele variable
var taglist = HtmlDoc.DocumentNode.SelectNodes("//" + mainele);
foreach (var ele in taglist) //check one by one element
{
string htmltext1 = ele.InnerText;
htmltext1 = Regex.Replace(htmltext1, @"\s", "");
htmltext1 = htmltext1.Replace("&", "&").Trim();
htmltext1 = htmltext1.Replace(" ", "").Trim();
string htmltext2 = saveInnerText; // my previus xpath text from HTML DOM data of WebBrowser control
htmltext2 = Regex.Replace(htmltext2, @"\s", "");
if (htmltext1 == htmltext2) // check equality to my previus xpath text..if it is equal thats my new xpath
{
savexpath = ele.XPath;
break;
}
}
}
我正在尝试使用 x-path 树元素获取元素但显示为空,并且这种类型的 x-path 对我来说适用于其他站点,只有 2% 的站点这种类型的 X-Path 不工作,也我也尝试了来自 chrome 的 x-path,但是当我的 x-path 无法正常工作时 chrome x-path 也无法正常工作。
public static void Main()
{
string url = "http://www.ndrf.gov.in/tender";
HtmlWeb web = new HtmlWeb();
var htmlDoc = web.Load(url);
var nodetest1 = htmlDoc.DocumentNode.SelectSingleNode("/html[1]/body[1]/section[2]/div[1]/div[1]/div[1]/div[1]/div[2]/table[1]"); // i want this type // not wroking
//var nodetest2 = htmlDoc.DocumentNode.SelectSingleNode("//*[@id=\"content\"]/div/div[1]/div[2]/table"); // from Google chrome // not wroking
//var nodetest3 = htmlDoc.DocumentNode.SelectSingleNode("//*[@id=\"content\"]"); // by ID but i don't want this type // wroking
Console.WriteLine(nodetest1.InnerText); //fail
//Console.WriteLine(nodetest2.InnerText); //fail
//Console.WriteLine(nodetest3.InnerText); //proper but I don't want this type
}
在浏览器中使用时,您的 xpath 会选择整个 table。您可以缩短并使用如下 (fiddle):
using System;
using HtmlAgilityPack;
public class Program
{
public static void Main()
{
string url = "http://www.ndrf.gov.in/tender";
HtmlWeb web = new HtmlWeb();
var htmlDoc = web.Load(url);
var nodetest1 = htmlDoc.DocumentNode.SelectSingleNode("//table");
Console.WriteLine(nodetest1.InnerText);
}
}
使用Fizzler.Systems.HtmlAgilityPack 详情在这里:https://www.nuget.org/packages/Fizzler.Systems.HtmlAgilityPack/ 这个库添加了名为 QuerySelector 和 QuerySelectorAll 的扩展方法,它们采用 CSS 选择器而不是 XPath。
@QHarr 建议的答案非常有效,但是使用正确的 x 路径得到 null 的原因是存在 a javascript file in the header of the site,它在 [= 周围添加了一个包装器 div
24=],并且由于在 HtmlAgilityPack 中获取结果似乎没有加载或执行 js,因此 x-path returns null.
js运行后你观察到的是:
<div class="view-content">
<div class="guide-text">
...
</div>
<div class="scroll-table1">
<!-- Your table is here -->
</div>
</div>
但是如果没有那个 js,您实际上得到的是:
<div class="view-content">
<!-- Your table is here -->
</div>
因此你的 x 路径应该是:
var nodetest1 = htmlDoc.DocumentNode.SelectSingleNode("/html[1]/body[1]/section[2]/div[1]/div[1]/div[1]/div[1]/table[1]");
Ali Bordbar 完美捕获,当我在 WebBrowser 控件中导航 URL 时,此 Url 添加了一个包装器 div 加载了所有 JavaScript 文件, 但是当我使用 HtmlWeb 加载 URL 时,加载了 JavaScript 文件的 none。 HtmlWeb 检索服务器发送的静态 HTML 响应,并且不执行任何 javascript,而 WebBrowser 会。 所以 WebBrowser 控件 HTML DOM 数据 XPath 和 HtmlWeb HTML DOM 数据 XPath 不匹配。
我的以下代码非常适合此转换
HtmlWeb web = new HtmlWeb();
web.AutoDetectEncoding = true;
HtmlAgilityPack.HtmlDocument theDoc1 = web.Load("http://www.ndrf.gov.in/tender");
var HtmlDoc = new HtmlAgilityPack.HtmlDocument();
var bodytag = theDoc1.DocumentNode.SelectSingleNode("//html");
HtmlDoc.LoadHtml(bodytag.OuterHtml);
var xpathHtmldata = HtmlDoc.DocumentNode.SelectSingleNode(savexpath); //savexpath is my first xpath make from HTML DOM data of WebBrowser control which is work for most url.
if (xpathHtmldata == null)
{
//take last tag name from first xpath
string mainele = savexpath.Substring(savexpath.LastIndexOf("/") + 1);
if (mainele.Contains("[")) { mainele = mainele.Remove(mainele.IndexOf("[")); }
//collect all tag name with name of which is sotre in mainele variable
var taglist = HtmlDoc.DocumentNode.SelectNodes("//" + mainele);
foreach (var ele in taglist) //check one by one element
{
string htmltext1 = ele.InnerText;
htmltext1 = Regex.Replace(htmltext1, @"\s", "");
htmltext1 = htmltext1.Replace("&", "&").Trim();
htmltext1 = htmltext1.Replace(" ", "").Trim();
string htmltext2 = saveInnerText; // my previus xpath text from HTML DOM data of WebBrowser control
htmltext2 = Regex.Replace(htmltext2, @"\s", "");
if (htmltext1 == htmltext2) // check equality to my previus xpath text..if it is equal thats my new xpath
{
savexpath = ele.XPath;
break;
}
}
}