記事初出時点では2021年12月24日までの情報でしたが、2021年12月25日までの情報を反映させました。
アドベントカレンダーにはどのような記事を紐付けていいのですか?
Qiita Advent CalendarにはQiitaはもちろんZennやnote、はてなブログ、個人ブログなど、エンジニアに関わる内容であればどのサイトの記事でも歓迎です。Qiita Advent Calendar について | Qiita Support https://help.qiita.com/ja/articles/qiita-adcal-1#faq
さて、今年の Qiita Advent Calendar の記事の公開先は「Qiita で公開」と「Zenn で公開」のどちらが多かったのでしょうか?
実装方法など
本記事をお読みの方は何よりも結果を先に知りたいかと思いますので、このために作成したプログラムなどについては記事末尾にまとめて記載します。キーワードだけ列挙しておきます。
Swift, Swift Concurrency, SwiftUI, Combine, Xcode 13.2, Swift Playgrounds 4
iOS App, iPadOS App, macOS Command Line Tool, Swift Package, Kanna
注意点
後述しますが、Qiita Advent Calendar 2021 のカレンダー数は約 700 であり、それらすべてにアクセスしてスクレイピングを行いました。ソフトウェアを開発・実行するときは以下に注意して行いました。
- User-Agent を設定し、その中に自分への連絡先情報を含める
- 実行にあたって Qiita API は使用していないが、Qiita API v2ドキュメント にある「利用制限」を参考に、リクエストの間隔は最低60秒以上空けるようにする
利用制限
認証している状態ではユーザごとに1時間に1000回まで、認証していない状態ではIPアドレスごとに1時間に60回までリクエストを受け付けます。Qiita API v2ドキュメント - Qiita:Developer https://qiita.com/api/v2/docs
そのため、すべてのデータの取得タイミングに60秒の間隔がありますので、タイミングによっては以下に示した結果が現在の状況を示していない場合があります。
(実行期間: 2021年12月24日10時33分ごろ 〜 2021年12月24日22時58分ごろ つまり2021年12月25日公開の記事が含まれていません)
(2021年12月25日までの情報を反映させました 実行期間: 2021年12月26日0時33分ごろ 〜 2021年12月26日14時47分ごろ)
結果(全体)
ドメイン | 記事数 | 割合 |
---|---|---|
qiita.com | 7760 | 60.3% |
zenn.dev | 888 | 6.9% |
note.com | 720 | 5.6% |
medium.com | 129 | 1.0% |
Qiita公開 のほうが多い
Qiita で公開のほうが多かった
というわけで、今年の Qiita Advent Calendar は、Qiita で公開された記事数が Zenn で公開された記事数の約8.9倍という結果でした。
…と、ここで思い浮かぶのは、「カレンダーカテゴリー別だと違う結果になるのではないか?」という予想です。確認してみることにしましょう。
結果(カレンダーカテゴリー別)
プレゼント
ドメイン | 記事数 | 割合 |
---|---|---|
qiita.com | 241 | 85.2% |
zenn.dev | 7 | 2.5% |
note.com | 5 | 1.8% |
Qiita公開 のほうが多い
Qiita主催
ドメイン | 記事数 | 割合 |
---|---|---|
qiita.com | 97 | 82.2% |
zenn.dev | 2 | 1.7% |
Qiita公開 のほうが多い
プログラミング言語
ドメイン | 記事数 | 割合 |
---|---|---|
qiita.com | 714 | 57.5% |
zenn.dev | 151 | 12.9% |
Qiita公開 のほうが多い
ライブラリ・フレームワーク
ドメイン | 記事数 | 割合 |
---|---|---|
qiita.com | 454 | 55.9% |
zenn.dev | 90 | 11.1% |
github.com | 16 | 2.0% |
Qiita公開 のほうが多い
データベース
ドメイン | 記事数 | 割合 |
---|---|---|
qiita.com | 63 | 40.9% |
scrapbox.io | 25 | 16.2% |
zenn.dev | 13 | 8.4% |
Qiita公開 のほうが多い
Webテクノロジー
ドメイン | 記事数 | 割合 |
---|---|---|
qiita.com | 166 | 53.4% |
zenn.dev | 42 | 13.5% |
note.com | 35 | 11.3% |
Qiita公開 のほうが多い
モバイル
ドメイン | 記事数 | 割合 |
---|---|---|
qiita.com | 129 | 61.7% |
zenn.dev | 41 | 19.6% |
Qiita公開 のほうが多い
DevOps・インフラ
ドメイン | 記事数 | 割合 |
---|---|---|
qiita.com | 248 | 55.4% |
zenn.dev | 49 | 10.9% |
Qiita公開 のほうが多い
IoT・ハードウェア
ドメイン | 記事数 | 割合 |
---|---|---|
qiita.com | 332 | 68.2% |
zenn.dev | 22 | 4.5% |
Qiita公開 のほうが多い
OS
ドメイン | 記事数 | 割合 |
---|---|---|
qiita.com | 95 | 77.2% |
github.com | 3 | 2.4% |
zenn.dev | 1 | 0.8% |
Qiita公開 のほうが多い
エディタ
ドメイン | 記事数 | 割合 |
---|---|---|
zenn.dev | 41 | 32.3% |
qiita.com | 33 | 26.0% |
twitter.com | 23 | 18.1% |
note.com | 8 | 6.3% |
Zenn公開 のほうが多い
学術
ドメイン | 記事数 | 割合 |
---|---|---|
qiita.com | 178 | 68.7% |
zenn.dev | 19 | 7.3% |
Qiita公開 のほうが多い
サービス・アプリケーション
ドメイン | 記事数 | 割合 |
---|---|---|
qiita.com | 890 | 57.0% |
zenn.dev | 100 | 6.4% |
note.com | 75 | 4.8% |
dev.classmethod.jp | 60 | 3.8% |
medium.com | 28 | 1.8% |
Qiita公開 のほうが多い
企業・学校・団体
ドメイン | 記事数 | 割合 |
---|---|---|
qiita.com | 3952 | 61.5% |
note.com | 431 | 7.4% |
zenn.dev | 234 | 4.0% |
medium.com | 85 | 1.5% |
Qiita公開 のほうが多い
その他
ドメイン | 記事数 | 割合 |
---|---|---|
qiita.com | 528 | 58.9% |
note.com | 127 | 14.2% |
zenn.dev | 66 | 7.4% |
Qiita公開 のほうが多い
未設定
集計せず
「Zenn で公開」の割合が多いカテゴリーがあった!
なんと「エディタ」カテゴリーでは Qiita で公開された記事数よりも、Zenn で公開された記事数のほうが多いという結果でした。
そもそも「エディタ」カテゴリーでは Twitter での公開も多くあり、かなり分散されているのが印象的でした。
また、今回は「ドメイン」で集計していますので、独自ドメインが設定可能なはてなブログや note など、サービス単位でまとめるとまた違った結果が見えてくる可能性もあります。
さらに「カテゴリー」別ではなくそれぞれのカレンダーごとに見てもおもしろいかもしれません。
今回、データを集計するために得たデータについては GitHub で公開していますので、気になる方はこの記事の続きをお読みください…。
実施方法
Mac・iPad の Swift Playgrounds 4 および Mac の Xcode 13.2 で開発可能な .swiftpm プロジェクトを開発しました。
これにより iOS & iPadOS App、macOS Command Line Tool のいずれでも動作します。行った処理は大まかに以下のとおりです。
- Qiita Advent Calendar 2021 に登録されているすべてのカレンダーの各情報を JSON に保存する
- カレンダータイトル
- カレンダー URL
- カレンダー参加者数(参加者数がゼロのカレンダーはここで弾く)
- 「1.」の情報を元に、各カレンダーの詳細情報と登録されている記事の各情報を JSON に保存する
- カレンダータイトル
- カレンダーカテゴリ
- カレンダー作成者
- カレンダー参加者数
- カレンダー URL
- カレンダー総 LGTM 数
- カレンダー購読者数
- 登録されている記事情報
- シリーズ(カレンダー1、カレンダー2、…)
- n日目
- 記事タイトル
- 記事 URL
- 記事作成者
- 「2.」の情報をまとめて JSON として出力する
- Qiita Advent Calendar 2021 全体の記事総数
- 記事 URL にあるドメインとその数
HTML のパーサーには Kanna を用いました。
ディレクトリ構成
基本的には .swiftpm の中に Swift ファイルを配置し、macOS Command Line Tool で使用するための main.swift
のみ外側に持ってきています。macOS Command Line Tool から見える main.swift
以外の Swift ファイルは、.swiftpm の中のディレクトリのシンボリックリンクになっています。
QACPercentageSurvey
├── README.md
├── Package.swift
├── Sources
│ ├── 1-StoreCalendarsData
│ │ └── main.swift
│ ├── 2-StoreArticlesData
│ │ └── main.swift
│ ├── 3-AggregateHostPercentages
│ │ └── main.swift
│ └── AppModule
│ ├── Entities -> ../../QACPercentageSurvey.swiftpm/Entities
│ ├── Extensions -> ../../QACPercentageSurvey.swiftpm/Extensions
│ └── Utilities -> ../../QACPercentageSurvey.swiftpm/Utilities
└── QACPercentageSurvey.swiftpm
├── Package.swift
├── QACPercentageSurveyApp.swift
├── Assets.xcassets
│ ├── AccentColor.colorset
│ │ └── Contents.json
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── PlaceholderAppIcon-gift-1024.png
│ │ ├── PlaceholderAppIcon-gift-60@2x.png
│ │ ├── PlaceholderAppIcon-gift-60@3x.png
│ │ ├── PlaceholderAppIcon-gift-76@2x.png
│ │ └── PlaceholderAppIcon-gift-83.5@2x.png
│ └── Contents.json
├── Entities
│ ├── AggregateHostPercentagesResult.swift
│ ├── QACalendar.swift
│ ├── QACalendarArticle.swift
│ ├── QACalendarArticlesData.swift
│ └── QACalendarsData.swift
├── Extensions
│ ├── ActivityIndicatorView.swift
│ ├── ActivityView.swift
│ ├── JSONDecoder+Extensions.swift
│ └── JSONEncoder+Exntensions.swift
├── Utilities
│ ├── FileHelper.swift
│ ├── MyURLSession.swift
│ ├── QACHelper.swift
│ ├── QACHelperFor1-StoreCalendarsData.swift
│ └── QACHelperFor2-StoreArticlesData.swift
└── Views
├── 1-StoreCalendarsDataView.swift
├── 2-StoreArticlesDataView.swift
└── 3-AggregateHostPercentagesResultView.swift
HTTP リクエストの間隔を60秒空ける
一度に大量のアクセスを行わないようにするため、async な Task.sleep(nanoseconds:)
を使って HTTP リクエストの間隔を最低60秒空けるようにしました。
また、残りの待機時間が何秒かを Combine の @Published
で伝えるようにしました。
import SwiftUI
@MainActor
struct StoreArticlesDataView: View {
@ObservedObject private var session = MyURLSession.shared
// Text("\(MyURLSession.shared.waitingTime) 秒後に接続します…")
// .monospacedDigit()
}
import Foundation
import Combine
public class MyURLSession: ObservableObject {
public static var shared = MyURLSession()
// ...
@MainActor @Published private(set) var waitingTime: Int = 0
@MainActor private func set(waitingTime: Int) {
self.waitingTime = waitingTime
}
private var session: URLSession { /* ... */ }
private var previousDate: Date? = nil
public func data(from url: URL) async throws -> Data {
// ...
if let previousDate = previousDate {
// Qiita API v2 ドキュメント https://qiita.com/api/v2/docs の「利用制限」を参考に、自主的に前回のアクセスから最低 60 秒は間隔を空ける
let interval = DateInterval(start: previousDate, end: Date())
let requiredWaitingTime = 60 - Int(interval.duration)
if requiredWaitingTime > .zero {
await set(waitingTime: requiredWaitingTime)
for _ in 0..<requiredWaitingTime {
try await Task.sleep(nanoseconds: 1 * 1000 * 1000 * 1000)
await set(waitingTime: waitingTime - seconds)
}
}
}
let (data, _) = try await session.data(from: url)
previousDate = Date()
return data
}
}
使用したプログラム・生データ JSON の公開
この記事を執筆するために使用したプログラム一式は GitHub で公開しています。
生データ(JSON)も一緒に置いてありますので、再度スクレイピングする必要がありません。
カレンダーごとの割合を出してみたり、ドメインごとではなくサービスごとに調べた結果の公開、どなたかお待ちしております…。
{
"created_at" : "2021-12-22T13:40:49Z",
"calendar_meta_data" : {
"author" : "@treastrain",
"category" : "プログラミング言語",
"lgtm" : 171,
"subscribers" : 74,
"title" : "Swift Advent Calendar 2021",
"participants" : 19,
"unique_name" : "swift",
"url" : "https://qiita.com/advent-calendar/2021/swift"
},
"articles" : [
{
"series" : "カレンダー1",
"title" : "Swift5 全予約語 (106語) の解説",
"author" : "@ezura",
"day" : 1,
"url" : "https://qiita.com/ezura/items/a4e43dfdadedb738be8a"
},
{
"series" : "カレンダー1",
"title" : "Swiftのプロトコルは何?",
"author" : "@hironytic",
"day" : 2,
"url" : "https://qiita.com/hironytic/items/6a50b7cc6dd1ea332ee2"
},