哈希集未更新
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 的理想情况。
我正在尝试编写网络爬虫,需要跟踪已访问的 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 的理想情况。