2016-06-22 29 views
1

我有一個函數,它解析一個html body以獲得如下的Open Graph屬性。如何在這種情況下使用Elixir Stream處理多個項目?

我不知道如何使用流,以便解析只能完成一次 - 這甚至有可能嗎?

def og(body) do 
image = attribute_content(body, "meta[property=og:image]") 
title = attribute_content(body, "meta[property=og:title]") 
site_name = attribute_content(body, "meta[property=og:site_name]") 
desc = attribute_content(body, "meta[property=og:description]") 
type = attribute_content(body, "meta[property=og:type]") 
url = attribute_content(body, "meta[property=og:url]") 
author = attribute_content(body, "meta[name=author]") 

%{image: image, title: title, type: type, 
    site_title: site_title, url: url, site_name: site_name, 
    description: desc, author: author} 
end 

@doc """ 
Parse html body for the target element and return the content. 
""" 
defp attribute_content(body, target) do 
    Floki.find(body, target) |> Floki.attribute("content") |> List.first 
end 
+0

什麼是'attribute_content'? – Dogbert

+0

只是一個私人幫手函數來獲取屬性內容。 編輯了原始問題並添加了清晰的功能。 –

回答

2

從你的問題我想bodyString,你想一次解析它。如果是這種情況,Floki.parse/1將身體解析爲列表。 Floki.find/2可以接收此列表作爲參數,而不是使用HTML的String

(...) 
parsed = Floki.parse(body) 
image = attribute_content(parsed, "meta[property=og:image]") 
(...) 

此外,您可以創建一個列表與所有喜歡的屬性:

attributes = [image: "meta[property=og:image]", 
       title: "meta[property=og:title]", 
       site_name: "meta[property=og:site_name]", 
       description: "meta[property=og:description]", 
       type: "meta[property=og:type]", 
       url: "meta[property=og:url]", 
       author: "meta[name=author]"] 

然後映射功能attribute_content/2和轉換KeywordMap

attributes 
|> Stream.map(fn {k, v} -> {k, attribute_content(parsed, v)} end) 
|> Enum.into(%{}) 

,所以該完整代碼將是:

def og(html) do 
    attributes = [image: "meta[property=og:image]", 
       title: "meta[property=og:title]", 
       site_name: "meta[property=og:site_name]", 
       description: "meta[property=og:description]", 
       type: "meta[property=og:type]", 
       url: "meta[property=og:url]", 
       author: "meta[name=author]"] 
    general(html, attributes) 
end 

defp general(html, attributes) do 
    parsed = Floki.parse(html) 
    attributes 
    |> Stream.map(fn {k, v} -> {k, attribute_content(parsed, v)} end) 
    |> Enum.into(%{}) 
end 

defp attribute_content(parsed, target) do 
    Floki.find(body, target) 
    |> Floki.attribute("content") 
    |> List.first 
end 

我希望這能回答你的問題。