Netlify Functions を使って Zenn のトレンド API を非公式で作ってみた

2 min read読了の目安(約1800字

とりあえず API を使いたい方は

https://zenn-api.netlify.app/trendTech.json
https://zenn-api.netlify.app/trendIdea.json
https://zenn-api.netlify.app/trendBook.json

を確認してみてください。それぞれ Tech, Ideas, Books のトレンドに対応しています。(万一上手く取得できていない場合はコメント欄かリポジトリの Issue にてお知らせください。)

背景

1年以上前に Qiita で同じことをしていました。

https://qiita.com/HelloRusk/items/803f9599cde72810f1a8

この記事の反響が思いの外大きく、この API が個人開発に使われたりもしました。

https://qiita.com/cryptobox/items/844cd3686dcbcd93e7f2

そういうわけで、Zenn の方でも直接 JSON を返せるような URL を自前で立てることにしました。

Netlify Functions

Netlify 上で AWS Lambda を使えるというものです。
無料だと Requests が 125,000/月, Runtime が 100 hours/月 (2019年12月時点)まで使えるので、趣味プロダクトなら全然余裕の範囲ですね。

今なら Vercel の方が便利だとは思いますが...

どう使っているか

URL を axios で GET して、cheerio でパースしているだけです。

src/lambda/trendTech.ts
import axios from 'axios'
import cheerio from 'cheerio'

const fetchTrend = (html: string) => {
  const $ = cheerio.load(html)
  const raw = $('script[id=__NEXT_DATA__]').html() ?? ''
  if (raw === undefined) return {}
  const rawData = JSON.parse(raw).props.pageProps.dailyTechArticles

  return rawData
}

export const handler = async () => {
  const url = 'https://zenn.dev/'

  return await axios
    .get(url)
    .then(({ data }) => {
      return {
        statusCode: 200,
        headers: {
          'Access-Control-Allow-Origin': '*',
          'Content-Type': 'application/json; charset=utf-8'
        },
        body: JSON.stringify(fetchTrend(data)),
      }
    })
    .catch(err => {
      return {
        statusCode: 500,
        body: err,
      }
    })
}

詳しくはリポジトリ

https://github.com/HelloRusk/zenn-trend-api

をご確認ください。