$\huge{元氣ですかーーーーッ!!!}$
$\huge{元氣があればなんでもできる!}$
はじめに
闘魂とElixirが出会いました。
闘魂 meets Elixir.です。
Elixir meets 闘魂.でもよいです。
私は @kaizen_nagoya さんに感化されて1月1日から、AdventCalendar2022を書いてきました。
私のアドベントカレンダー一覧は、コチラです。
autoracex、闘魂ex Advent Calendar 2022 25日のまとめ記事です。
だれよりも本日の2022/12/25を楽しみにしていると自負しております。
iex> "Elixir" |> String.graphemes() |> Enum.frequencies()
%{"E" => 1, "i" => 2, "l" => 1, "r" => 1, "x" => 1}
完走賞
今年はQiitaさんが完走賞を創設されました。
私向きの賞レースです。
私はおもいます。
人類はアップデートしたのです。
12月に1人1記事なんとか投稿するペース感から、12月には1人25記事以上投稿することが当たり前の世界へ。
Qiitaさんの「完走賞」創設には、そういうメッセージが込められていることを私は感じました。
アウトプットは善いとおっしゃられる方がいます。わたしもそうだとおもいます。すぐには効果はでませんが、続けていくことでスキルアップを実感する瞬間がきます。エンジニアと呼ばれる方々がみな全員で一ヶ月間毎日、記事を書き連ねることは、世界文化の進展を加速させることになります。
私は賞なんてなくても2020年、2021年と12月には25記事以上投稿してきました。
私のように何もなくても自分でモチベーションを保てる人がいる一方で、そうではない大半の方へ向けたQiitaさんからの応援、叱咤激励なのだと私は捉えています。
気になったこと
2022年12月19日(月) 19:56 に、Qiitaさんからメールが届きました。
【残り1週間】Qiita Advent Calendar 2022のラストを駆け抜けましょう!
このメールの中で、130名の方が挑戦をしていると書いてありました。
私が主に購読、投稿(闘魂)しているElixir Advent Calendar 2022では、2022-12-25 20:10時点で7名が候補です。
いったいどのカレンダーで何人くらいの人がノミネートしているのかということが気になりました。
気になったら調べればいいのです。
カウントはざっくりとした方法です。
以下の通りです。
- カレンダーに参加登録がされていれば1カウント
- 本当に投稿したのかどうかまではチェックしていません
論よりRun
四の五の言わずにプログラムを作ります。
Livebook or IExで動かすことを想定しています。
Mix.install([:req, :floki])
HTTPクライアントとHTMLを解析するライブラリをインストールします。
categories = ~w(
https://qiita.com/advent-calendar/2022/categories/sponsor
https://qiita.com/advent-calendar/2022/categories/qiita_official
https://qiita.com/advent-calendar/2022/categories/programming_languages
https://qiita.com/advent-calendar/2022/categories/libraries
https://qiita.com/advent-calendar/2022/categories/databases
https://qiita.com/advent-calendar/2022/categories/web_technologies
https://qiita.com/advent-calendar/2022/categories/mobile
https://qiita.com/advent-calendar/2022/categories/devops
https://qiita.com/advent-calendar/2022/categories/iot
https://qiita.com/advent-calendar/2022/categories/os
https://qiita.com/advent-calendar/2022/categories/editors
https://qiita.com/advent-calendar/2022/categories/academic
https://qiita.com/advent-calendar/2022/categories/services
https://qiita.com/advent-calendar/2022/categories/company
https://qiita.com/advent-calendar/2022/categories/miscellaneous
https://qiita.com/advent-calendar/2022/ranking/feedbacks/categories/to_be_decided
)
全部のアドベントカレンダーが必要ですので、とりあえずQiitaさんが区分けされているカテゴリーのURLを並べます。
defmodule ScrapingCategory do
def run(base_url) do
IO.puts base_url
Stream.iterate(1, &(&1 + 1))
|> Enum.reduce_while([], fn page, acc ->
url = "#{base_url}?page=#{page}"
{:ok, %{body: html}} = Req.get(url)
{:ok, document} = Floki.parse_document(html)
max_page = Floki.find(document, "div.style-xkoxod span") |> max_page()
cont_or_halt = if page < max_page, do: :cont, else: :halt
{cont_or_halt, acc ++ do_run(document)}
end)
end
defp max_page([]), do: 0
defp max_page([{"span", [], [_current, {:comment, " "}, " / ", {:comment, " "}, max_page]}]), do: String.to_integer(max_page)
defp do_run(document) do
texts = Floki.find(document, "p.style-1d6vmtz") |> Enum.map(&Floki.text/1)
hrefs = Floki.find(document, "div.style-1tovpxo a") |> Enum.map(fn a -> Floki.attribute(a, "href") |> Enum.at(0) end)
Enum.zip(texts, hrefs)
end
end
各カテゴリは、いくつかのページに分かれていることがありますので、そのへんを考慮してカテゴリー内に属するすべてのカレンダーを取得します。
Flokiは適当に使っています。あんまり意味をわかっていません。もっとエレガントで効率のよい書き方があるかもしれません。おわかりの方はぜひ編集リクエストをください
適当に書いていると言っているのは、「CSS selectors」の話です。適当に書いています。CSSと言われると途端に力が抜けます。ファイトが湧いてきません。私の弱点です。
f = fn url ->
IO.puts url
with %{status: 200, body: html} <- Req.get!(url),
{:ok, parsed_doc} <- Floki.parse_document(html),
[{_tag, _attrs, json} | _] <- Floki.find(parsed_doc, "[data-js-react-on-rails-store=AppStoreWithReactOnRails]"),
{:ok, decoded} <- Jason.decode(json),
[table_advent_calendars | _] <- get_in(decoded, ["adventCalendars", "tableAdventCalendars"]) do
table_advent_calendars
|> Map.fetch!("items")
|> Enum.frequencies_by(&get_in(&1, ["user", "urlName"]))
|> Enum.sort_by(fn {_user, cnt} -> cnt end, :desc)
else
_ -> :error
end
end
この関数は、各アドベントカレンダーを解析して各人の投稿(闘魂)予約数を数えています。
ちなみに無名関数にしていますが、なにかモジュールを作ってその中の関数としてもよいです。寧ろそうすべきかとおもいます。あんまり時間もないので突貫小僧星野勘太郎です。
の記事でやっていることと同じです。
@mnishiguchi さんのおかげです。ありがとうございます。
部品は揃いました。
あとは大きなループで全体をまわしてやれば完成です。
{result_list, result_total} =(
categories
|> Enum.flat_map(&ScrapingCategory.run/1)
|> Enum.map(fn {name, path} ->
{name, path, f.("https://qiita.com#{path}")}
end)
|> Enum.reduce({[], 0}, fn {name, path, list_of_users}, {acc_list, acc_total} ->
finish_count = list_of_users |> Enum.count(fn {_user, cnt} -> cnt >= 25 end)
if finish_count > 0 do
{acc_list ++ [{name, path, list_of_users, finish_count}], acc_total + finish_count}
else
{acc_list, acc_total}
end
end)
)
# 以下マークダウンの表形式で出力
result_list
|> Enum.sort_by(fn {_name, _path, _list_of_users, finish_count} -> finish_count end, :desc)
|> Enum.reduce("| カレンダー | 完走賞ノミネート者数 |\n|:-|-:|\n", fn {name, path, _list_of_users, finish_count}, acc ->
acc <> "| [#{name}](https://qiita.com#{path}) | #{finish_count} |\n"
end)
|> Kernel.<>("||#{result_total}|")
|> IO.puts
結果のテーブルには、勇者たちのメンションを付けようかともおもいましたが、Elixir Advent Calendar 2022とは違って知らない方が多いし、アドハラになるといけませんのでやめておきました。
アドハラ
アドハラとは私が作った言葉です。
アドベントカレンダーを25記事以上書くことを強要する行為(厚意?)です。
受け取り手が嫌だとおもったらハラスメントになりますので気をつけないといけません。
実行結果
2022-12-25 20:51時点です。
23:59までが期限ですのでまだ増えるとおもいます。
私調べではトータル154名です。私のように一人で複数のカレンダーに完走賞ノミネートという人もいるとおもいますが、その重複排除はしていません。レアケースだとおもいますので。
ちなみに私は、「Elixir 」と「autoracex、闘魂ex Advent Calendar 2022」の2つにノミネートしています。
みなさまの完走を応援しています!
おわりに
Elixir Advent Calendar 2022はシリーズ数も多かったですが、完走賞のノミネート者数も多いことがわかりました。
アドハラしているのかも? と内心ビクビクしていましたが、Elixir Advent Calendar 2022カレンダーが他のカレンダーよりも多くの完走賞達成者を輩出しそうでうれしくもあります。
@RyoWakabayashi さんがLivebookでいい感じ(寛至)の記事にしてくれるとおもいます!
また明日からはアドベントカレンダー2023がはじまります!
がんばっていきましょう!
元氣があればなんでもできる!!!
$\huge{元氣があればなんでもできる!}$
$\huge{元氣ですかーーーーッ!!!}$
$\huge{元氣があればなんでもできる!}$
$\huge{1、2、3 ぁっダー!}$