F#.Data HTML解析器从节点中提取字符串

时间:2017-05-31 20:48:27

标签: f# f#-data

我正在尝试使用FSharp.Data的HTML Parser从href属性中提取字符串链接列表。

我可以将链接打印到控制台,但是,我很难将它们列入清单。

打印所需链接的代码的工作片段:

let results = HtmlDocument.Load(myUrl)
let links = 
    results.Descendants("td")
    |> Seq.filter (fun x -> x.HasClass("pagenav"))
    |> Seq.map (fun x -> x.Elements("a"))
    |> Seq.iter (fun x -> x |> Seq.iter (fun y -> y.AttributeValue("href") |> printf "%A"))

如何将这些字符串存储到变量链接中而不是将其打印出来?

干杯,

1 个答案:

答案 0 :(得分:2)

在最后一行,您最终得到一系列序列 - 对于每个td.pagenav,您有一堆<a>,每个href都有一个Seq.iter。这就是为什么你必须有两个嵌套的Seq.collect - 首先你迭代外部序列,并在每次迭代时迭代内部序列。

要展平序列序列,请使用Seq.toList。此外,要将序列转换为列表,请使用List.ofSeqlet a = [ [1;2;3]; [4;5;6] ] let b = a |> Seq.collect id |> Seq.toList > val b : int list = [1; 2; 3; 4; 5; 6] (它们等效):

let links = 
    results.Descendants("td")
    |> Seq.filter (fun x -> x.HasClass("pagenav"))
    |> Seq.map (fun x -> x.Elements("a"))
    |> Seq.collect (fun x -> x |> Seq.map (fun y -> y.AttributeValue("href")))
    |> Seq.toList

将此应用于您的代码:

Seq.collect

或者你可以通过在第一次遇到嵌套序列的位置应用let links = results.Descendants("td") |> Seq.filter (fun x -> x.HasClass("pagenav")) |> Seq.collect (fun x -> x.Elements("a")) |> Seq.map (fun y -> y.AttributeValue("href")) |> Seq.toList 来使它更清晰:

let links = [ for td in results.Descendants "td" do
                if td.HasClass "pagenav" then
                  for a in td.Elements "a" ->
                    a.AttributeValue "href"
            ]

那就是说,我宁愿把它重写为列表理解。看起来更干净:

datetime