我尝试使用HTTPoison编写Web抓取工具。作为第一步,我按照下面显示的步骤编写了一个简短的HTTP访问代码;
通过mix
创建项目$ mix new httptest1
在lib / httptest1.ex上写一个简短的代码。
defmodule Httptest1 do
require HTTPoison
def test1 do
ret = HTTPoison.get! "http://www.yahoo.com"
%HTTPoison.Response{status_code: 200, body: body} = ret
IO.inspect body
end
end
Httptest1.test1()
修改HTTP.ison的mix.exs。
defmodule Httptest1.Mixfile do
use Mix.Project
def project do
[app: :httptest1,
version: "0.0.1",
elixir: "~> 1.0",
build_embedded: Mix.env == :prod,
start_permanent: Mix.env == :prod,
deps: deps]
end
# Configuration for the OTP application
def application do
[applications: [:logger, :httpoison]]
end
# Dependencies can be Hex packages:
#
defp deps do
[
{:httpoison, "~> 0.6"}
]
end
end
运行$ mix deps.get
以获取相关性。
运行$ mix run
,然后编译失败;
==> idna (compile)
Compiled src/idna.erl
Compiled src/idna_ucs.erl
Compiled src/punycode.erl
(... snip ...)
Generated httpoison app
== Compilation error on file lib/httptest1.ex ==
** (exit) exited in: :gen_server.call(:hackney_manager, {:new_request, #PID<0.154.0>, #Reference<0.0.1.1724>, {:client, :undefined, :hackney_dummy_metrics, :hackney_tcp_transport, 'www.yahoo.com', 80, "www.yahoo.com", [connect_timeout: 5000, recv_timeout: :infinity], nil, nil, nil, true, :hackney_pool, :infinity, false, 5, false, 5, nil, nil, nil, :undefined, :start, nil, :normal, false, false, false, false, nil, :waiting, nil, 4096, "", [], :undefined, nil, nil, nil, nil, :undefined, nil}}, :infinity)
** (EXIT) no process
(stdlib) gen_server.erl:212: :gen_server.call/3
src/hackney_client/hackney_manager.erl:66: :hackney_manager.init_request/1
src/hackney_client/hackney_manager.erl:56: :hackney_manager.new_request/1
src/hackney_connect/hackney_connect.erl:181: :hackney_connect.socket_from_pool/4
src/hackney_connect/hackney_connect.erl:36: :hackney_connect.connect/5
src/hackney_client/hackney.erl:319: :hackney.request/5
lib/httpoison.ex:60: HTTPoison.request/5
lib/httpoison.ex:60: HTTPoison.request!/5
当我使用$ iex -S mix
时,结果是相同的。
但是,如果我将httptest1.ex移动到放置了mix.exs的同一目录,例如$ mv lib/httptest1.ex .
,并尝试明确指定源文件; $ mix run httptest1
,它运作正常。
问题: 我怀疑我的mix.exs设置有问题,那是什么?
答案 0 :(得分:2)
.ex
中的所有lib/
都已编译完毕。由于Elixir是编译文件时的元编程语言,因此实际上是在运行代码。这意味着在编译项目时会执行Httptest1.test1()
。
需要启动HTTPoison才能正常工作。它是在您的应用程序启动时启动的,当您执行mix run ...
时。但是当您的项目正在编译项目或者您的依赖项未启动时,对依赖项的调用可能会失败。
在入门指南中查看本章Supervisor and Application,了解如何在应用程序启动时运行代码。
答案 1 :(得分:0)
改进!现在我知道如何创建可执行的调用命令行。
方案;
defmodule Httptest1 do
use Application
require HTTPoison
def start(_type, _args) do
import Supervisor.Spec, warn: false
children = []
opts = [strategy: :one_for_one, name: Httptest1.Supervisor]
Supervisor.start_link(children, opts)
end
def main(args) do # entry point
ret = HTTPoison.get! "http://www.yahoo.com"
%HTTPoison.Response{status_code: _, body: body} = ret # no status code matching now
IO.inspect body
end
end
和mix.exs(均由$ mix new httptest1 --sup
主管选项创建);
defmodule Httptest1.Mixfile do
use Mix.Project
def project do
[app: :httptest1,
version: "0.0.1",
elixir: "~> 1.0",
build_embedded: Mix.env == :prod,
start_permanent: Mix.env == :prod,
escript: escript, # <<<< Added
deps: deps]
end
def escript do # define escript
[main_module: Httptest1]
end
def application do
[applications: [:logger, :httpoison],
mod: {Httptest1, []}] #
end
defp deps do
[
{:httpoison, "~> 0.6"}
]
end
end
然后在$ iex -S mix
类型Httptest.test1
调用的iex中,预期的结果出现了!感谢。
另外,要创建命令行可执行文件,
$ mix escript.build
然后生成./httptest1。完成。