C# HtmlNode 解析抛出 Collection was modified 错误
C# HtmlNode parsing throws Collection was modified error
我觉得这有点奇怪。我有一个 HtmlDocument
,在解析时我得到:
System.InvalidOperationException: 'Collection was modified; enumeration operation may not execute.'
令我感到奇怪的是,我没有遍历从我的代码返回的列表,但我仍然收到此错误。
using (HttpClient client = new HttpClient())
{
using (HttpResponseMessage response = await client.GetAsync(url))
{
response.EnsureSuccessStatusCode(); // Throw if httpcode is an error
using (HttpContent content = response.Content)
{
string result = await content.ReadAsStringAsync();
var website = new HtmlDocument();
website.LoadHtml(result);
//Thread.Sleep(5000);
List<HtmlNode>topbar = website.DocumentNode.Descendants("div").FirstOrDefault(o => o.GetAttributeValue("class", "") == "valueofClass")
.Descendants("div").FirstOrDefault(o => o.GetAttributeValue("class", "") == "valueofClass").Elements("section").ToList();
//loop
}
}
}
如果我添加 Sleep
代码似乎没有任何问题,这让我认为 LoadHtml
仍在后台工作,或者我正在执行某种 javascript
,我不是。
您是否尝试过在查询后两次使用 SelectNodes
而不是 运行 Descendants
来获取 HtmlNodeCollection
以获取单个节点。
using (HttpContent content = response.Content)
{
string result = await content.ReadAsStringAsync();
var website = new HtmlDocument();
website.LoadHtml(result);
HtmlNodeCollection topbar = website.DocumentNode.SelectNodes("//div[@class='valueofClass']//section");
if (topbar != null)
foreach (HtmlNode node in topbar)
{
....
}
}
topbar 包含 div
名称 valueofClass
包含标签 section
的所有可能节点的列表,这就是我假设您正在尝试使用 Descendants 和 FirstOrDefault 查找。
我看到的另一件事是,在您的 FirstOrDefault
语句中,您正在对字符串使用 ==
比较。如果您想使用 Descendants 路线,我建议使用 .Equals()
来正确比较两个字符串。如果您的比较在第一个 FirstOrDefault
语句中给出空值,那么第二个 Descendants
将失败并显示 Object reference not set to instance of an object.
更新:
如果你想对多个后代使用你的语句,我建议使用 ToList()
转换后代的 IEnumerable
结果,然后用 FirstOrDefault() 过滤它。这将有助于解决您遇到的错误。
website.DocumentNode
.Descendants("div").ToList()
.FirstOrDefault(o => o.GetAttributeValue("class", "") == "valueofClass")
.Descendants("div").ToList()
.FirstOrDefault(o => o.GetAttributeValue("class", "") == "valueofClass")
.Elements("section").ToList();
我觉得这有点奇怪。我有一个 HtmlDocument
,在解析时我得到:
System.InvalidOperationException: 'Collection was modified; enumeration operation may not execute.'
令我感到奇怪的是,我没有遍历从我的代码返回的列表,但我仍然收到此错误。
using (HttpClient client = new HttpClient())
{
using (HttpResponseMessage response = await client.GetAsync(url))
{
response.EnsureSuccessStatusCode(); // Throw if httpcode is an error
using (HttpContent content = response.Content)
{
string result = await content.ReadAsStringAsync();
var website = new HtmlDocument();
website.LoadHtml(result);
//Thread.Sleep(5000);
List<HtmlNode>topbar = website.DocumentNode.Descendants("div").FirstOrDefault(o => o.GetAttributeValue("class", "") == "valueofClass")
.Descendants("div").FirstOrDefault(o => o.GetAttributeValue("class", "") == "valueofClass").Elements("section").ToList();
//loop
}
}
}
如果我添加 Sleep
代码似乎没有任何问题,这让我认为 LoadHtml
仍在后台工作,或者我正在执行某种 javascript
,我不是。
您是否尝试过在查询后两次使用 SelectNodes
而不是 运行 Descendants
来获取 HtmlNodeCollection
以获取单个节点。
using (HttpContent content = response.Content)
{
string result = await content.ReadAsStringAsync();
var website = new HtmlDocument();
website.LoadHtml(result);
HtmlNodeCollection topbar = website.DocumentNode.SelectNodes("//div[@class='valueofClass']//section");
if (topbar != null)
foreach (HtmlNode node in topbar)
{
....
}
}
topbar 包含 div
名称 valueofClass
包含标签 section
的所有可能节点的列表,这就是我假设您正在尝试使用 Descendants 和 FirstOrDefault 查找。
我看到的另一件事是,在您的 FirstOrDefault
语句中,您正在对字符串使用 ==
比较。如果您想使用 Descendants 路线,我建议使用 .Equals()
来正确比较两个字符串。如果您的比较在第一个 FirstOrDefault
语句中给出空值,那么第二个 Descendants
将失败并显示 Object reference not set to instance of an object.
更新:
如果你想对多个后代使用你的语句,我建议使用 ToList()
转换后代的 IEnumerable
结果,然后用 FirstOrDefault() 过滤它。这将有助于解决您遇到的错误。
website.DocumentNode
.Descendants("div").ToList()
.FirstOrDefault(o => o.GetAttributeValue("class", "") == "valueofClass")
.Descendants("div").ToList()
.FirstOrDefault(o => o.GetAttributeValue("class", "") == "valueofClass")
.Elements("section").ToList();