2014-04-09 28 views
3

我想用F#和Canopy編寫一個簡單的抓取工具(請參閱http://lefthandedgoat.github.io/canopy/)。我試圖從類「.application-tile」中的所有元素中提取文本。但是,在下面的代碼中,我得到了以下的構建錯誤,我不明白它。用F#和Canopy進行站點抓取

This expression was expected to have type 
    OpenQA.Selenium.IWebElement -> 'a  
but here has type 
    OpenQA.Selenium.IWebElement 

任何想法爲什麼會發生這種情況?謝謝!

open canopy 
open runner 
open System 

[<EntryPoint>] 
let main argv = 
    start firefox 

    "taking canopy for a spin" &&& fun _ -> 
     url "https://abc.com/" 

     // Login Page 
     "#i0116" << "[email protected]" 
     "#i0118" << "abc" 
     click "#abcButton" 

     // Get the Application Tiles -- BUILD ERROR HAPPENS HERE 
     elements ".application-tile" |> List.map (fun tile -> (tile |> (element ".application-name breakWordWrap"))) |> ignore 

    run() 
+0

您試圖完成你的List.map? –

+0

我試圖從每個元素中獲取文本/內容。 – Martin

回答

5
open canopy 
open runner 

start firefox 

"taking canopy for a spin" &&& fun _ -> 
    url "http://lefthandedgoat.github.io/canopy/testpages/" 

    // Get the tds in tr 
    let results = elements "#value_list td" |> List.map read 

    //or print them using iter 
    elements "#value_list td" 
     |> List.iter (fun element -> System.Console.WriteLine(read element)) 

run() 

這應該做你想做的。

canopy有一個叫做'read'的函數,它接受一個選擇器或一個元素。既然你從「元素」選擇器中選擇了所有的元素,那麼你可以將列表中的元素進行映射。

List.map接受一個函數,運行它並返回結果列表。 (x => read(x)) List.iter與.foreach(x => System.Console.Writeline(read(x))相同

0

我相信錯誤發生在您的List.map調用中的投影lambda中。從冠層文檔elements返回匹配CSS選擇器或文本的所有元素。 element獲取給定css選擇器或文本的元素。

因此,在這裏您可以獲取與選擇器「.application-tile」匹配的元素列表。 List.map需要一個帶有IElement(包含在元素中的類型)的lambda,將它投影到一個新的表單中(通用的'a')。

我對這個框架了解不多,但我不確定爲什麼你需要一個元素,然後將其調入另一個元素調用。

仔細查看文檔,我們發現讀取功能: 「讀取元素的文本(或值或選定的選項)。」這是你想要的嗎?

+0

「閱讀元素的文本(或值或選定的選項)。」這是你想要的嗎? - 是的。這正是我想要的,我的理解是「元素」會將所有元素返回給類「.application-tile」,並且我想要一個包含每個元素的內容/文本的集合。 – Martin