15、Elixir开发:从OS命令到Twitter数据获取

Elixir开发:从OS命令到Twitter数据获取

1. 使用Porcelain执行OS命令

1.1 配置Porcelain自动运行

在创建应用程序并将Porcelain作为依赖项添加后,我们需要对其进行配置以实现自动运行。具体步骤如下:
1. 在步骤3中,将Porcelain添加到 OsCommands 应用程序启动时会自动引导的应用程序列表中。
2. 在步骤5和6中,定义两个函数:
- list 函数:执行 ls 命令。若未传入路径选项,则默认使用应用程序目录。
- run 函数:功能更为通用,可执行操作系统中可用的任何命令。

1.2 Porcelain的更多特性

Porcelain允许将输入定义为文件或流,输出同样支持这样的定义方式。它是一个强大的工具,可用于构建文件系统监视器等,能在文件发生更改时执行相应操作。其最令人印象深刻的是,它能让我们借助底层操作系统的强大功能,扩展Elixir中的可用选项。

1.3 相关拓展

可以将Goon驱动与Porcelain结合使用。Goon用Go语言开发,能为Porcelain提供更多功能,特别是向外部程序发送EOF信号以及向程序发送操作系统信号的能力。更多关于Porcelain的信息,可参考文档: http://porcelain.readthedocs.org/

2. 获取Twitter数据

2.1 准备工作

在开始构建应用程序之前,需要在Twitter上注册一个新应用,以获取用于身份验证和使用Twitter API的API密钥。具体操作如下:
1. 访问 https://apps.twitter.com ,点击“Create New App”按钮。
2. 按照步骤操作后,将获得四个必要的项: consumer_key consumer_secret access_token access_token_secret
3. 这些值可以直接在应用程序中使用,也可以在bash或zsh(如果使用Unix系统)的初始化文件中设置为环境变量。

2.2 构建应用程序的步骤

2.2.1 创建新的Phoenix应用程序
> mix phoenix.new phoenix_twitter_stream code/phoenix_twitter_stream

注意:如需了解更多创建Phoenix应用程序的信息,请参考相关文档。

2.2.2 添加依赖项

mix.exs 文件中添加以下依赖项:

defp deps do
  [
    {:phoenix, "~> 0.8.0"},
    {:cowboy, "~> 1.0"},
    {:oauth, github: "tim/erlang-oauth"},
    {:extwitter, "~> 0.1"}
  ]
end
2.2.3 获取并编译依赖项
> mix deps.get && mix deps.compile
2.2.4 配置应用程序使用Twitter API密钥

编辑 lib/phoenix_twitter_stream.ex 文件,添加以下配置块:

defmodule PhoenixTweeterStream do
  use Application
  def start(_type, _args) do
    import Supervisor.Spec, warn: false
    ExTwitter.configure(
      consumer_key: System.get_env("SMM_TWITTER_CONSUMER_KEY"),
      consumer_secret: System.get_env("SMM_TWITTER_CONSUMER_SECRET"),
      access_token: System.get_env("SMM_TWITTER_ACCESS_TOKEN"),
      access_token_secret: System.get_env("SMM_TWITTER_ACCESS_TOKEN_SECRET")
    )
    children = [
      # Start the endpoint when the application starts
      worker(PhoenixTweeterStream.Endpoint, []),
      # Here you could define other workers and supervisors as children
      # worker(PhoenixTweeterStream.Worker, [arg1, arg2, arg3]),
    ]
    opts = [strategy: :one_for_one, name: PhoenixTweeterStream.Supervisor]
    Supervisor.start_link(children, opts)
  end
  def config_change(changed, _new, removed) do
    PhoenixTweeterStream.Endpoint.config_change(changed, removed)
    :ok
  end
end

注意:若不想将密钥设置为环境变量,可直接将密钥声明为字符串,例如: consumer_key: "this-is-an-example-key"

2.2.5 定义处理新推文查询的模块

lib/phoenix_twitter_stream/tweet_streamer.ex 文件中添加以下代码:

defmodule PhoenixTwitterStream.TweetStreamer do
  def start(socket, query) do
    stream = ExTwitter.stream_filter(track: query)
    for tweet <- stream do
      Phoenix.Channel.reply(socket, "tweet:stream", tweet)
    end
  end
end
2.2.6 创建处理推文的通道

web/channels/tweets.ex 文件中添加以下代码:

defmodule PhoenixTwitterStream.Channels.Tweets do
  use Phoenix.Channel
  alias PhoenixTwitterStream.TweetStreamer
  def join("tweets", %{"track" => query}, socket) do
    spawn(fn() -> TweetStreamer.start(socket, query) end)
    {:ok, socket}
  end
end
2.2.7 编辑应用程序路由器

编辑 /web/router.ex 文件,注册WebSocket处理程序和推文通道:

defmodule PhoenixTwitterStream.Router do
  use Phoenix.Router
  pipeline :browser do
    plug :accepts, ~w(html)
    plug :fetch_session
    plug :fetch_flash
    plug :protect_from_forgery
  end
  pipeline :api do
    plug :accepts, ~w(json)
  end

  socket "/ws" do
    channel "tweets", PhoenixTwitterStream.Channels.Tweets
  end

  scope "/", PhoenixTwitterStream do
    pipe_through :browser # Use the default browser stack
    get "/", PageController, :index
  end
end
2.2.8 替换索引模板内容

web/templates/page/index.html.eex 文件的内容替换为以下代码:

<div class="row">
  <div class="col-lg-12">
    <ul id="tweets"></ul>
  </div>
  <script src="/js/phoenix.js" type="text/javascript"></script>
  <script src="https://code.jquery.com/jquery-2.1.1.js" type="text/javascript"></script>
  <script type="text/javascript">
    var my_track = "programming";
    var socket = new Phoenix.Socket("ws://" + location.host + "/ws");
    socket.join("tweets", {track: my_track}, function(chan){
      chan.on("tweet:stream", function(message){
        console.log(message);
        $('#tweets').prepend($('<li>').text(message.text));
        });
    });
  </script>
</div>
2.2.9 启动应用程序
> mix phoenix.server
2.2.10 访问应用程序

打开浏览器,访问 http://localhost:4000/ ,几秒后,推文将开始显示,新推文会显示在页面顶部。

2.3 应用程序的工作原理

  1. 创建Phoenix应用程序 :选择Phoenix是因为它适合实时显示带有推文更新的网页,通过WebSocket实现实时更新。
  2. 添加依赖项 :在步骤2中,添加了与Twitter API交互所需的依赖项,包括parroty的 extwitter Elixir应用程序( https://hex.pm/packages/extwitter )和Tim的 erlang-oauth 应用程序( https://github.com/tim/erlang-oauth/ )。获取并编译依赖项后,在步骤4中添加Twitter API密钥,用于身份验证。
  3. 定义查询函数 :在步骤5中,定义的函数启动后会向Twitter查询包含特定查询词的推文。 stream = ExTwitter.stream_filter(track: query) 定义了一个流,该流是 ExTwitter 应用程序过滤Twitter时间线后的结果,仅提取包含定义查询词的条目。 for tweet <- stream do Phoenix.Channel.reply(socket, "tweet:stream", tweet) 是一个流推导式,会将流中的每个新条目通过Phoenix通道发送出去。
  4. 定义通道 :在步骤6中定义的通道类似于WebSocket处理程序。 join 函数在WebSocket连接建立时,通过 spawn 调用初始化步骤5中定义的模块,该函数接收前端代码中定义的查询字符串,并将其传递给 ExTwitter 作为过滤条件。
  5. 注册WebSocket处理程序 :在步骤7中,使用 use Phoenix.Router.Socket 在路由器中注册并挂载WebSocket处理程序,使用 channel "tweets", PhoenixTwitterStream.Channels.Tweets 定义通道及其处理模块。注意,通道定义必须在任何作用域定义之外。
  6. 前端代码 :在步骤8中,将HTML和JavaScript混合在一个文件中,用于显示根页面并与服务器建立WebSocket连接。使用 phoenix.js 库辅助处理Phoenix WebSocket和通道。前端代码的具体解释如下:
    • var my_track = "programming" :初始化查询词,这里过滤包含“programming”的所有推文。
    • var socket = new Phoenix.Socket("ws://" + location.host + "/ws") :初始化WebSocket连接,端点为 /ws
    • socket.join("tweets", {track: my_track}, function(chan){...}) :加入 tweets 通道,当有新推文通过WebSocket连接到达时,将其添加到页面现有推文的顶部。

2.4 更多建议

若希望页面更新速度更快,可选择更热门的查询词。

3. 安装相关软件及参考资料

3.1 安装Elixir

访问 http://elixir-lang.org/install.html 获取安装Elixir和Erlang在主要操作系统上的所有文档。

3.2 安装PostgreSQL

3.3 安装Redis

3.4 有用的链接

技术 链接
Elixir http://elixir-lang.org
http://elixir-lang.org/getting-started/introduction.html
http://elixir-lang.org/docs.html
https://hex.pm
https://github.com/elixir-lang/elixir
Phoenix框架 http://www.phoenixframework.org
Erlang http://www.erlang.org
http://www.erlang.org/doc.html

3.5 整体流程

graph LR
    A[准备工作:获取Twitter API密钥] --> B[创建Phoenix应用程序]
    B --> C[添加依赖项]
    C --> D[获取并编译依赖项]
    D --> E[配置应用程序使用API密钥]
    E --> F[定义查询模块]
    F --> G[创建通道模块]
    G --> H[编辑路由器]
    H --> I[替换索引模板内容]
    I --> J[启动应用程序]
    J --> K[访问应用程序]

以上就是从使用Porcelain执行OS命令到获取Twitter数据的详细过程,涵盖了应用程序的创建、配置、运行以及相关软件的安装和参考资料,希望能帮助你在Elixir开发中顺利实现这些功能。

4. Elixir开发中的其他关键技术点

4.1 数据结构与操作

4.1.1 列表操作

列表是Elixir中常用的数据结构,支持添加和减法操作:
- 添加列表 :使用 ++ 运算符,例如:

list1 = [1, 2, 3]
list2 = [4, 5, 6]
result = list1 ++ list2
# result 为 [1, 2, 3, 4, 5, 6]
  • 减去列表 :使用 -- 运算符,例如:
list1 = [1, 2, 3, 4]
list2 = [2, 4]
result = list1 -- list2
# result 为 [1, 3]
  • 组合元组成列表 :可以将多个元组组合成一个列表,例如:
tuple1 = {1, "a"}
tuple2 = {2, "b"}
list = [tuple1, tuple2]
# list 为 [{1, "a"}, {2, "b"}]
4.1.2 映射操作

映射是一种键值对的数据结构,可用于创建键值存储:

map = %{:key1 => "value1", :key2 => "value2"}
# 获取值
value = map[:key1]
# value 为 "value1"

也可以使用 Map.new/0 函数创建空映射:

empty_map = Map.new()
4.1.3 关键字列表操作

关键字列表是一种特殊的列表,其中的元素是二元元组,第一个元素为原子:

keyword_list = [name: "John", age: 30]
# 获取值
name = keyword_list[:name]
# name 为 "John"

关键字列表的创建和操作示例如下:

# 创建
new_list = [color: "red", size: "large"]
# 操作
updated_list = Keyword.put(new_list, :shape, "circle")

4.2 函数定义与模式匹配

4.2.1 函数定义中的默认参数

在Elixir中可以定义带有默认参数的函数:

defmodule Example do
  def greet(name \\ "Guest") do
    "Hello, #{name}!"
  end
end

# 调用
Example.greet() # 返回 "Hello, Guest!"
Example.greet("Alice") # 返回 "Hello, Alice!"
4.2.2 函数定义中的守卫子句和模式匹配

守卫子句和模式匹配可用于更精确地定义函数行为:

defmodule Math do
  def add(a, b) when is_integer(a) and is_integer(b) do
    a + b
  end
  def add(_, _) do
    :error
  end
end

# 调用
Math.add(1, 2) # 返回 3
Math.add(1, "a") # 返回 :error

4.3 并发与分布式编程

4.3.1 使用任务模块进行并发计算

Task 模块可用于执行多个并发计算:

defmodule ConcurrentExample do
  def run do
    task1 = Task.async(fn -> 1 + 1 end)
    task2 = Task.async(fn -> 2 + 2 end)

    result1 = Task.await(task1)
    result2 = Task.await(task2)

    {result1, result2}
  end
end

# 调用
ConcurrentExample.run() # 返回 {2, 4}
4.3.2 创建和连接命名节点

可以创建命名节点并进行连接:

# 创建命名节点
Node.start(:node1@localhost)
Node.start(:node2@localhost)

# 连接节点
Node.connect(:node2@localhost)

在不同节点上执行代码可以使用 Node.spawn 函数:

pid = Node.spawn(:node2@localhost, fn -> 1 + 1 end)

4.4 错误处理与异常管理

在Elixir中,错误处理和异常管理是重要的部分:

try do
  raise "An error occurred"
rescue
  e in RuntimeError ->
    IO.puts("Caught error: #{e.message}")
end

还可以使用 throw catch 来处理特定情况:

try do
  throw(:error)
catch
  :error ->
    IO.puts("Caught throw")
end

5. Phoenix框架深入

5.1 创建Phoenix应用程序的更多细节

5.1.1 创建视图和模板

视图和模板是Phoenix应用程序中用于呈现数据的重要部分。创建视图的示例如下:

defmodule PhoenixTwitterStream.Web.PageView do
  use PhoenixTwitterStream.Web, :view
end

创建模板,例如在 web/templates/page/index.html.eex 中:

<h1>Welcome to the Phoenix Twitter Stream</h1>
5.1.2 实现主题

在Phoenix应用程序中可以实现主题,例如在通道中处理不同的主题:

defmodule PhoenixTwitterStream.Channels.Tweets do
  use Phoenix.Channel

  def join("tweets:programming", payload, socket) do
    # 处理编程主题的逻辑
    {:ok, socket}
  end

  def join("tweets:sports", payload, socket) do
    # 处理体育主题的逻辑
    {:ok, socket}
  end
end

5.2 保护Phoenix应用程序

可以使用SSL保护Phoenix应用程序,在配置文件中添加SSL相关配置:

config :phoenix_twitter_stream, PhoenixTwitterStream.Endpoint,
  https: [
    port: 443,
    cipher_suite: :strong,
    keyfile: "priv/ssl/selfsigned_key.pem",
    certfile: "priv/ssl/selfsigned_cert.pem"
  ]

5.3 Phoenix应用程序的整体架构

graph LR
    A[客户端] --> B[WebSocket连接]
    B --> C[Phoenix路由器]
    C --> D[通道处理]
    D --> E[查询模块]
    E --> F[Twitter API]
    F --> E
    E --> D
    D --> C
    C --> B
    B --> A

6. 总结

通过以上内容,我们全面了解了Elixir开发的多个方面,从使用Porcelain执行OS命令,到获取Twitter数据,再到Elixir中的数据结构操作、并发编程、错误处理以及Phoenix框架的深入应用。掌握这些技术点可以帮助我们开发出高效、稳定且功能丰富的Elixir应用程序。在实际开发中,我们可以根据具体需求灵活运用这些知识,不断优化和完善我们的项目。同时,合理利用参考资料和相关工具,能够进一步提升开发效率和质量。希望这些内容能为你的Elixir开发之旅提供有力的支持。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值