Qiita Advent Calendar 2023
Mix.install([
{:req, "~> 0.5"},
{:req_easyhtml, "~> 0.1"},
{:explorer, "~> 0.9"},
{:kino, "~> 0.14"},
{:kino_vega_lite, "~> 0.1"}
])
準備
alias Explorer.DataFrame
alias Explorer.Series
require Explorer.DataFrame
カレンダーデータの取得
req =
Req.new(http_errors: :raise)
|> ReqEasyHTML.attach()
calendar_df =
req
|> Req.get!(url: "https://qiita.com/advent-calendar/2023/elixir")
|> then(& &1.body["[data-js-react-on-rails-store=AppStoreWithReactOnRails]"].nodes)
|> Floki.text(js: true)
|> Jason.decode!()
|> get_in(["adventCalendars", "tableAdventCalendars"])
|> hd()
|> Map.fetch!("items")
|> Enum.frequencies_by(&get_in(&1, ["user", "urlName"]))
|> then(fn map ->
%{
name: Enum.map(map, fn {name, _} -> name end),
count: Enum.map(map, fn {_, count} -> count end)
}
end)
|> DataFrame.new()
|> dbg()
データテーブルの表示
calendar_df
|> DataFrame.sort_by(desc: count)
|> Kino.DataTable.new()
グラフの表示
x = Series.to_list(calendar_df["name"])
y = Series.to_list(calendar_df["count"])
VegaLite.new(width: 800, height: 400)
|> VegaLite.data_from_values(x: x, y: y)
|> VegaLite.mark(:bar)
|> VegaLite.encode_field(:x, "x", type: :nominal, sort: "-y", title: "アカウント名")
|> VegaLite.encode_field(:y, "y", type: :quantitative, title: "記事数")