Qiita
api

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

More than 1 year has passed since last update.

さっき流れてきた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

タイトル別ランキング

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

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

というわけで

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

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

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

おまけ

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

$ npm i --save-dev coffee-script gulp request-promise
# 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