使用HTML AgilityPack按分隔線解析HTML

c# html-agility-pack parsing

我試圖解析特定HTML字符串,這樣我可以提取一組被打散線<br/>斷裂線。輸入HTML如下所示:

<div class="PlainText">
  DATE: 2013-10-28 20:00:43 -0500 <br/>
  Item 1: Text1 <br/>
  Item 1: Text1 <br/>
  Item 1: Text1 <br/>
  Item 1: Text1 <br/>
  <br/> //Notice this has two break lines, i would like to stop after seeing two consecutive break lines.
</div>

使用更大的html文檔中的div,我能夠獲得HTML ChildNodes

List<HtmlNode> nodes = htmlDoc.DocumentNode
                                    .Descendants("div")
                                    .Where(x => x.Attributes.Contains("class") &&
                                            x.Attributes["class"].Value.Contains("PlainText")).ToList();

我不完全確定從哪裡開始,我想閱讀所有文本,直到我看到兩個分隔線並停止?

編輯

我看著的childNodes nodes在Visual Studio中運行時檢查,發現裡面居然是不是兩個consectuive <br/>線,但單斷線和#text與它的innerHTML存在標籤\n換行符。

在此處輸入圖像描述

一般承認的答案

這樣的事情應該有效

[Test]
public void Test()
{
    var x = ReadTillTwoBr(GetDivClass()).ToList();
}

public HtmlNode GetDivClass()
{
    var html = @"<html><div class=""PlainText"">
            DATE: 2013-10-28 20:00:43 -0500 <br/>
            Item 1: Text1 <br/>
            Item 1: Text1 <br/>
            Item 1: Text1 <br/>
            Item 1: Text1 <br/>
            <br   /> //Notice this has two break lines, i would like to stop after seeing two consecutive break lines.
            Item 3
        </div></html>";
    var doc = new HtmlDocument();
    doc.LoadHtml(html);

    return doc.DocumentNode
                .Descendants("div").First(x => x.Attributes.Contains("class") &&
                                                x.Attributes["class"].Value.Contains("PlainText"));

}

public IEnumerable<string> ReadTillTwoBr(HtmlNode node)
{
    var nonEmptyNodes =
        node.ChildNodes.Except(node.ChildNodes.Where(f => f.Name == "#text" && String.IsNullOrWhiteSpace(f.InnerHtml)))
            .ToList();

    foreach (var n in nonEmptyNodes)
    {
        if (IsBr(n) && IsBr(n.NextSibling))
        {
            yield break;
        }

        if (n.Name == "#text")
        {
            yield return n.InnerText.Trim();
        }
    }
}

public bool IsBr(HtmlNode n)
{
    return n != null && n.NodeType == HtmlNodeType.Element && n.Name == "br";
}

哪個回報

在此處輸入圖像描述

請注意在兩個br之後它沒有返回註釋

編輯:

我刪除了空的#text值,因為當你在最後兩個br標籤之間有換行符時,你實際上得到了帶有換行符的#text標籤。我認為這是新行混淆的地方。


熱門答案

您可以使用XPath //div[@class='PlainText']來獲取所需的div節點。您還可以在從div獲取子節點時檢查下一個兄弟節點:

HtmlDocument doc = new HtmlDocument();
doc.Load("index.html");
Func<HtmlNode, bool> notTwoBrakes = 
    n => (n.Name != "br" || n.NextSibling != null && n.NextSibling.Name != "br");
var nodes = doc.DocumentNode.SelectNodes("//div[@class='PlainText']")
               .Select(div => div.ChildNodes.TakeWhile(notTwoBrakes));

我不使用內聯lambda只是為了提高可讀性。條件的工作方式如下:

  • 檢查下一個節點是否為空,如果為空,則獲取當前節點
  • 檢查下一個節點是否為br節點,如果不是 - 請獲取當前節點
  • 檢查當前節點是否為br節點,如果不是 - 獲取當前節點
  • 否則停止服用子節點

結果:

在此處輸入圖像描述



許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因