选择hq节点seq的内部文本

时间:2014-06-05 15:17:41

标签: f# html-agility-pack f#-3.0 c#-to-f#

我目前使用HTML Agility包进行C#web scrape,最终结果是表示一行表中数据的字符串数组列表。我对F#很新,遇到一些问题,了解如何正确解析它。我也使用这个F#包装器:https://fsnotebook.net/notebook/fssnip-kr/HtmlAgilityPack_FSharp

我的C#代码:

var body = document.DocumentNode.Descendants().FirstOrDefault(n => n.Name == "body");
var table = body.Descendants("table").FirstOrDefault(t => t.Attributes.Contains("cellpadding") && t.Attributes["cellpadding"].Value == "1");
var rows =
    table.Descendants("tr")
         .Where(r => r.Attributes.Contains("bgcolor") && r.Attributes["bgcolor"].Value == "#ffffff");
List<string[]> athleteDatas =
    rows.Select(t => t.Descendants("td").Select(d => d.InnerText).ToArray()).ToList();

我的F#代码。到目前为止,我有一系列td元素,我需要选择每个序列的内部元素作为字符串数组,然后将其放回序列/列表中。

 let resultsBody resultsPage =
    resultsPage
    |> createDoc
    |> descendants "table"
    |> Seq.filter (hasAttr "cellpadding" "1")
    |> Seq.head
    |> descendants "tr"
    |> Seq.filter (hasAttr "bgcolor" "#ffffff")
    |> Seq.map(descendants "td")
    |> Seq.toArray

2 个答案:

答案 0 :(得分:3)

您可以使用XPath简化此操作。这将返回seq<string>。如果您需要列表或数组,请将最后一行输送到Seq.toList / Seq.toArray

open HtmlAgilityPack

let html = """
<html>
    <body>
        <table cellpadding="1">
            <tbody>
                <tr bgcolor="#ffffff">
                    <td>
                        Some text.
                    </td>
                </tr>
            </tbody>
        </table>
    </body>
</html>"
"""

let doc = HtmlDocument()
doc.LoadHtml(html)
doc.DocumentNode.SelectNodes("//body/table[@cellpadding='1']//tr[@bgcolor='#ffffff']/td")
|> Seq.map (fun n -> n.InnerText)

答案 1 :(得分:2)

如果我理解正确,丢失的部分包含在原始代码的.Select(...)内,因此您需要同样修改map

|> Seq.map (descendants "td" >> Seq.map innerText >> Array.ofSeq)

或者如果你在无点上有一些困难:

|> Seq.map (fun line ->
    line
    |> descendants "td"
    |> Seq.map innerText
    |> Array.ofSeq)