初心者向けの記事って多すぎん？？（JavaScript初心者向けQiitaAPIでLGTM数TOP10を出してみる）

#はじめましての自己紹介
はじめまして！超ウルトラスーパー初心者のぜらちんです。
JavaScript？新しい紅茶？というくらいにチンプンカンプンな30オーバー限界ヲタク女が
JavaScriptで何かを作り始めてみる、という記事をこれからいくつか投稿していこうと思います。

#何を作ろうか
まずはQiitaのAPIを使用して、（この言い回しがあっているかも分からない……。）
初心者が読むべき記事を抽出してみることにします。
そう。自分のために作るのです！
Qiitaは記事が多すぎる……。初心者向けとされている無数の記事の中から、良さそうな記事だけ読みたいんじゃー！
何をもって良い記事とするか。そう。他者からの評価が多い記事だけを読むのです。
自分はJavaScriptを使用して挑戦するので、抽出する記事は「JavaScriptを学ぶ初心者向けの記事」にします。

#作成するものの概要
・QiitaAPIを使って、記事タイトル、本文、タグに「JavaScript」と「初心者」が含まれる記事を取得する。
・2021年9月までの記事を取得することにする。（実行の度に結果がブレるため日付を区切る。）
・結果を手動集計しLGTM数で並び変える。（アナログ・・・！）

#環境
Node　v16.10.0
axios　0.22.0

#完成コード
XXXXXは発行されたアクセストークン

```js
const axios = require('axios');

//タグに「初心者」「JavaScript」どちらも設定されている記事
async function main() {

    for (page = 1;page<=100;page++){

    let parm = "https://qiita.com/api/v2/items?page=" + page + "&per_page=100&query=JavaScript+" + encodeURIComponent("初心者") + "+created%3A" + encodeURIComponent("<2021-10");
    let response = await axios.get(parm, {
        headers: {
        "Authorization": "Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
        }
    });
    
    //取得したデータ件数分タイトル、URL、LGTM数取得
        for (let i = 0; i < response.data.length; i++) {
        var title_name = response["data"][i]["title"];
        var sample = response["data"][i]["url"];
        var cntlike = response["data"][i]["likes_count"];

        console.log(title_name+"¥"+sample+"¥"+cntlike);
        }
    }
}

main();
```

コードはこのように記載しましたが、数が多すぎるのか途中でエラーになったので、10ずつ区切って実行し結果をExcelに貼り付けて手動で降順にしました。（圧倒的アナログ……！）
結果を「¥」で結び、Excel上でデータ分割しました。
（タイトルにカンマやスペースを入れている記事があったため区切り文字として設定できませんでした。）

#JavaScript初心者向けLGTM数TOP10(～2021年9月作成記事)
得られた結果からLGTM数のTOP10を発表します！！
それぞれリンクも設定していますので飛んでみてください。
記事タイトル、本文、タグのいずれかに、「JavaScript」と「初心者」の2語が含まれています。
※LGTM数は2021/10/13時点のものとなります。

| No | 記事タイトル | LGTM数 |
|:------------:|:------------|:------------:|
| 1 | [AtCoder に登録したら次にやること ～ これだけ解けば十分闘える！過去問精選 10 問 ～](https://qiita.com/drken/items/fd4e5e3630d0f5859067)| 6248        | 
| 2 | [イマドキのJavaScriptの書き方2018](https://qiita.com/shibukawa/items/19ab5c381bbb2e09d0d9)| 5554        | 
| 3 | [良いコードの書き方](https://qiita.com/alt_yamamoto/items/25eda376e6b947208996)| 4363        | 
| 4 | [すべての新米フロントエンドエンジニアに読んでほしい50の資料](https://qiita.com/suzu-4/items/ea5d802cb0ad16682ae2)| 3876        | 
| 5 | [2020年のフロントエンドマスターになりたければこの9プロジェクトを作れ](https://qiita.com/rana_kualu/items/915345b8f3f870cfe2aa)| 3647        |
| 6 | [プログラミング勉強を加速させる7つの習慣](https://qiita.com/YudaiTsukamoto/items/42a8df22ca4c6b327dfd)| 3379        |
| 7 | [トップデベロッパーになるために作成したいアプリ8選](https://qiita.com/baby-degu/items/f905c8ee972cf46ce11b)| 3248        |
| 8 | [初心者歓迎！手と目で覚える正規表現入門・その１「さまざまな形式の電話番号を検索しよう」](https://qiita.com/jnchito/items/893c887fbf19e17d3ff9)| 3163        |
| 9 | [初心者プログラマが犯しがちな過ち25選](https://qiita.com/rana_kualu/items/379eefb3a40c6b44cb92)| 2492        |
| 10 | [【保存版・初心者向け】独学でAIエンジニアになりたい人向けのオススメの勉強方法](https://qiita.com/tani_AI_Academy/items/4da02cb056646ba43b9d)| 2444        |
 
#考察
TOP10に記載させていただいた記事をすべて見てみました。
一字一句逃さず、とはいきませんが、全体をざっと見てLGTMを集める記事の共通点を考察してみました。

**● タイトルに数値が入っている**
「過去問精選<font color="red">**10**</font>門」「読んでほしい<font color="red">**50**</font>の資料」「<font color="red">**7**</font>つの習慣」「アプリ<font color="red">**8**</font>選」
上記のようにタイトルに目を引く数字が入っています。
具体的な数字が書かれていると
「これだけやればいいんだ！」
「この数の分だけ覚えればいいんだ！」と思い、
初心者がとっつきやすくなるのかもしれません。

**● 長い**
一部の記事を除いて、とにかく記事の内容が長い！一体何回スクロールしたことか！
あまり長いと初心者の方は敬遠するんじゃないか？と思いましたが、
情報量が多ければ多いほどQiitaを利用する初心者には好まれるのかもしれません。

**● 図が豊富に組み込まれている**
参考画像などの図が少なくとも3つ以上組み込まれている記事が多かったです。
中には動画の埋め込みもありました。
文字ばっかりになるよりは、図やイラスト、動画を入れることでより分かりやすくなっているようです。

**● 折りたたみを使用していない**
中には、これだけ長い記事なら「折りたたみ」を使用すればいいのに、と思う記事もありました。
が、気づきました。折りたたまれた記事は読まれない！
スクロールの途中でマウスに置く指の位置を変えて折りたたみを開こうと思わないのです。
10個の記事を見ている自分がそうでした。
たくさんある記事を渡り歩いていく途中で折りたたみは見逃されてしまうのです。
どんなに長くなっても折りたたみは使わないほうがいいようです。
（時と場合によると思いますが……。）

**● おすすめの資料、テキスト、参考書が紹介されている**
表紙の画像を添えておすすめの本を紹介している記事がいくつかありました。
Qiitaやnoteの記事、YouTubeの動画などインターネット上にはたくさんの初心者向けコンテンツが溢れていますが、
プロが執筆し、校正、校閲を通った書籍を初心者が求めるのは今も昔も変わらないようです。

**● 形容詞が多く使われている**
最後にTOP10の記事本文をテキストマイニングツールにかけてみました。
使用したツールはこちら→「[userlocal テキストマイニングツール](https://textmining1.userlocal.jp/home/result/fd6ecff33f28fae656eec103e472c6b2)」
結果は折りたたみの中に画像として貼り付けています。
（TOP10に倣わず折りたたみました。）

各記事で取り上げている内容が異なるため、出現頻度の多い単語には着目せず画像の黄緑色文字（形容詞）に注目しました。
「良い」「素晴らしい」「難しい」「早い」「新しい」「多い」「優しい」「短い」「長い」
などなど、様々な形容詞が各記事で使われていることがわかりました。
ほとんどの記事で、動詞よりも多用されていると言ってもいいほどです。
誰もが想像しやすく、分かりやすい内容となるように形容詞を使うことで、
戸惑う初心者の心に寄り添う内容となり、結果多くのLGTMが得られたのかもしれません。

<details><summary>TOP10記事本文のテキストマイニング</summary>
▼AtCoder に登録したら次にやること ～ これだけ解けば十分闘える！過去問精選 10 問 ～
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122198/5f76efcf-4408-2dbf-16e9-b337a872c4a1.png)
▼イマドキのJavaScriptの書き方2018
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122198/3f9c609a-863e-9e06-ee39-6ddb6acdc7d2.png)
▼良いコードの書き方
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122198/0b1f2010-793b-13bc-f465-c5a90217e4e0.png)
▼すべての新米フロントエンドエンジニアに読んでほしい50の資料
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122198/d89d957b-0326-9bc7-4669-e5fbeaa9accd.png)
▼2020年のフロントエンドマスターになりたければこの9プロジェクトを作れ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122198/63f6a46d-3b1b-8fcd-27ea-6dafc2cc9bff.png)
▼プログラミング勉強を加速させる7つの習慣
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122198/d27c86ff-9960-6060-6117-ce98874dbd8b.png)
▼トップデベロッパーになるために作成したいアプリ8選
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122198/a8342c32-6bcc-d3a1-944f-95d9ed8840e0.png)
▼初心者歓迎！手と目で覚える正規表現入門・その１「さまざまな形式の電話番号を検索しよう」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122198/b54eb898-e38a-8758-731a-a4b721ede410.png)
▼初心者プログラマが犯しがちな過ち25選
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122198/12935f67-23d0-5f26-ff90-818ac1a00af6.png)
▼【保存版・初心者向け】独学でAIエンジニアになりたい人向けのオススメの勉強方法
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122198/f5ed0647-b2dc-1fc8-526e-9fc875a8d8f0.png)</details>

初心者向けの記事を書き、多くのLGTMをもらうためにはこれらのことを念頭に置いて執筆してみるとよいでしょう。
と言いましたが、書いてみた結果うまくいかなくても投稿主は責任を取れませんのでご了承ください……。

#感想
最後は手動でゴリ押ししたところもあったので、そこが悔やまれました。
情報を取れるだけとってExcelに貼り付けてソートして……と不毛な作業をしていたように思います。
終わり良ければ総て良し！なのかもしれませんが、なんだかスッキリしません。
ですが、今まで使ってこなかった脳みそを使えたので良い勉強になりました！
私のこの記事も抽出期間を広げれば対象に入ってきますが、上位10記事くらいLGTMを付けられる日はおそらく来ないので、今後記事を更新することはなさそうです。
参考にした記事は一番下にまとめていますのでご参照ください。


#紆余曲折
Visual Studio Codeを使用してJavaScriptでやりました。
初心者の勉強用投稿なのでやってみてダメだったコードも書いていきます。
ここからはとにかく長くなってしまったので、お時間のある方のみどうぞ……。

##初心者向けの記事数を得る
まずは、タグに「初心者」と設定されている記事数を取得してみます。

```js
const axios = require('axios');

//タグが「初心者」である記事
async function main() {
  let response = await axios.get('https://qiita.com/api/v2/tags/' + encodeURIComponent('初心者'));
  console.log(response.data);
}

main();
```
こんな結果が得られました。

```json
{
  followers_count: 5331,
  icon_url: 'https://s3-ap-northeast-1.amazonaws.com/qiita-tag-image/2383c6450ddfcedeb18a168a1a13023ee25687c5/medium.jpg?1611635876',
  id: '初心者',
  items_count: 19206
}

```

記事数が19206件もある！
こんなに読み切れない！！
初心者が入口で躓くのは参考資料の多さが原因の一つだと私は思っています。

フォロー数は5331。
そりゃ、継続していけば初心者ではなくなるからこれは納得。

閑話休題。

私が知りたいのはJavaScriptに関する初心者向け記事なので数を絞ってみます。

##JavaScriptの初心者向け記事を取得する
初心者タグが設定されている、かつ、JavaScriptタグも設定されている記事に絞ればいいのだから、
タグのAND検索でいけそうです。
検索窓に「JavaScript　初心者」と入れるイメージです。

```js
const axios = require('axios');

//タグに「初心者」「JavaScript」どちらも設定されている記事
async function main() {
    let response = await axios.get('https://qiita.com/api/v2/tags/' + encodeURIComponent('初心者') + '&tags/' + + encodeURIComponent('javascript'));
  console.log(response.data);
}

main();

```

結果は……言うまでもなく失敗です。
そもそも「JavaScript」は日本語じゃないんだからエンコードする必要がないです。
投稿主は超のつく初心者なので、どうか暖かい目で見てください……。（褒めて伸びるタイプです。）

ここでチームに相談！15分調べてわからなかったら聞くに限ります！
調べても分からなかったんだし！
教えてもらった内容で再挑戦します。

```js
const axios = require('axios');

//タグに「初心者」「JavaScript」どちらも設定されている記事
async function main() {
    let response = await axios.get('https://qiita.com/api/v2/items?query=tag%3AJavaScript+tag%3A' + encodeURIComponent('初心者') );
  console.log(response.data);
}

main();

```

エラーは出なくなりました。
成功ですが、なんだか出力された内容が少ないように見えます。
気になるので取得できた記事数を確認してみます。

##取得した記事件数を確認

「items_count」を追加して取得した記事件数が確認できるか試してみます。

```js
const axios = require('axios');

//タグに「初心者」「JavaScript」どちらも設定されている記事
async function main() {
    let response = await axios.get('https://qiita.com/api/v2/items?query=tag%3AJavaScript+tag%3A' + encodeURIComponent('初心者') );
  console.log(response.data.items_count);
}

main();

```

結果は「undefined」という表示。
「undefined」は「未定義」という意味らしい……。
んんーー？？どういうことだー？？
おそらく「値がない」ということなんだろうと思います。

この方法ではダメなので他の方法を探します。
色んな記事を見てみると「length」で数が取れそうです！
早速書き書き……。

```js
const axios = require('axios');

//タグに「初心者」「JavaScript」どちらも設定されている記事
async function main() {
    let response = await axios.get('https://qiita.com/api/v2/items?query=tag%3AJavaScript+tag%3A' + encodeURIComponent('初心者') );
    //取得した記事数
    console.log(response.data.length);
}

main();
```

結果は「20」と出ました！
……いや！そんなわけない！初心者向けのjavascriptの記事が20件なわけがない！！
またしても問題にぶちあたりました……。

##記事をさらに取得する
[Qiita API v2（ページネーション）](https://qiita.com/api/v2/docs#%E3%83%9A%E3%83%BC%E3%82%B8%E3%83%8D%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%EF%BC%89)を調べてみると以下の記載がありました。
>per_pageの初期値は20、per_pageの最大値は100に設定されています。

「per_page」をいじる必要がありそうです。
「per_page」の最大値を設定してリトライしてみます。

```js
const axios = require('axios');

//タグに「初心者」「JavaScript」どちらも設定されている記事
async function main() {
    let response = await axios.get('https://qiita.com/api/v2/items?per_page=100&query=tag%3AJavaScript+tag%3A' + encodeURIComponent('初心者') );
    //取得した記事数
    console.log(response.data.length);
}

main();
```

結果は『100』と表示されました！成功です！
最大値に100を設定しているから当たり前ですね……。
そして条件にあてはまる記事が100件なわけないです……。
次はすべての記事を取得する必要があります。

##すべての記事を取得する
2021/10/11現在、Qiitaの検索窓で「JavaScript　初心者」と入力すると、すべての検索結果は「7276」件となりました。
「page」の最大値も設定して取得できる記事の数が増えるか試してみます。

```js
const axios = require('axios');

//タグに「初心者」「JavaScript」どちらも設定されている記事
async function main() {
    let response = await axios.get('https://qiita.com/api/v2/items?per_page=100&page=100&query=tag%3AJavaScript+tag%3A' + encodeURIComponent('初心者') );
    //取得した記事数
    console.log(response.data.length);
}

main();
```

結果は『0』
ええ！なんで！？これは再度調査が必要そうです……。
チームからの助言をまるっと引用
>Qiita APIでは検索結果が複数返ってくるようなAPIに対して、それを一度に返すことはせずに、ページという単位で分割して返すようになっています。
この時に使うオプションがper_pageとpageで、per_pageで1ページ辺りに幾つの検索結果を含むかを指定でき、pageでその中の何ページ目を取得するかを指定します。
>per_page=100&page=100
という記載をした場合、検索結果を100個ずつに区切って、その中の100番目のページを取得する（＝9901番目～10000番目の結果を取得する）という意味になります。
なので、検索結果が9901件以上無いと結果は0になります。
>per_page=100
という記載の場合は、検索結果は上と同様に100個ずつに区切られ、その中の1番目のページを取得する（=1番目～100番目の結果を取得する）という意味になります。
※これはpageというパラメータを指定しなかった場合の初期値が1だからです。ちなみに、per_pageの初期値は20です。
なので、この場合は検索結果が100件以上あれば取得できるデータの個数は100になります。
APIではレスポンスヘッダーというところに要素の合計数が出力されます。
レスポンスのボディ（データ本体）ではなくヘッダーの情報を取りたいときはaxiosで取得した結果に対してheadersという要素にアクセスすると取り出せます。
console.log(response.headers);
としていただけるとヘッダーの中身が見れますのでtotal-countという項目を探してみてください。

いただいた助言を元に以下を実行してみます。

```js
const axios = require('axios');

//タグに「初心者」「JavaScript」どちらも設定されている記事
async function main() {
    let response = await axios.get('https://qiita.com/api/v2/items?query=tag%3AJavaScript+tag%3A' + encodeURIComponent('初心者') );
    //取得した記事数
    console.log(response.headers);
}

main();
```

得られた結果の中に`'total-count': '1576',`とありました。
ふむ……。1576件……。思ったより少ないな……。
Qiitaの検索窓で検索した結果は7276件だったので、検索対象をタグではなく、タイトルと本文を含めたすべてにしてみます。

```js
const axios = require('axios');

//タグに「初心者」「JavaScript」どちらも設定されている記事
async function main() {
    let response = await axios.get('https://qiita.com/api/v2/items?query=JavaScript+' + encodeURIComponent('初心者') );
    //取得した記事数
    console.log(response.headers);
}

main();
```

結果は`'total-count': '7280',`（2021/10/13時点）
うん！いい感じです！
ここから全記事のLGTM数をとり、降順にして上位10個の記事だけを取得します。
記事全文だと長すぎるのでタイトルとURLだけ取得し、末尾にLGTM数も取得するようにしてみます。

```js
for (page = 1;page<=100;page++){

    let parm = "https://qiita.com/api/v2/items?page=" + page + "&per_page=100&query=JavaScript+" + encodeURIComponent("初心者") + "+created%3A" + encodeURIComponent("<2021-10");
    let response = await axios.get(parm, {
        headers: {
        "Authorization": "Bearer a57b66c2c1c2a8a9bb53be4879f6ecf5ab28c5a4"
        }
    });
```

実行中にまたもやエラー発生！
per_page=100&page=100　だと途中でエラーになったので、
per_page=100&page=10　で数回実行し、結果をExcelに貼り付けていくことにします。
本当はコード内だけで降順にしてTOP10の記事だけ抽出、としたかったのですが力量不足でした……。
とりあえずは形にすることができたので自分で自分を褒めてあげたいです！（懐）

が、また途中で謎のエラーに引っ掛かりました。
頼れるチームメンバーに相談し、アクセストークンなるものを設定してみました。
※以下のコードは一部抜粋しています。XXXXX～は発行したアクセストークンを設定。
※アクセストークンの設定方法は参考記事を参照。

```js
 let parm = "https://qiita.com/api/v2/items?page=" + page + "&per_page=100&query=JavaScript+" + encodeURIComponent("初心者") + "+created%3A" + encodeURIComponent("<2021-10");
    let response = await axios.get(parm, {
        headers: {
        "Authorization": "Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
        }
    });
```

これで何とかすべての記事を取得することができました。
最終的に完成したコードは「完成コード」のとおりです。

#参考記事
以下の記事を参考にしました。
▼私にはMarkdownチートシートよりもわかりやすかったです。
[Qiita Markdown 書き方 まとめ](https://qiita.com/shizuma/items/8616bbe3ebe8ab0b6ca1)
▼コメント数を取得するあたりなどまるっと~~パクった~~参考にしました。
[結局Qiita記事ってどれぐらい書けばいいのさ](https://qiita.com/canonno/items/57f917147b3d6ae106e9)
▼作成日を指定して取得する箇所を参考にしました。
[QiitaAPIで2020年投稿のストック数が多い記事のタグ情報を調べてみた](https://qiita.com/PmanRabbit/items/b4ffb0d46cfaeb73e1f6)
▼記事をたくさん取得する方法を参考にしました。
[「テレワーク」と「新型コロナ」には相関性があるのか確かめてみた。](https://qiita.com/twtjudy1128/items/836efaf748b8b76a6b82)
▼アクセストークンの設定について参考にしました。
[よそ様の情報を簡単に参照できるWEBAPIが本当に簡単なのか体験してみた。](https://qiita.com/grayhamchan/items/8bbccba34caaa71058b9)
▼なんやかんや参考にしました。（説明めんどくさくなるな。）
[Qiita API v2（ページネーション）](https://qiita.com/api/v2/docs#%E3%83%9A%E3%83%BC%E3%82%B8%E3%83%8D%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%EF%BC%89)