はじめに
- ElixirConf EU VirtualでセッションをきいたCrawlyを試してみます
elixir 1.10.3-otp-23
erlang 23.0.1
What is Crawly ?
Crawly, a high-level web crawling & scraping framework for Elixir.
クローラーに必要なこと全部入りライブラリというところでしょうか。
セッションの中では以下の内容を熱っぽく語られていました。
- 他言語製のなにかにインスパイアを受けてElixirでつくっちゃおう
- ドキュメントを充実させる
- 電池入ではめ込んですぐにでも使えるもの
- Robots.txtに従ったり、JavaScriptのコンテンツをいい感じ(!?)にしたり
- アクセスの都度User-Agentを変えたりする
- を作りました!
0. 準備
1. プロジェクトをつくってREADME等に書いてあることをそのまま写します
- まずプロジェクトをつくります
$ mix new crawly_example --sup
$ cd crawly_example
- 次に依存関係を解決します
mix.exs
defp deps do
[
{:crawly, "~> 0.10.0"},
{:floki, "~> 0.26.0"}
]
end
$ mix deps.get
- サンプルモジュールを写します
- 作者 さんがErlang Solutionsの中の人のようで、スクレイピングするサイトはサンプルをそのまま使わせてもらいます
lib/crawly_example/esl_spider.ex
defmodule EslSpider do
use Crawly.Spider
alias Crawly.Utils
@impl Crawly.Spider
def base_url(), do: "https://www.erlang-solutions.com"
@impl Crawly.Spider
def init(), do: [start_urls: ["https://www.erlang-solutions.com/blog.html"]]
@impl Crawly.Spider
def parse_item(response) do
{:ok, document} = Floki.parse_document(response.body)
hrefs = document |> Floki.find("a.more") |> Floki.attribute("href")
requests =
Utils.build_absolute_urls(hrefs, base_url())
|> Utils.requests_from_urls()
title = document |> Floki.find("article.blog_post h1") |> Floki.text()
%{
:requests => requests,
:items => [%{title: title, url: response.request_url}]
}
end
end
config/config.exs
use Mix.Config
config :crawly,
middlewares: [
{Crawly.Middlewares.UserAgent,
user_agents: ["Crawly Bot", "Crawly Bot 1.0", "Crawly Bot 2.0", "Awesome Bot"]}
],
pipelines: [
Crawly.Pipelines.JSONEncoder,
{Crawly.Pipelines.WriteToFile, folder: "/tmp", extension: "jl"}
]
2. 実行
- 動かしてみましょう
$ iex -S mix
iex> Crawly.Engine.start_spider(EslSpider)
3. 結果確認
$ cat /tmp/EslSpider_2020_06_20_00_42_16_073891.jl
{"url":"https://www.erlang-solutions.com/blog.html","title":""}
{"url":"https://www.erlang-solutions.com/blog/welcome-to-our-new-blog.html","title":"Welcome to our new blog!!"}
{"url":"https://www.erlang-solutions.com/blog/mongooseim-1-6-1-is-released.html","title":"MongooseIM 1.6.1 is releasedMongooseIM 1.6.1 is released"}
{"url":"https://www.erlang-solutions.com/blog/secure-shell-for-your-erlang-node.html","title":"Secure Shell for Your Erlang NodeSecure Shell for Your Erlang NodeStarting upWrapping in an application"}
{"url":"https://www.erlang-solutions.com/blog/mongooseim-1-6-riak-devops-love-and-so-much-more.html","title":"MongooseIM 1.6: Riak, DevOps love, and so much more!"}
{"url":"https://www.erlang-solutions.com/blog.html","title":""}
{"url":"https://www.erlang-solutions.com/blog/welcome-to-our-new-blog.html","title":"Welcome to our new blog!!"}
-
EslSpider.parse_item
の結果のitems
に指定した形のものがファイルに書き出されるようです -
ファイル名の日時のところは適宜読み替えてください
その他
- Use-Agentをランダムに切り替える処理は、たぶんココ
Wrapping Up
- Enjoy!!!
iex> [87, 101, 32, 97, 114, 101, 32, 116, 104, 101, 32, 65, 108, 99, 104, 101, 109, 105, 115, 116, 115, 44, 32, 109, 121, 32, 102, 114, 105, 101, 110, 100, 115, 33]