哈希集未更新

Hashset not updating

我正在尝试编写网络爬虫,需要跟踪已访问的 URL。为此,我尝试使用 HashSet,但无法使用新的 URLs

对其进行更新
defmodule Crawl do

  @depth 2

  @doc """
  Starts crawling process
  """
  def start(url) do
    visit(url, @depth, HashSet.new)
  end

  defp visit(url, 0, cache) do
  end

  defp visit(url, depth, cache) do
    if Set.member? cache, url do
      IO.puts "Cache hit"
    else
      IO.puts "Crawling [#{depth}] #{url}"
      IO.puts "#{Set.size(cache)}"

      new_cache          = Set.put(cache, url)
      {status, response} = HTTPoison.get(url)
      handle(status, response, depth, new_cache)
    end
  end

  defp handle(:ok, response, depth, cache) do
    %{status_code: code, body: body} = response
    handle(code, body, depth, cache)
  end

  defp handle(:error, response, depth, cache) do
    %{id: id, reason: reason} = response
    handle(400, reason, depth, cache)
  end

  defp handle(200, body, depth, cache) do
    IO.puts "Parsing body..."
    parse(body, depth, cache)
  end

  defp handle(301, body, cache), do: IO.puts 301
  defp handle(400, reason, cache), do: IO.puts reason

  # Parses HTML body
  #
  defp parse(body, depth, cache) do
    body
    |> Floki.find(".entry .first a")
    |> Floki.attribute("href")
    |> Enum.map(fn(url) -> visit(url, depth - 1, cache) end)
  end


end

仅插入初始 URL,之后,记录大小不断返回 1

有什么建议吗?

您需要确保缓存的新副本可用于需要它的函数。您将其设置为 visit 而从不 return 它;较新版本的缓存永远不会传播回树。

Elixir 始终按值传递,因为数据是不可变的。您无法更改参数的值,您所能做的就是对其应用一个函数,然后 return 一个新的数据项。

"elixir" 做你想做的事情的方法是创建一个代理来管理访问过的 URL 的持久状态。参见

http://elixir-lang.org/getting-started/mix-otp/agent.html

举个例子。

如果您出于某种原因不想使用代理,则需要 return 访问当前状态,然后在您的解析函数中使用 Enum.reduce。 然而,这确实是 Agent 的理想情况。