Edited at

Qiitaレジェンド達の偉大さをシェル芸で眺めて2016年を振り返る

More than 1 year has passed since last update.


2016年の振り返り

eto_saru_kakizome.png

私事ですが、2016年のQiita振り返りをさせていただきます。

2016年に投稿したQiitaの記事は17本、これで18本目になります。

平均すると1カ月に1本以上書いてはいるのですが、時期的にはやはり波がありますね。

ネタのストックがなかったとか DevOps導入指南 執筆のタイミングと被ったとかいうのもあるかもしれませんが、下期は全体的に少なかったです。

1年の中で印象深かったのは、

の記事で、ありがたいことにこれだけで2000を超えるいいね1をいただくことができ、他の記事とあわせて年初に500程度だった総Contributionは現時点で3700を超えるまでになりました。

個人的にこうした数字で見える成果は好きなので、来年もアウトプットを続けるモチベーションになったと思っています。


Contributionの分析

tantei_boy.png

さて、現時点での総Contributionは上の記事1本によるところが大きいのですが、ちょっとContributionの分析をやってみます。


  • 総Contribution

  • 記事数

  • 記事あたりの平均Contribution(平均)

  • Top記事によるContribution(Top数)

  • Top記事によるContributionが総Contributionに占める割合(Top占有率)

総Contribution
記事数
平均
Top数
Top占有率

3799
26
146.115
2390
62.91%

という感じでした。

やはりTop記事による占有率が半分以上、運の要素があるとはいえ、ぽっと出感が否めません。

継続的によいアウトプットを出しつつ、よりContributionを高めていきたいと思います( 使命感 )


Qiitaレジェンド達はどうか

moses_umi.png

それではQiitaで 総ContributionのTOP100をひた走るQiitaレジェンド達 はどうなのでしょうか。

まず、Qiitaレジェンドの一覧を得なければなりません。

ありがたいことにランキングサイトを作ってくださった方がいました。たまに見てます^^(病気)。

そういえば現時点で僕は104位でした。もう少しでTOP100入り...!

こちらでTOP1002のユーザを確認することができます。

あとはそれぞれのユーザを確認してちまちま計算すれば大丈夫そうです。

それでは、地道に収集、計算していきたいと思います。

なお、たまたま私は シェル芸人3 を目指しておりますので、地道にワンライナーでの収集、計算にチャレンジします。環境はCentOS 7.2.15114です。

$ for PAGE in $(seq 1 5) ; do for USER in $(curl -s https://qiita-user-ranking.herokuapp.com/?page=${PAGE} | grep -E "第[0-9]*位" -A 1 | grep href | sed -e "s/^.*href=\".*\">\(.*\)<\/a>.*$/\1/g") ; do echo -en "@${USER}\t" ; curl -s http://qiita.com/${USER} | grep Contribution | sed -e "s/^.*<span class=\"userActivityChart_statCount\">\([0-9]*\)<\/span><br \/> <span class=\"userActivityChart_statUnit\">Contribution<\/span>.*<span class=\"userActivityChart_statCount\">\([0-9]*\)<\/span><br \/> <span class=\"userActivityChart_statUnit\">Items<\/span>.*<span class=\"fa fa-like\"><\/span> \([0-9]*\)<\/div>.*<a itemprop=\"url\" href=\"\(.*\)\">\(.*\)<\/a><ul class=\"list-inline userPopularItems_tags tagList\">.*\(itemprop.*\)\{,4\}.*$/\1\t\2\t\3\t\[\5\](http:\/\/qiita.com\4)/g" ; done ; done | awk -F"\t" '{if(NF==5) print "|"NR"|"$1"|"$2"|"$3"|"$2/$3"|"$4"|"$4/$2*100"%|"$5}'

出力がそのままMarkdownの表形式になるようにしたので見出しをつけてペタリ。

ランク
ユーザ名
総Contribution
記事数
平均いいね
Top数
Top占有率
Top記事

1
@hirokidaichi
30990
33
939.091
4641
14.9758%
ペアプログラミングして気がついた新人プログラマの成長を阻害する悪習

2
@jnchito
26953
135
199.652
2478
9.19378%
モデルやメソッドに名前を付けるときは英語の品詞に気をつけよう

3
@suin
20120
652
30.8589
4034
20.0497%
【まとめ】これ知らないプログラマって損してんなって思う汎用的なツール 100超

4
@icoxfog417
18927
124
152.637
2057
10.8681%
Pythonを書き始める前に見るべきTips

5
@shu223
17091
156
109.558
1239
7.24943%
ディープラーニングの有名ライブラリ5種を最短距離で試す半日コース(TensorFlow, Chainer, Caffe, DeepDream, 画風変換)

6
@KeithYokoma
16737
138
121.283
3919
23.4152%
うまくメソッド名を付けるための参考情報

7
@yuku_t
16134
182
88.6484
1352
8.37982%
中規模Web開発のためのMVC分割とレイヤアーキテクチャ

8
@kenju
15443
120
128.692
2173
14.0711%
中上級者になるためのJavaScript【知識編】

9
@KENJU
15443
120
128.692
2173
14.0711%
中上級者になるためのJavaScript【知識編】

10
@mizchi
15101
162
93.216
1795
11.8866%
春からはじめるモダンJavaScript / ES2015

11
@awakia
14642
150
97.6133
1547
10.5655%
開発フロー研修 @ Wantedly

12
@opengl-8080
14161
211
67.1137
1205
8.50929%
AngularJS使い方メモ

13
@mpyw
13960
235
59.4043
1732
12.4069%
PHPでデータベースに接続するときのまとめ

14
@mono0926
13289
89
149.315
1315
9.8954%
ローディング時のズルい進捗表示

15
@muran001
12312
34
362.118
4191
34.04%
Gitでやらかした時に使える19個の奥義

16
@haminiku
12144
70
173.486
2800
23.0567%
2016年 独りで新規WEBサービスを開発・運用した際の知見

17
@b4b4r07
11652
56
208.071
1430
12.2726%
さいつよのターミナル環境を構築しよう

18
@appwatcher
11583
59
196.322
2004
17.3012%
iOSでこんなアプリ,こんな機能を作りたかったらこれを見ろ!作りたいアプリに対応するクラス、フレームワーク、ライブラリのまとめ!

19
@edo_m18
11550
363
31.8182
1017
8.80519%
WebのUIテスト自動化 - Seleniumを使ってみる

20
@cognitom
11489
89
129.09
1678
14.6053%
そろそろ真面目に、HTMLで帳票を描く話をしようか

21
@susieyy
10847
47
230.787
1877
17.3043%
Swiftで作られたイケてるUIライブラリたち

22
@kazunori279
10262
36
285.056
1259
12.2686%
Cloud Vision APIの凄さを伝えるべくRasPi botとビデオを作った話

23
@yimajo
10247
127
80.685
688
6.71416%
iOS実機のSSL通信をプロキシによって傍受したり改ざんする方法

24
@hkusu
9243
201
45.9851
963
10.4187%
[WEB開発] 私的な最近のおすすめサービス/ツール 14選 ~2014年版~

25
@zaru
9393
96
97.8438
1525
16.2355%
Webフロントエンド表示速度、最速化手法まとめ

26
@uasi
9000
116
77.5862
1977
21.9667%
英語のコメントや issue で頻出する略語の意味 (FYI, AFAIK, ...)

27
@kidach1
8990
83
108.313
1261
14.0267%
Nginx導入時、サクッと対応しておくと良いかもしれない

28
@ynakayama
8937
186
48.0484
632
7.07172%
機械学習や統計に関する情報収集

29
@HirofumiYashima
8947
633
14.1343
482
5.38728%
クロージャってどんなときに使うの? ~ 利用場面を 3つ 挙げてみる

30
@joker1007
8766
96
91.3125
999
11.3963%
てめえらのRailsはオブジェクト指向じゃねえ!まずはCallbackクラス、Validatorクラスを活用しろ!

31
@koher
8540
50
170.8
1247
14.6019%
null安全でない言語は、もはやレガシー言語だ

32
@tukiyo3
8527
1421
6.0007
356
4.17497%
たくさんあるオープンソースライセンスのそれぞれの特徴のまとめ

33
@kenmatsu4
8515
60
141.917
1557
18.2854%
【機械学習】ディープラーニング フレームワークChainerを試しながら解説してみる。

34
@takeharu
8302
18
461.222
1304
15.7071%
JavaScriptの「this」は「4種類」??

35
@hshimo
8075
276
29.2572
2051
25.3994%
プログラマが独立・起業する時によくするミスと対策 まとめ

36
@tadsan
7795
145
53.7586
1856
23.8101%
ライセンスの選択を恐れる必要はありません

37
@kawasima
7707
73
105.575
634
8.22629%
多い日も安心設計

38
@usagimaru
7578
155
48.8903
879
11.5994%
iOS ヒューマンインターフェースの原則

39
@kawaz
7563
138
54.8043
1941
25.6644%
最強のSSH踏み台設定

40
@sion_cojp
7343
33
222.515
3473
47.2967%
インフラエンジニアとしてよく使うコマンド集

41
@syui
7318
211
34.6825
1344
18.3657%
MacBookAirで使っている便利ツール

42
@okappy
7218
28
257.786
4918
68.1352%
非デザイナーエンジニアが一人でWebサービスを作るときに便利なツール32選

43
@gaogao_9
7084
13
544.923
3963
55.943%
旧石器時代のJavaScriptを書いてる各位に告ぐ、現代的なJavaScript超入門 Section1 ~すぐにでも現代っぽく出来るワンポイントまとめ~

44
@zembutsu
6870
76
90.3947
1262
18.3697%
Docker 入門ハンズオン資料

45
@kaiinui
6809
46
148.022
2474
36.3343%
最近の行儀のよい JavaScript の書き方

47
@vvakame
6648
39
170.462
1201
18.0656%
Gradle入門

48
@Jxck_
6580
62
106.129
1055
16.0334%
DELETE_FLAG を付ける前に確認したいこと。

49
@tbpgr
6386
681
9.37739
667
10.4447%
Markdown記法 サンプル集

50
@armorik83
6366
107
59.4953
1321
20.7509%
AngularJSモダンプラクティス

51
@Quramy
6351
75
84.68
1767
27.8224%
Electronでアプリケーションを作ってみよう

52
@yuya_presto
6324
38
166.421
754
11.9228%
Gitコンフリクト解消ガイド(git mergetoolの使い方)

53
@gogotanaka
6129
56
109.446
3237
52.8145%
ネイティブと働いて分かった英語コミットメッセージの頻出動詞10つ

54
@yaotti
5895
151
39.0397
1251
21.2214%
gitでありがちな問題の解決方法まとめ

55
@n0bisuke
5802
222
26.1351
690
11.8925%
3行のソースコードを入れるだけで機械学習できると噂のindicoをNode.jsで使って機械学習入門してみる

56
@tonkotsuboy_com
5788
83
69.7349
798
13.7871%
2016年新機能! GitHubのmasterブランチをWebページとして公開する手順

57
@r7kamura
5581
56
99.6607
655
11.7362%
RailsでAPIをつくるときのエラー処理

58
@tatesuke
5271
34
155.029
2056
39.0059%
You Don't Need jQuery

59
@jacksuzuki
5268
5
1053.6
5258
99.8102%
ロシアの天才ハッカーによる【新人エンジニアサバイバルガイド】

60
@tag1216
5270
64
82.3438
2475
46.9639%
インフラエンジニアじゃなくても押さえておきたいSSHの基礎知識

61
@voluntas
5100
107
47.6636
843
16.5294%
docker コマンド チートシート

62
@amay077
5087
212
23.9953
257
5.05209%
NHK紅白の Android/iPhone アプリが .NET/Xamarin 製だったということ

63
@hnakamur
5053
187
27.0214
497
9.83574%
ちょっとしたHTMLはGitHub Gistに置いてbl.ocks.orgで表示するのがお手軽です

64
@daxanya1
5042
28
180.071
4018
79.6906%
数学を避けてきた社会人プログラマが機械学習の勉強を始める際の最短経路

65
@y_hokkey
5008
52
96.3077
1473
29.4129%
Dockerで即実行できる、社内・自宅向けオープンソースWebアプリ

66
@koba04
4970
38
130.789
739
14.8692%
私のJavaScript情報の集め方

67
@shibukawa
4927
81
60.8272
815
16.5415%
オブジェクト指向と20年戦ってわかったこと

68
@magicant
4871
33
147.606
1994
40.9362%
クラスの命名のアンチパターン

69
@koogawa
4858
55
88.3273
1117
22.993%
iPhoneアプリ申請やAppleの審査に関するメモ

70
@puriketu99
4791
183
26.1803
791
16.5101%
機械学習クソ素人の俺がプロダクトをリリースするまでの2ヶ月で覚えたこと

71
@hidekuro
4731
79
59.8861
1764
37.286%
VagrantとDockerについて名前しか知らなかったので試した

72
@nekoneko-wanwan
4684
56
83.6429
1365
29.1418%
はじめてajaxを使うときに知りたかったこと

73
@okmttdhr
4664
63
74.0317
1918
41.1235%
ここ数年前から2015/5までのモダンフロントエンドを総まとめしてみた

74
@mochizukikotaro
4581
178
25.736
855
18.664%
初心者がAWSでミスって不正利用されて$6,000請求、泣きそうになったお話。

75
@chuck0523
4567
62
73.6613
1367
29.9321%
フロントエンドエンジニアが暇なときにやると良いかもしれないこと

76
@satomyumi
4521
243
18.6049
487
10.772%
覚えておきたい Vim コマンド 備忘録

77
@m-yamashita
4508
12
375.667
3361
74.5563%
初心者向け、「上手い」シェルスクリプトの書き方メモ

78
@kuni-nakaji
4484
17
263.765
2197
48.9964%
httpsだからというだけで安全?調べたら怖くなってきたSSLの話!?

79
@kazukichi
4484
30
149.467
1396
31.1329%
エンジニアで稼ぐために大切な15のコト

80
@disc99
4471
22
203.227
1817
40.6397%
Javaを使うなら知っておきたい技術、フレームワーク、ライブラリ、ツールまとめ

81
@hachi8833
4437
45
98.6
2569
57.8995%
Vim幼稚園からVim小学校へ

82
@makoto_kw
4402
59
74.6102
641
14.5616%
趣味でつくるiOSアプリこそJenkinsでリリースを自動化

83
@Hiraku
4370
111
39.3694
1162
26.5904%
WebAPIリクエスト仕様書としてcurlコマンドのご提案

84
@howdy39
4376
19
230.316
1166
26.6453%
フロントエンドにテストを導入

85
@mima_ita
4339
99
43.8283
587
13.5285%
あなたのおっしゃるレビューってどのことかしら?

86
@ukiuni@github
4286
56
76.5357
1633
38.1008%
JavaScriptを読んでて「なにこれ!?」と思うけれど調べられない記法8選。

87
@hik0107
4305
21
205
758
17.6074%
Pythonでデータ分析するのに必要なツールのまとめ

88
@pugiemonn
4234
249
17.004
814
19.2253%
こんなHTMLとCSSのコーディング規約で書きたい

89
@ryounagaoka
4230
47
90
1752
41.4184%
もう逃げない。HTMLのviewportをちゃんと理解する

90
@tenntenn
4230
61
69.3443
1597
37.7541%
Go言語の初心者が見ると幸せになれる場所 #golang

91
@futoase
4156
100
41.56
595
14.3167%
【個人メモ】CentOS環境に登録するyumリポジトリ

92
@reikubonaga
4115
61
67.459
680
16.5249%
iOS開発する上で絶対に押さえておく8つの項目

93
@konifar
4053
92
44.0543
231
5.69948%
Android Studioのgradleビルドを高速化する

94
@harukasan
4030
52
77.5
976
24.2184%
我々はどのようにして安全なHTTPS通信を提供すれば良いか

95
@k-shogo
4026
18
223.667
1450
36.0159%
無料のSSL証明書StartSSLを活用する

96
@nori0620
4018
11
365.273
1743
43.3798%
[iOS] 新言語SwiftがObjective-Cよりも良いところ

97
@k0kubun
4015
41
97.9268
858
21.3699%
ActiveRecordのjoinsとpreloadとincludesとeager_loadの違い

98
@Hironsan
4008
36
111.333
889
22.1806%
機械学習を使って作る対話システム

99
@merrill
3991
37
107.865
996
24.9562%
Swift でアプリ開発を1ヶ月やってみて感じた Xcode の効率的な使い方と、Web と連動するときのプラクティス

100
@horimislime
3975
35
113.571
1065
26.7925%
APIドキュメントを書くのが楽になるツールまとめ

やはり上位のQiitaレジェンドは何か1つの記事で稼いだという感じでもなく、Top記事が1000いいねを超えていても占有率は高々20%という感じが大半のようです。

例外的なのは @jacksuzuki さんですかね...。

僕もいいねせずにはいられませんでしたが、 ロシアの天才ハッカーによる【新人エンジニアサバイバルガイド】 が1記事で5000を超えるいいねを集め、 占有率99.8102% というまた違ったレジェンドっぷりを輝かせております。

他に目立つものといえば、全体でもトップの @hirokidaichi さんは平均いいねが1000近く、ある程度数を重ねられている方でこの数値では圧倒的。

他には、 @tukiyo3 さんの 記事数1421 なんてのもすごい数字です。 @tbpgr さんの681でもすごい数字なのにその2倍近いとは恐れ入ります。。。


シェル芸の解説

school_sensei_kokuban.png

せっかくなので収集、計算に使ったシェル芸の簡単な解説をしておきます。


  1. Qiita User RankingからTOP100ユーザ名を抜き出す

  2. 各ユーザのQiitaトップページを取得する

  3. Qiitaトップページから「総Contribution」「記事数」「Top数」「Top記事」を抜き出す

  4. それぞれの値から「平均いいね」「Top占有率」を計算し、出力する


1. Qiita User RankingからTOP100ユーザ名を抜き出す

ランキングページの中身を見ると、

<h2>ランキング一覧</h2>

<p>
第1位
<a href="http://qiita.com/hirokidaichi">hirokidaichi</a>,
30974
</p>
<p>
第2位
<a href="http://qiita.com/jnchito">jnchito</a>,
26930
</p>
<p>
第3位
<a href="http://qiita.com/suin">suin</a>,
20108
</p>

というような感じになっています。そこで、特徴的な「第○位」に着目し、

$ grep -E "第[0-9]*位" -A 1 | grep href | sed -e "s/^.*href=\".*\">\(.*\)<\/a>.*$/\1/g"

の要領でユーザ名を抜き出しています。

欲しいユーザ名は「第○位」の1行下にあるため、 grep -A 1 で出すことにしています。あとはみんな大好き正規表現で抽出しているだけですね。

ランキングページ自体は20件ずつの表示になっているため、

$ for PAGE in $(seq 1 5) ; do curl -s https://qiita-user-ranking.herokuapp.com/?page=${PAGE} ; done

で合計100件分をまわしています。

curl -s オプションで邪魔なステータスを出ないようにしています。


2. 各ユーザのQiitaトップページを取得する

こちらも簡単です。先ほど取得したユーザ名一覧を使って、

$ for USER in $([ユーザ名一覧]) ; do curl -s http://qiita.com/${USER} ; done

とするだけです。


3. Qiitaトップページから「総Contribution」「記事数」「Top数」「Top記事」を抜き出す

おわかりかと思いますが、ここが一番面倒です。

Qiitaユーザトップのソースを見てもらえばお分かりになるかと思いますが、実はこのページから 得たい情報の全てが1行のソースに存在 しています。

もちろんコードによって生成されていますので、法則性があり正規表現で捕まえられるのですが、ピンポイントで捕まえるのには結構苦労しました。

sed -e "s/^.*<span class=\"userActivityChart_statCount\">\([0-9]*\)<\/span><br \/> <span class=\"userActivityChart_statUnit\">Contribution<\/span>.*<span class=\"userActivityChart_statCount\">\([0-9]*\)<\/span><br \/> <span class=\"userActivityChart_statUnit\">Items<\/span>.*<span class=\"fa fa-like\"><\/span> \([0-9]*\)<\/div>.*<a itemprop=\"url\" href=\"\(.*\)\">\(.*\)<\/a><ul class=\"list-inline userPopularItems_tags tagList\">.*\(itemprop.*\)\{4\}.*$/\1\t\2\t\3\t\[\5\](http:\/\/qiita.com\4)/g"

どこまで行っても正規表現なので、興味がある方はページのソースと正規表現でにらめっこしてみてください。

1つだけ説明を加えておくと、「Top数」「Top記事」を取るのが大変でした。

1行が長いため、色々な部分で .* のワイルドカード的な表現を使っているのですが、 最長一致 などの都合でなかなか思うように抜き出しができませんでした。

最終的には、Top5記事に対するitempropを手掛かりに、最初の1つにパターンマッチをかけ、残り4つには \(itemprop.*\)\{4\} を引っ掛けることでTop記事に関する情報だけを抜き出しました。


4. それぞれの値から「平均いいね」「Top占有率」を計算し、出力する

あとは awk を使った簡単な計算です。

sed の出力をタブでさせていたので、デリミタをタブにしつつ各行の値を計算して出力しています。

ここでランクが出力されますが、ストリームのレコード番号を格納する NR で出しています。結構便利。

ちまちま挟んであるパイプはMarkdownでの表にするためですね。

awk -F"\t" '{if(NF==5) print "|"NR"|"$1"|"$2"|"$3"|"$2/$3"|"$4"|"$4/$2*100"%|"$5"|"}'

条件で NF==5 を指定していますが、それはこのあと出てきます。


46位がいない件

business_karoushi.png

お気づきの方もいらっしゃるでしょうか、実は上の表では 46位が欠けています

46位にランクされているのは @Qiita さんなのですが、投稿記事数が4でTOP100ユーザの中で唯一「 投稿記事数が5未満 」となっています。

どうして上の表に出てこないかというと、処理説明3のところで、


Top5記事に対するitempropを手掛かりに、最初の1つにパターンマッチをかけ、残り4つには \(itemprop.*\)\{4\} を引っ掛ける


と書いていたのですが、投稿記事数が4つしかない @Qiita さんは上記の正規表現で上手く値が取れませんでした。

そのため、 sed の結果としてフィールド数が足りない状態であるため、最後の awkNF==5 の条件をつけることで結果から弾いています。

そもそももっと頭のいい正規表現を書ければ今の方針でもなんとかなったのかと思いますが、15分考えてもいいものが浮かばなかったので諦めました5

何かいい方法をお持ちの方はぜひご指導をお願いいたしますm(_ _)m

ちなみに @Qiita さんのContributionまわりは下記の感じです。

ランク
ユーザ名
総Contribution
記事数
平均いいね
Top数
Top占有率
Top記事

46
@Qiita
6743
4
1685.75
5417
80.3351%
Markdown記法 チートシート

チートシートは僕もたいへんお世話になりました。


おわりに

シェル芸たのしい^^

来年は sed awk とかメジャーなものだけじゃなく、もっと黒魔術っぽいシェル芸を身に着けたいです。がんばろう。

pose_ganbarou_man.png





  1. 投稿した当時はまだストックによるContribution反映でした。 



  2. なお、こちらのサイトの仕様上「サイトにある情報は結構タイムラグがあったりします」とのことなので、実際のTOP100ではない可能性があります。 



  3. シェル芸: マウスも使わず、ソースコードも残さず、GUIツールを立ち上げる間もなく、あらゆる調査・計算・テキスト処理をCLI端末へのコマンド入力一撃で終わらすこと。あるいはそのときのコマンド入力のこと。(シェル芸の定義バージョン1.1



  4. GNU bash 4.2.46, GNU sed 4.2.2, GNU Awk 4.0.2でした。 



  5. 組織アカウントだし、まぁいいかな、なんて...(逃げ)