使用HTML Agility包從HTML表單中提取數據

c# html html-agility-pack winforms

我正在嘗試使用HTML agility pack動態列出HTML表單中的所有節點,這意味著我不知道屬性的名稱和輸入名稱。問題是當我想獲得與輸入相對應的標籤時。

<form name="input" action="html_form_action.asp" method="get">
Username: <input type="text" name="user" />
<input type="submit" value="Submit" />
</form>

所以在這裡我想寫用戶名然後輸入,在這個例子中看起來很明顯,但有時他們不是直接的兄弟姐妹,會有很多隱藏的輸入或其他標籤。

另一個例子:

<form name="input" action="html_form_action.asp" method="get">
Username: <input type="text" name="user" />
<input type="submit" value="Submit" />
</form>

我在我的項目中使用C#winforms。

我有一些想法,但他們會花很多時間,所以我想,因為我是HTML敏捷包的新手,有一種方法或一些捷徑可以得到它,,任何建議?

熱門答案

這樣的事情應該有效。

static IEnumerable<Tuple<string, HtmlNode>> GetInputNodes(HtmlDocument doc, params string[] fields)
{
    var form = doc.DocumentNode.SelectSingleNode("//form");
    foreach (var field in fields)
    {
        var fieldNode = form.ChildNodes
            .OfType<HtmlTextNode>()
            .Where(node => node.Text.Trim().StartsWith(field, StringComparison.OrdinalIgnoreCase))
            .SingleOrDefault();
        if (fieldNode == null)
            continue;

        var input = FindCorrespondingInputNode(fieldNode);
        if (input != null)
            yield return Tuple.Create(field, input);
    }
}

static HtmlNode FindCorrespondingInputNode(HtmlTextNode fieldNode)
{
    for (var currentNode = fieldNode.NextSibling;
         currentNode != null && currentNode.NodeType != HtmlNodeType.Text;
         currentNode = currentNode.NextSibling)
    {
        if (currentNode.Name == "input"
         && !currentNode.Attributes["type"].Value.Contains("hidden"))
        {
            return currentNode;
        }
    }
    return null;
}

然後使用它,只需傳入要獲取輸入元素的字段的名稱。

static IEnumerable<Tuple<string, HtmlNode>> GetInputNodes(HtmlDocument doc, params string[] fields)
{
    var form = doc.DocumentNode.SelectSingleNode("//form");
    foreach (var field in fields)
    {
        var fieldNode = form.ChildNodes
            .OfType<HtmlTextNode>()
            .Where(node => node.Text.Trim().StartsWith(field, StringComparison.OrdinalIgnoreCase))
            .SingleOrDefault();
        if (fieldNode == null)
            continue;

        var input = FindCorrespondingInputNode(fieldNode);
        if (input != null)
            yield return Tuple.Create(field, input);
    }
}

static HtmlNode FindCorrespondingInputNode(HtmlTextNode fieldNode)
{
    for (var currentNode = fieldNode.NextSibling;
         currentNode != null && currentNode.NodeType != HtmlNodeType.Text;
         currentNode = currentNode.NextSibling)
    {
        if (currentNode.Name == "input"
         && !currentNode.Attributes["type"].Value.Contains("hidden"))
        {
            return currentNode;
        }
    }
    return null;
}

只是一個警告,似乎HtmlAgilityPack並沒有像它應該的那樣關閉表單。因此,您必須指定在加載html之前應關閉表單元素。沒有它,HAP將無法識別該表單有任何子節點。

static IEnumerable<Tuple<string, HtmlNode>> GetInputNodes(HtmlDocument doc, params string[] fields)
{
    var form = doc.DocumentNode.SelectSingleNode("//form");
    foreach (var field in fields)
    {
        var fieldNode = form.ChildNodes
            .OfType<HtmlTextNode>()
            .Where(node => node.Text.Trim().StartsWith(field, StringComparison.OrdinalIgnoreCase))
            .SingleOrDefault();
        if (fieldNode == null)
            continue;

        var input = FindCorrespondingInputNode(fieldNode);
        if (input != null)
            yield return Tuple.Create(field, input);
    }
}

static HtmlNode FindCorrespondingInputNode(HtmlTextNode fieldNode)
{
    for (var currentNode = fieldNode.NextSibling;
         currentNode != null && currentNode.NodeType != HtmlNodeType.Text;
         currentNode = currentNode.NextSibling)
    {
        if (currentNode.Name == "input"
         && !currentNode.Attributes["type"].Value.Contains("hidden"))
        {
            return currentNode;
        }
    }
    return null;
}



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