Python、ChatGPT（一部）を用いて、QIita記事を分析してみた

目次
[1. はじめに](#1-はじめに)
[2. Qiita APIを使ってデータ取得](#2-qiita-apiを使ってデータ取得)
[3. データの前処理クレンジング](#3-データの前処理クレンジング)
[4. 分析可視化](#4-分析可視化)
[5.まとめ](#5-まとめ)

# 1. はじめに
こんにちは、クロスマートアドベントカレンダー21日目の記事となります🎄🎅

Qiitaといえばエンジニアが技術記事をわいわい共有する場所ですよね。
せっかくなら、そこにある大量の情報をAPIから引っ張ってきて、今どんな技術が話題なのか、ちょっと覗いてみたくなりませんか？

今回は、Qiita APIから取得してきた記事データを分析・可視化し、その中で気がついたポイントに関してざっくりまとめてみました。

# 2. Qiita APIを使ってデータ取得
Qiitaは公式にRESTfulなAPIを提供しているため、これを用いて記事データを取得しました。
データには記事タイトル、いいね数、タグ情報、作成日時などが含まれ、認証用のアクセストークンを設定すれば誰でも利用可能です。
今回は下記のコードを用いて取得した、2024年9月1日〜2024年11月30日のデータ（34713件）を使用します。
```python
import requests

API_TOKEN = "<your_access_token>"
headers = {"Authorization": f"Bearer {API_TOKEN}"}

def fetch_qiita_articles(start_date, end_date):
    url = "https://qiita.com/api/v2/items"
    articles = []
    page = 1

    while True:
        params = {
            "page": page,
            "per_page": 100,
            "query": f"created:>={start_date} created:<{end_date}"
        }
        response = requests.get(url, headers=headers, params=params)
        data = response.json()
				
				# 制限があるため無駄なリクエストを避ける
        if response.status_code != 200:
            print(ff"{target_year}-{target_month}-01", f"{target_year}-{target_month+1}-01"status code: {response.status_code}")
            break
        elif len(data) == 0:
            print(f"empty data")
            break

        articles.extend(data)
        page += 1
        time.sleep(1)  # API制限を考慮して1秒待機

    return articles

data = fetch_qiita_articles("2024-11-01", "2024-12-01")
print(data)
```

https://qiita.com/api/v2/docs

https://qiita.com/fkooo/items/250f42a0b641fb96b5ff

# 3. データの前処理・クレンジング
取得したデータをそのまま分析に使用するのではなく、今後の分析に役立つよう、以下の前処理を行いました。
1. **日付データの加工**
    記事の作成日時（`created_at`）から「時間」と「曜日」を抽出しました。
    これにより、投稿が集中する時間帯や曜日の傾向を把握しやすなります。
2. **タグデータの整形**
    記事に付けられている複数のタグをリスト形式に変換し、各記事のタグ数も抽出しました。
    タグ数が多い記事が特定の傾向を持つかを分析する際に使用します。
3. **テキストデータの文字数抽出**
    記事タイトルおよび本文全体の文字数を算出しました。
    これにより、短い記事と長文記事で人気度や注目度が異なるかを分析できます。
4. **人気度の算出**
    記事の人気度を独自に算出しました。具体的には、以下のように「いいね数」と「ストック数」に重みをつけてスコア化しています。
    ```math
    人気度 = いいね数 \times 1 + ストック数 \times 2
    ```
    ストック数により高い重みをつけた理由として、ストックが「保存したい」と思わせる価値の指標として、いいねよりも重要であると考えたためです。
    

そして、当初は2023年11月〜2024年11月の1年分のデータ（128808件）を使用する予定でした。しかし、以下の理由からデータ範囲を直近3ヶ月（2024年9月〜11月）に変更しました。
1. **データ量による問題**
    1年分のデータは膨大で、処理時間や分析の負荷が高かったため。
2. **記事の新旧差**
    古い記事と新しい記事で注目度やいいね数に偏りが出るため、直近3ヶ月に絞ることで現状を反映した分析が可能になると判断しました。

このような前処理を経て、分析に適したクリーンなデータセットを用意しました。次は、いよいよ具体的な分析手法と結果に進みます！

# 4. 分析・可視化
## 4-1. 人気度と出現頻度の可視化
まず、人気度がどの範囲に集中しているのかなどの分布を理解するために、人気度と出現頻度の可視化を行いました。

![全体を表示](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1344080/02f7c236-a295-f2d6-0cef-d81598d9da64.png)

このグラフでは全体を表示しています、ほとんどのデータが「(人気度)=0」の範囲に集中していることが確認できます。
人気度0の記事が圧倒的に多すぎて、その他の値の分布が見えてないですね。

![出現頻度（y軸）の幅を大幅に制限](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1344080/f0c53138-279b-721d-8039-b4fe97fccfee.png)

出現頻度を大幅に制限（0-10）して拡大表示してみました。

### 人気度における度数分布表（一部表示)
| 人気度 | 人気度（正規化） | 出現数 |
| --- | --- | --- |
| 0 - 217.1 | 0 - 0.05 | 34483 |
| 217.1 - 434.2 | 0.05 - 0.1 | 116 |
| 434.2 - 651.3 | 0.1 - 0.15 | 37 |
| 651.3 - 868.4 | 0.15 - 0.2 | 21 |
| 868.4 - 1085.5 | 0.2 - 0.25 | 15 |
| 1085.5 - 1302.6 | 0.25 - 0.3 | 11 |
| 1302.6 - 1519.7 | 0.3 - 0.35 | 9 |
| 1519.7 - 1736.8 | 0.35 - 0.4 | 4 |
| 1736.8 - 1953.9 | 0.4 - 0.45 | 7 |
| 1953.9 - 2171 | 0.45 - 0.5 | 2 |
| ... | ... | ... |

拡大したグラフ、度数分布表を見ても、人気度0周辺にデータが分布していることがわかります。人気度が増加するにつれて出現頻度は大幅に減少しており、人気のある記事は全体的に見て非常に少数であることが見て取れます。
これは「いいね」、「ストック」をそもそも得ることが非常に難しいということを意味します。
人気記事が少数派である一方で、マイナーな人気度を持つ記事が広範囲に分布している可能性を考慮し、人気度が低い記事データを除外しロングテールの観点から投稿傾向の把握も後ほど行おうと思います。

## 4-2. タイトル文字数と人気度の関係

タイトルは情報発信において最初に目に入る要素であり、その長さが閲覧者の興味を引きつける上で重要な役割を果たすのではないかという仮説のもと今回着目してみました。

![タイトルの文字数と出現数の関係](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1344080/c12f015d-0be8-e700-2c67-edfb8b378ebe.png)

![タイトル文字数と人気度の関係](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1344080/08d6747c-f72a-834f-18d9-dddc2515a4e0.png)

どちらのグラフも似たような分布を示している点が非常に興味深いですね。
特に、20～40文字程度の範囲でタイトルの作成数が多く、かつ人気度も高い傾向が見られます。このことから、タイトルの文字数が読者の好みに大きな影響を与える可能性が示唆されます。
また、この範囲に集中している理由として、検索エンジンやSNSでの表示制限が影響している可能性がありえるらしいです（ChatGPT調べ）。特に、40文字を超えるタイトルでは「…」で省略されてしまうケースがあるため、作成者が自然と20～40文字に収める傾向があるのかもしれません。

## 4-3. 人気度0を除いたデータの作成

前段の分析で、人気度が低い記事が全体の大部分を占めていることが確認できた。
そこで、これらの記事は「いいね」や「ストック」が付かず、注目を集めていないため、今後の分析ではノイズとなる可能性もあるため、人気度0の記事を除外し、**「注目を集めた記事のみ」を対象としたデータセット**を作成しました。

このデータセットでは、読者に何らかの反応を引き起こした記事（いいね数やストック数が1以上）のみを対象に分析を進めていこうと思います。

## 4-4. タグと人気度の関係

Qiitaでは、記事に複数のタグ（最大5つ）を付けることができます。タグは記事の内容を端的に示すだけでなく、読者の検索結果やフィード表示に影響を与える重要な要素です。これの可視化を行いました。

![tags.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1344080/8d9f5bd4-7c4e-73d9-c04e-16866b28e0f0.png)
グラフ通りですが、タグ数が増えるにつれて平均人気度が上昇しており、特に4～5個のタグが付いている記事は高い人気度を示しています。
タグが多いことで、記事がより多くの読者の検索や興味に引っかかりやすくなる可能性があります。そのため、積極的にタグは5つ付けて行きましょう！！

しかし、タグ数だけではなく、付けられた「タグの内容そのもの（=記事の内容）」が人気度に大きく関わる可能性があります。具体的なタグの種類と人気度の関係を掘り下げ、どのタグが注目を集めやすいのかを分析してみます。

### 人気タグの傾向

タグの種類は全16,412種類でした。その中の上記25件のみ表示してみます。

![tag_popularity.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1344080/3c4b4818-e503-9c78-8f4a-cda1605a31da.png)

<details><summary>タグ使用率1-50位</summary>

| 1 | シニアエンジニア | 0.401658 |
| --- | --- | --- |
| 2 | テックリード | 0.401658 |
| 3 | コード管理 | 0.320129 |
| 4 | ブランチ戦略 | 0.296868 |
| 5 | 内製化 | 0.285122 |
| 6 | 請負開発 | 0.285122 |
| 7 | CAIS | 0.251152 |
| 8 | 脳科学 | 0.240673 |
| 9 | pep | 0.234915 |
| 10 | Tim_Peters | 0.234915 |
| 11 | フィードバック | 0.194841 |
| 12 | レトロゲーム | 0.180562 |
| 13 | デバッグツール | 0.160295 |
| 14 | Andoird | 0.154422 |
| 15 | AIエンジニア | 0.154307 |
| 16 | リッチテキスト | 0.149701 |
| 17 | git-flow | 0.148434 |
| 18 | トランクベース開発 | 0.148434 |
| 19 | Webエンジニア | 0.145785 |
| 20 | 多重下請け構造 | 0.145785 |
| 21 | 人月商売 | 0.145785 |
| 22 | 競馬予想 | 0.143079 |
| 23 | 仕事のやり方 | 0.136419 |
| 24 | devsumi | 0.135882 |
| 25 | SpaceTravel | 0.135882 |
| 26 | homelab | 0.131737 |
| 27 | 隠し機能 | 0.123215 |
| 28 | Idle_Detection_API | 0.1193 |
| 29 | PSF | 0.117457 |
| 30 | スタッフエンジニア | 0.100818 |
| 31 | vertex | 0.095117 |
| 32 | 早起き | 0.093966 |
| 33 | 帯域 | 0.090972 |
| 34 | APIデータ統合 | 0.090511 |
| 35 | diagrams | 0.086826 |
| 36 | ロバストPython | 0.085905 |
| 37 | 型アノテーション | 0.085905 |
| 38 | OJT | 0.083602 |
| 39 | vscode-reveal | 0.083372 |
| 40 | workshop | 0.082335 |
| 41 | ディレクション | 0.081529 |
| 42 | theme | 0.080838 |
| 43 | やる気 | 0.080454 |
| 44 | コンサルティング | 0.080147 |
| 45 | クリティカルシンキング | 0.079687 |
| 46 | ラテラルシンキング | 0.079687 |
| 47 | テキストエディタ | 0.078996 |
| 48 | チーム | 0.078151 |
| 49 | 心理的安全性 | 0.077384 |
| 50 | honeypot | 0.076462 |
</details>

<details><summary>タグ使用率51-100位</summary>

| 51 | T-Pot | 0.076462 |
| --- | --- | --- |
| 52 | GooglePlay | 0.074574 |
| 53 | 大学 | 0.074159 |
| 54 | エンジニア採用 | 0.071971 |
| 55 | おやつ | 0.070705 |
| 56 | 間食 | 0.070705 |
| 57 | 息抜き | 0.070705 |
| 58 | 休憩 | 0.070705 |
| 59 | Unix哲学 | 0.069668 |
| 60 | 継続 | 0.069611 |
| 61 | 線形代数学 | 0.06702 |
| 62 | PyMuPDF | 0.06322 |
| 63 | ベストプラクティス | 0.062989 |
| 64 | DX | 0.062137 |
| 65 | EPUB | 0.061089 |
| 66 | 要件定義 | 0.059399 |
| 67 | ソースコード | 0.058959 |
| 68 | SpeechToText | 0.058038 |
| 69 | 習慣化 | 0.055827 |
| 70 | 性能 | 0.054353 |
| 71 | 性能評価 | 0.054007 |
| 72 | setting | 0.053739 |
| 73 | 徳丸基礎試験 | 0.053201 |
| 74 | マルチエージェントシステム | 0.052636 |
| 75 | DeadLock | 0.049747 |
| 76 | 朝活 | 0.049401 |
| 77 | アドレスバー | 0.048825 |
| 78 | Webデザイン | 0.04825 |
| 79 | t3-stack | 0.047111 |
| 80 | await | 0.046714 |
| 81 | kag | 0.046522 |
| 82 | 複合AI | 0.046104 |
| 83 | ロジアナ | 0.045371 |
| 84 | ナレベベ | 0.045256 |
| 85 | 本 | 0.043903 |
| 86 | bandit | 0.043759 |
| 87 | Safety | 0.043759 |
| 88 | 研修 | 0.042999 |
| 89 | mailpit | 0.042607 |
| 90 | reveal.js | 0.042492 |
| 91 | TOEIC | 0.042377 |
| 92 | ウェブ制作 | 0.041686 |
| 93 | おしゃれさんと繋がりたい | 0.041686 |
| 94 | ポモドーロ | 0.040611 |
| 95 | 就職 | 0.040189 |
| 96 | システム生成AI | 0.038462 |
| 97 | WAI-ARIA | 0.038462 |
| 98 | 言語化 | 0.037886 |
| 99 | 質問力 | 0.036849 |
| 100 | 協調フィルタリング | 0.036849 |
</details>

1. **特定のタグが人気に関して**
    1. **トピックの関連性と実用性**
        - 「シニアエンジニア」や「テックリード」は、エンジニアリング組織での役割やリーダーシップに関連しており、実務に直結するテーマであるため、読者の関心を集めていると考えられます。
        - 「コード管理」や「ブランチ戦略」は、開発フローを効率化するための手法であり、多くのエンジニアにとって実用性が高い内容です。
    2. **需要の高さ**
        「内製化」は、組織がソフトウェアを内製化するトレンドが背景にあると考えられます。このテーマは経営戦略にも関連し、エンジニア以外の読者層にも関心を持たれる可能性があります。
        
    3. **トレンド性**
        最新の技術や業界動向に関連するタグが人気を集めやすい。タグがその時期のホットな話題を反映している場合、より多くの注目を集める傾向があります。
        
2. **おすすめの使いやすいタグ**
    1. **汎用性の高いタグ**
        「コード管理」「ブランチ戦略」などは、広範なエンジニア層に関係があり、どのレベルの読者に対しても有用性が高い。
    2. **役割やキャリアに関連するタグ**
        「シニアエンジニア」「テックリード」のようなタグは、特定のポジションに焦点を当てた記事を書く際に有効。特に中級～上級エンジニアをターゲットとする場合に効果的です。
    3. **ニッチだけど注目されやすいタグ**
        「内製化」のような経営戦略や特定の技術課題にフォーカスしたタグは、少数派の読者に強く刺さり、シェアされやすい傾向があります。
        
## 4-5. 投稿タイミングと人気度の関係

記事がどの時間帯に投稿されると読者の目に留まりやすいかを把握し、読者がアクティブな時間帯を狙うことで、より効果的な投稿スケジュールを立てるということで投稿タイミングに着目してみました。

![曜日時間帯別の投稿数](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1344080/d5d933af-c0a2-27f8-0565-9a639fe906e2.png)

このヒートマップは、各曜日および時間帯における投稿数を示しています。

1. **投稿数のピーク**
    - 平日昼間（12:00～14:00）に投稿が集中している。
    - 特に、**日曜日の日中と月曜日の12時過ぎ**での投稿数が非常に多くなっている
        - **日曜日の日中**では、週末の読者層を意識した投稿の可能性
        - **月曜日の12時過ぎ**では、週末に執筆したもの投稿の可能性
2. **夕方帯以降の投稿**
    15時～24時での投稿が非常に少なく、0時～6時くらいでの投稿も数が少ない。エンジニアに問わず日常的にアクティブではない時間帯のため少なくなってくると考えられる。
    
3. **曜日ごとの違い**
    月曜日での投稿が多く、土曜日に向かって少しずつ減っていき日曜日に再度活性化している傾向が見られる。

![曜日時間帯別の平均人気度](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1344080/a298cbc6-09d6-dcf6-257e-51db02feb4cd.png)

このヒートマップは、各曜日および時間帯における記事の平均人気度を示しています。

1. **人気度の高い時間帯**
    **金曜日の18時～19時**が特に高い平均人気度を示しており、週末に投稿された記事をチェックしている可能性がある。
    
2. **低い人気度の時間帯**
    深夜帯（0:00～6:00）は全体的に人気度が低い。
    投稿のタイミングでもあった様に、この時間帯はアクティブではない時間帯のため少なくなってくると考えられる。
    
3. **曜日の影響**
    - 金曜日、土曜日の夜や日曜日の明け方は、他の曜日と比較して人気度が高い傾向が見られる。
        - 平日の朝（8:00～10:00）や昼間（12:00～14:00）は投稿数が多いにも関わらず、平均人気度は平凡。

平日昼間や夕方、週末の夜など、読者がアクティブな時間帯を狙うことで、記事が埋もれるリスクを減らし、注目度を高めることが可能になります。特に競争が少ない時間帯を狙った投稿をしていきましょう！！

# 5. まとめ

今回の分析を通じて、記事の人気度に影響を与えるさまざまな要因が判明しました。タグの選択、投稿タイミング、そして読者の行動パターンが、記事の人気度を大きく左右することがデータから明らかになったため下記のポイントを押さえて戦略的な投稿をしていきましょう！！
1. **人気のタグ、トレンド性のあるタグを適切に5件しっかり選ぶこと**
2. **投稿タイミングの最適化**
    平日昼間や夕方、週末の夜などの読者がアクティブな時間帯