Qiitaでストックされた記事の傾向と対策


さっき流れてきたTweetによると「4000 Contribution!」らしいので、今までどんな記事がストックされたのか、気になって(?)調べてみました。「対策」も何もないので「誰得」なことこの上ないですが。調査にはQiita API 2.0を使っています。

## 投稿数の推移

2015年7末現在、全部で64本。こんなに書いてたかな...。2013年は完全に飽きてますね。仕事が忙しい時ほど、無駄投稿が増えます。

年 | 記事の本数 | ストック数
:-- | --: | --:
2012 | 15本 | 305
2013 | 3本 | 42
2014 | 	25本 | 1849
2015 | 21本 | 1805

## ストック数の分布

だいたい、上位10本で全体の7割に達しています。100ストックあたりで壁があって、そこを越えると割と伸びやすいようです。たぶん、この辺を境にQiitaのニュースレターに載るのかな?

![Kobito.CW5Q8L.png](https://qiita-image-store.s3.amazonaws.com/0/1858/92cb07fd-6250-5649-101f-357c159b5ba1.png "Kobito.CW5Q8L.png")


## タイトル別ランキング

Riot, Browserify, gulpあたり興味をもってもらえたみたいで何よりです。Riotはしばらく前から「中の人」になったので、もうちょい投稿していきたいところ。デザイン関係も「読んだよ」と言ってくれるひとが結構いたのが嬉しかったです。

&nbsp; | タイトル | ストック数 | 年月
:-- | :-- | :-- | :--
1 | [Riot.js 2.0 を触ってみた — まだReactで消耗しているの?](http://qiita.com/cognitom/items/fb1295f3f93911e9e92d) | 542 | 2015年2月
2 | [Browserify: それはrequire()を使うための魔法の杖](http://qiita.com/cognitom/items/4c63969b5085c90639d4) | 477 | 2014年5月
3 | [デザインワークをGitに含めるべき? 含めないべき?](http://qiita.com/cognitom/items/f127891ab7e07c590dd0) | 382 | 2015年2月
4 | [ビルドツールまとめ。Gruntとかgulpとか (フロント寄り)](http://qiita.com/cognitom/items/db88babebeb869a4a198) | 339 | 2014年5月
5 | [gulp.js チートシート](http://qiita.com/cognitom/items/e542e6601ab6af8b6e1e) | 281 | 2014年6月
6 | [富豪実装なJavaScriptジオコーダーを作ってみた](http://qiita.com/cognitom/items/695843cea316fa6784eb) | 232 | 2015年7月
7 | [デザイナはWeb Componentsに夢を見るのか](http://qiita.com/cognitom/items/c5f17fd9b1c53c420232) | 179 | 2015年2月
8 | [CSS内の画像埋込で高速化(Data URI)](http://qiita.com/cognitom/items/3134467210e0022f4a02) | 144 | 2012年7月
9 | [gulpfile スタイルガイド - v0.5.0](http://qiita.com/cognitom/items/045c8596a30aa5ab8a47) | 139 | 2014年9月
10 | [BaaSはまだ戦国時代だったのか、まとめ。(執筆中)](http://qiita.com/cognitom/items/ead2837115bc900a0acc) | 119 | 2014年8月
11 | [AngularとBrowserifyの微妙すぎる関係](http://qiita.com/cognitom/items/1f5d82a4513af446cb57) | 81 | 2015年1月
12 | [Riot.js 2.0 情報まとめ](http://qiita.com/cognitom/items/54ae38c9a50dbbe28367) | 77 | 2015年2月
13 | [3時間でできるnpmモジュール](http://qiita.com/cognitom/items/75736e27cc7de151a7d5) | 75 | 2014年4月
14 | [Riot.js ソースコード完全解説](http://qiita.com/cognitom/items/eb6d56485fe517ccd9ee) | 73 | 2015年2月
15 | [コンポーネントを使うのはJSerじゃない、HTML/CSSコーダーだ](http://qiita.com/cognitom/items/2dacc00305534241c1f7) | 65 | 2015年3月
16 | [無謀にもJavaScriptなしでやってみる! Riot.js入門](http://qiita.com/cognitom/items/8010e0779950df574cc9) | 65 | 2015年3月
17 | [FacebookとGoogleだけ、やたら遅い場合の対処](http://qiita.com/cognitom/items/1f5dbe36e083f806d0b3) | 54 | 2014年10月
18 | [Chromeコンソールでお手軽クローリング](http://qiita.com/cognitom/items/babefa7b85ffc050d4bd) | 51 | 2014年5月
19 | [Ansibleでファイルの行を書き換える3つの方法](http://qiita.com/cognitom/items/57de72b739642041dcd5) | 45 | 2014年12月
20 | [gulp 3.7 リリース: CoffeeScriptネイティブに](http://qiita.com/cognitom/items/4468723674199cf5f9a5) | 44 | 2014年6月

## というわけで

オチも何もありませんが、時宜を得たもの、まとめ系、作ってみた系(=手をかけて調べた系)は、やはりニーズが強いですね。あと、Qiitaが特徴的なのは、内部の閲覧が一定数あるためか、初速が比較的つきやすいところでしょうか。感覚的にはこんな感じ。

- Qiita内部: 序盤とロングテール
- Twitter: 比較的いつでも
- はてなブックマーク: 中盤。ホッテントリ入りすると、異様に強い

商業誌/サイトに書くときは、締め切りに追われてる思い出ばかりですが、その点Qiitaは「思いついて書いちゃう」パターンがほとんど。気楽に書けるのが魅力ですが、深夜についつい書き出してしまうのが危ないです。(あああ、今回もそのパターンだ...)

## おまけ

データ取得に使ったスクリプトを貼っておきます。`gulpfile.coffee`として保存して`gulp`コマンドをたたくと、`profile.csv`に記事一覧を吐き出してくれるはずです。ストック数を簡単に取る方法がなさそうだったので、記事一件ごとに`total-count`を取得しました。あっという間にリミット(60回/時)に到達するので、[アクセストークン](https://qiita.com/api/v2/docs#%E8%AA%8D%E8%A8%BC%E8%AA%8D%E5%8F%AF)を取っておくと良いようです。ディレイを少しいれないと怒られる点も注意が必要かも。

```bash
$ npm i --save-dev coffee-script gulp request-promise
```

```coffeescript
# gulpfile.coffee
gulp    = require 'gulp'
request = require 'request-promise'
fs      = require 'fs'

QIITA_BASE = 'http://qiita.com/api/v2'
QIITA_USER = '' # ユーザ名を設定
QIITA_AUTH = '' # アクセストークンを設定
PER_PAGE   = 100 # 最大100

# デフォルト設定
request = request.defaults
  resolveWithFullResponse: true
  headers: Authorization: "Bearer #{ QIITA_AUTH }"

gulp.task 'default', (callback) ->
  posts = []
  request
    uri: "#{ QIITA_BASE }/users/#{ QIITA_USER }/items?per_page=#{ PER_PAGE }"
  .then (response) ->
    # ユーザの投稿一覧
    posts =
      for row in (JSON.parse response.body)
        id:         row.id
        title:      row.title
        created_at: row.created_at.replace /T.+$/, ''
    # 投稿ごとのストック数を取得
    # ただし、1投稿ごとしか取得できないため、thenで繋いで順番に実行
    promise = Promise.resolve()
    for i in [0...posts.length]
      do (i) -> promise = promise.then -> doItLater (cb) ->
        request
          uri: "#{ QIITA_BASE }/items/#{ posts[i].id }/stockers"
        .then (res) ->
          posts[i].count = res.headers['total-count']
          cb()
    promise
  .then ->
    # CSVファイルに保存
    stream = fs.createWriteStream 'profile.csv'
    stream.write "id,title,created_at,count\n"
    for post in posts
      stream.write "#{ post.id },\"#{ post.title }\",#{ post.created_at },#{ post.count || 0 }\n"
    stream.end()
    callback()
  return

# 少し待って実行するための関数
doItLater = (callback) ->
  new Promise (resolve, reject) ->
    setTimeout ->
      callback -> resolve()
    , 500

```