2016-06-22 5 views
1

Ich habe eine Funktion, die einen HTML-Text analysiert, um die Open Graph-Attribute wie unten zu erhalten.Wie kann Elixir Stream verwendet werden, um mehrere Objekte in dieser Situation zu verarbeiten?

Ich bin mir nicht sicher, wie man Stream nutzt, damit das Parsen nur einmal durchgeführt werden kann - und das ist sogar möglich?

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

Was ist 'attribute_content'? – Dogbert

+0

Nur eine private Hilfsfunktion, um den Attribut-Inhalt zu erhalten. Editierte die ursprüngliche Frage und fügte die Funktion für Klarheit hinzu. –

Antwort

2

Aus Ihrer Frage denke ich body ein String ist und Sie wollen es einmal analysieren. Wenn das der Fall ist, analysiert Floki.parse/1 den Körper zu einer Liste. Floki.find/2 kann diese Liste als Argument anstelle des String mit dem HTML erhalten.

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

Zusätzlich können Sie eine Liste mit allen Attributen wie erstellen:

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

Und dann ordnen Sie die Funktion attribute_content/2 und wandeln die Keyword auf ein Map:

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

So die volle Code wäre:

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 

Ich hoffe, dies beantwortet Ihre Frage.

Verwandte Themen