使用HTML Agility包从HTML表单中提取数据

时间:2011-11-08 15:38:43

标签: c# html winforms html-agility-pack

我正在尝试使用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>

所以在这里我想写用户名然后输入,在这个例子中看起来很明显,但有时它们不是直接的兄弟姐妹,会有很多隐藏的输入或其他标签。

另一个例子:  

   <input type=hidden name="startDate">

      <TR>  <TD bgColor=#008088 colSpan=2 class="headfont">

        <FONT color=#FFFFFF>  <B>* Enter ur username and password</B> </FONT>

      </TD></TR>

      <TR>

       <TD bgColor=#9ccdcd class="datafont"><FONT color=black>Username</FONT></TD>

            <TD bgColor=#9ccdcd class="datafont">

            <INPUT tabIndex=1 name=stuNum 

              autocomplete="off" size="20"></TD></TR>

          <TR>

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

我没有什么想法,但是他们会花很多时间,所以我认为既然我是HTML敏捷包的新手就会有一种方法或一些捷径可以获得它,任何建议?

1 个答案:

答案 0 :(得分:2)

这样的事情应该有效。

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;
}

然后使用它,只需传入要获取输入元素的字段的名称。

GetInputNodes(doc, "username");

只是一个警告,似乎HtmlAgilityPack并没有像它应该的那样关闭表单。因此,您必须指定在加载html之前应关闭表单元素。没有它,HAP将无法识别该表单有任何子节点。

var doc = new HtmlDocument();
HtmlNode.ElementsFlags["form"] = HtmlElementFlag.Closed;
doc.Load(url);