23
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ElixirAdvent Calendar 2016

Day 21

Elixirでスクレイピングしてみた

Last updated at Posted at 2016-12-20

##使うライブラリ

HTTPoison

HTTPoisonは, HTTPクライアントでリクエストを投げて, レスポンスのHTMLを取得するために使います。

###Floki

Flokiは, シンプルなHtmlパーサでHtmlを解析してデータを取得するために使います。

###プロジェクト作成

mixは
Elixirプロジェクトの作成や依存解決,コンパイル,テストを行うビルドツール。

mixを使ってElixirプロジェクトの作成をしていきます。

$ mix new scraper
* creating README.md
* creating .gitignore
* creating mix.exs
* creating config
* creating config/config.exs
* creating lib
* creating lib/scraper1.ex
* creating test
* creating test/test_helper.exs
* creating test/scraper1_test.exs

Your Mix project was created successfully.
You can use "mix" to compile it, test it, and more:

    cd scraper
    mix test

Run "mix help" for more commands.

Elixirプロジェクトが作成されたので, プロジェクトに移動し進めていきます

###関連モジュール, ライブラリを取得

#mix.exs
defmodule Scraper.Mixfile do
  use Mix.Project

  def project do
    [app: :scraper,
     version: "0.1.0",
     elixir: "~> 1.3",
     build_embedded: Mix.env == :prod,
     start_permanent: Mix.env == :prod,
     deps: deps()]
  end

  def application do
    [applications: [:logger, :floki, :httpoison]]
  end

  defp deps do
    [
      {:floki, "~> 0.10.0"},
      {:httpoison, "~> 0.9.0"}
    ]
  end
end

mix.exsのdepsにimportするモジュールを書き込みます。

ここで

  • floki
  • httpoison

を使うので追加します。

{:floki, "~> 0.10.0"},
{:httpoison, "~> 0.9.0"}

mix deps.get でdepsに書き込んだ関連モジュールを取得します。

Takuya@Takuya-no-MacBook-Air:~/scraper1 mix deps.get
Running dependency resolution
Dependency resolution completed
  certifi: 0.7.0
  floki: 0.10.1
  hackney: 1.6.3
  httpoison: 0.9.2
...

関連モジュールを取得してスクレイピングをする準備ができました。
次はスクレイピングをしていきます。

###スクレイピング

iex -S mixでプロジェクトの環境を読み込み, 依存モジュールを使用しながらインタラクティブにコードを実行していくことができます。

ここでは例としてgithubのプロフィールからfollower数を取ってみたいと思います。
githubのapiで提供されていると思うがやってみます:)

スクリーンショット 2016-12-20 22.18.36.png

iex -S mix
Erlang/OTP 19 [erts-8.0.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Interactive Elixir (1.3.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> body = HTTPoison.get!("https://github.com/takpy").body

iex(2)> Floki.find(body, "span.counter") |> Enum.at(2) |> Floki.text() |> String.strip()

###body = HTTPoison.get! "https://github.com/takpy"

では"https://github.com/takpy" にhttpリクエストを送ったレスポンスのhtmlをbodyにバインドします。

bodyの Data typeはBitStringになっています

ちなみに変数のData typeは i 変数で確認できます。

###Floki.find(body, "span.counter") |> Enum.at(2) |> Floki.text() |> String.strip()

パイプライン演算子でつなげていますが一つずつ解説します。

<a href="/takpy?tab=followers" class="underline-nav-item " aria-selected="false" role="tab">
          Followers
          <span class="counter">
取得したい -->            2
          </span>
        </a>

取得したいfollowerの数を取るためにはこの要素を取らなければならないのですが,
Floki.find(body, "span.counter")
をすると

Floki.find(body, "span.counter")
[{"span", [{"class", "counter"}], ["\n             3\n           "]},
 {"span", [{"class", "counter"}], ["\n            12\n          "]},
 {"span", [{"class", "counter"}], ["\n            2\n          "]},
 {"span", [{"class", "counter"}], ["\n            2\n          "]}]

共通のタグとクラスのデータのレポジトリ数, star数なども取れてしまいます。
ですがリストの2番目(3要素目)に入っていることがわかっているのでlist[2]を指定してデータを取得します。

iex(34)> Floki.find(body, "span.counter") |> Enum.at(2)
{"span", [{"class", "counter"}], ["\n            2\n          "]}

Enum.at(2)でlistの2番目を取得することができました。
ですが今は{tag, attribute, text}のtuppleが帰って来ています。
textを取得するためには

iex(37)> Floki.find(body, "span.counter") |> Enum.at(2) |> Floki.text()
"\n            2\n          "

これで取りたいfollowerの数が取れたのですが, 改行コードも付いて来てしまったのでパースしたいと思います。

iex(42)> followers = Floki.find(body, "span.counter") |> Enum.at(2) |> Floki.text()
"\n            2\n          "

iex(43)> String.strip(followers)
"2"

String.strip(変数)で改行コード, 空白文字をremoveしました。

一応取得したかったfollower数を取得することができました。

振り返ってみると今回のスクレイピングは一行でかけましたね。

HTTPoison.get!("https://github.com/takpy").body |> Floki.find("span.counter") |> Enum.at(2) |> Floki.text() |> String.strip()

パイプライン演算子は本当に気持ちがいい...

23
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?