2016-06-22 23 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 

我希望这能回答你的问题。