2017-05-31 74 views
2

我試圖使用FSharp.Data的HTML解析器來提取字符串鏈接從href屬性列表。F#。數據HTML解析器從節點提取字符串

我可以打印輸出到控制檯的鏈接,但是,我正在努力讓他們進入列表。

工作的打印出想要的鏈接的代碼片段:

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")) 

如何存放這些字符串爲可變鏈接,而不是將它們打印出來的?

乾杯,

回答

2

在最後一行,你最終序列的序列 - 每個td.pagenav你有一大堆的<a>,每個有href。這就是爲什麼你必須有兩個嵌套的Seq.iter - 首先迭代外部序列,並在每次迭代中迭代內部序列。

要平鋪序列序列,請使用Seq.collect。此外,一個序列轉換到一個列表,使用Seq.toListList.ofSeq(他們是等價):

let 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" 
      ] 
+0

完美答案,謝謝! – snowbane

+0

如果我的回答對你有幫助,你會考慮接受嗎? –