HAPPY HACKING Oouchi's BLOG

PSE(ポンコツエンジニア)の技術ブログ

未経験エンジニアが作成したポートフォリオで使われている技術を集計してみた

f:id:ooooouchi:20210214155941p:plain

最近、未経験からエンジニア就職を目指しているをよく見るようになりましたね。
それに伴ってポートフォリオを作ってみた趣旨の記事もよく見るようになりました。
自分が就職した当時はポートフォリオなんて言葉を知らなかったし、なんなら今の自分よりトレンド技術をうまく使いこなしているのではないかとも思ったりします。
そんな訳で、未経験エンジニアはどんな技術を使ってポートフォリオを作っているのかを調べてみたいと思います。

どうやる

  • Qiitaで「未経験 ポートフォリオ」で記事検索をする
  • タグを集計して各技術の割合を算出する
  • どうにかこうにか円グラフを描画する

やる

ソース全文

import * as nodeplotlib from "nodeplotlib";
import * as rp from "request-promise";
require("dotenv").config();
const MAX_CONTENTS = 100;
/**
 * Qiita記事
 */
interface Post {
  body: string;
  coediting: boolean;
  comments_count: number;
  created_at: string;
  group: string;
  id: string;
  likes: number;
  page_views_count: number;
  private: boolean;
  reactions_count: number;
  tags: tag[];
  length: number;
}
/**
 * タグ
 */
interface tag {
  name: string;
  versions: [];
}
async function main(): Promise<void> {
  let pageIndex: number = 1;
  const body: string = await getPosts(pageIndex);
  const posts: Post[] = JSON.parse(body);
  let allPosts: Post[] = [];
  allPosts = allPosts.concat(posts);
  let postSize = posts.length;
  while (postSize >= MAX_CONTENTS) {
    pageIndex++;
    const body = await getPosts(pageIndex);
    const nextPosts = JSON.parse(body);
    allPosts = allPosts.concat(nextPosts);
    postSize = nextPosts.length;
  }
  const tagsArr: tag[] = [].concat(
    ...allPosts
      .map(function (res) {
        return res.tags;
      })
      .map(function (tags: tag[]) {
        return tags.map(function (tag) {
          return tag.name;
        });
      })
  );
  const pie = countDuplicate(tagsArr);
  const data: nodeplotlib.Plot[] = [
    {
      type: "pie",
      values: Object.values(pie),
      labels: Object.keys(pie),
      textinfo: "label+percent",
    },
  ];
  nodeplotlib.plot(data);
}

main();

/**
 * Qiita上の記事を取得する(検索文字列:未経験、ポートフォリオ)
 * @param page ページインデックス
 * @returns
 */
function getPosts(page: number) {
  const options: rp.Options = {
    uri: `https://qiita.com/api/v2/items?page=${page}&per_page=100&query=%E6%9C%AA%E7%B5%8C%E9%A8%93%E3%80%80%E3%83%9D%E3%83%BC%E3%83%88%E3%83%95%E3%82%A9%E3%83%AA%E3%82%AA`,
    headers: {
      Authorization: `Bearer ${process.env.READ_TOKEN}`,
    },
  };
  return new Promise<string>((resolve, reject) => {
    rp(options)
      .then((res) => {
        resolve(res);
      })
      .catch((err) => {
        reject(err);
      });
  });
}
function countDuplicate(arr) {
  return arr.reduce(function (counts, key) {
    counts[key] = counts[key] ? counts[key] + 1 : 1;
    return counts;
  }, {});
}

記事検索

Qiita APIを使用します。
Qiita API v2ドキュメント - Qiita:Developer

import * as rp from "request-promise";

let pageIndex: number = 1;

const body: string = await getPosts(pageIndex);
const posts: Post[] = JSON.parse(body);
let allPosts: Post[] = [];
allPosts = allPosts.concat(posts);
let postSize = posts.length;

while (postSize >= MAX_CONTENTS) {
  pageIndex++;
  const body = await getPosts(pageIndex);
  const nextPosts = JSON.parse(body);
  allPosts = allPosts.concat(nextPosts);
  postSize = nextPosts.length;
}

function getPosts(page: number) {
  const options: rp.Options = {
    uri: `https://qiita.com/api/v2/items?page=${page}&per_page=100&query=%E6%9C%AA%E7%B5%8C%E9%A8%93%E3%80%80%E3%83%9D%E3%83%BC%E3%83%88%E3%83%95%E3%82%A9%E3%83%AA%E3%82%AA`,
    headers: {
      Authorization: `Bearer ${process.env.READ_TOKEN}`,
    },
  };
  return new Promise<string>((resolve, reject) => {
    rp(options)
      .then((res) => {
        resolve(res);
      })
      .catch((err) => {
        reject(err);
      });
  });
}

「未経験 ポートフォリオ」で記事検索した結果を100件ずつ取得しています。
100件取得できた場合はページインデックスをインクリメントして次の100件を取得します。
最終的に取得したデータはこんな感じ↓

f:id:ooooouchi:20210214155325p:plain

504件取得できたみたいです。

タグ集計

取得してきた記事の中からタグだけを抽出した配列を作成します。

const tagsArr: tag[] = [].concat(
  ...allPosts
    .map(function (res) {
      return res.tags;
    })
    .map(function (tags: tag[]) {
      return tags.map(function (tag) {
        return tag.name;
      });
    })
);

できた配列はこんな感じ↓

f:id:ooooouchi:20210214155343p:plain

技術カテゴリではないタグも混じってるけど動くのでとりあえずヨシ!

配列内で重複しているタグの出現回数をを集計します。
※参考:JavaScriptで配列の重複している項目の数をカウントする - Qiita

const pie = countDuplicate(tagsArr);

function countDuplicate(arr) {
  return arr.reduce(function (counts, key) {
    counts[key] = counts[key] ? counts[key] + 1 : 1;
    return counts;
  }, {});
}

グラフ描画

nodeplotlib - npmを使用します。

const data: nodeplotlib.Plot[] = [
  {
    type: "pie",
    values: Object.values(pie),
    labels: Object.keys(pie),
    textinfo: "label+percent",
  },
];
nodeplotlib.plot(data);
f:id:ooooouchi:20210214155414p:plain

タグが多すぎてなんとも言えないグラフが完成しました。
ここからある程度の傾向がわかるくらいにタグを間引いていきます。

完成した円グラフ

f:id:ooooouchi:20210214155431p:plain

まとめ

未経験エンジニアのポートフォリオで使用されている技術は大体こんな感じでしょうか。

サーバーサイド:Ruby、PHP、Python
フロントエンド:JavaScript、Vue.js、React
フレームワーク:Rails、Laravel、Django
ホスティング:AWS、Firebase
サーバー:Docker
コード管理:GitHub

よく使用されている技術を使用してレベルの差を見せつけるも良し、敢えて使用率の低い技術にチャレンジしてみるのもいいかもしれないですね。