📘

ZennのPublicationに投稿されている一覧を取得する

2023/12/03に公開

はじめに

MidraLabというコミュニティにて、技術検証やゲーム開発,アプリ開発,AIキャラクター作成など様々なことを行っています。
方針の中で、なるべく内部の技術をOpenにしてほかの方の助けになろうという思いから技術ブログをZennのPublicationを使用して執筆・公開しています。
しかし、自分たちのHP(Notion)にも書いた記事を載せたいとなったときにコミュニティに属している人の記事を取得する方法に苦戦したため、記事にしていきたいと思います。

以下はZennのPublicationの記事をNotionのDBに送って、自動で更新するライブラリを公開しています!ご興味があれば確認してみてください

https://github.com/MidraLab/zenn-to-notion-aggregator

以下はMidraLab(ミドラボ)での投稿記事一覧になりますので、ご興味があればご覧ください!

https://zenn.dev/p/midra_lab

ZennAPIの調査

まずは、ZennのAPIを調査します。しかし、そもそもZennはAPIを提供していないことがすぐにわかることかと思います

いくつか調べていくと、Zenn dev用のAPIがあることがわかります(Zennの作者の方がコメントで記載されていました)

そのため、今回はこれを使って実装を進めていきたいと思います


https://zenn.dev/link/comments/de8c8e9f253aa4

余談

ZennのAPIがない場合、ほかの方法としてWebスクレイピングという方法が思いつくと思います。
この場合はchromedriver + selenium になると思いますが、現時点ではchromedriverのv119をインストールすることができず諦めました。

過去にはこちらで実装しているので、もし興味があればzenn-to-notion-aggregator v1.0.0時点のコードを確認してみてください

調査メモ

https://zenn.dev/ayousanz/scraps/6ad79260ccd86c

Publicationに登録されている記事を取得

APIを無理やり使っているため、ある程度の力技が必要になってきます。

特定のユーザーの記事を取得する

まずは、あるユーザーの記事一覧を取得することができるAPI Endpointを叩きます。
https://zenn.dev/api/articles?username=name&order=latest

上記のEndpointをPostmanで叩いた結果は、以下のようになっています。

Publicationに登録されている記事を取得

上記の画像からpublicationnameから判断ができることがわかります。
これから特定のユーザーの記事を確認することができるため、その中からコミュニティに紐づけされている記事を取得します。
publicationがない場合もあるので、Noneの判定も入れるようにします

# 'publication'が存在し、その'name'が'midra_lab'であるか確認
                    if article.get("publication") and article["publication"].get("name") == "midra_lab":

あとは好きなパラメータを取得するようにすれば、Publicationに登録されている記事を取得に登録されている記事を取得できるようになります

Publicationにいるユーザーのものを取得

こちらはだれがPublicationに入っているかは目視からしか判断できないので、上記のAPIをユーザー分forで回すようにしています。

    def get_midra_lab_articles(self, usernames):
        base_url = "https://zenn.dev/api/articles"

        for username in usernames:
            response = requests.get(base_url, params={'username': username, 'order': 'latest'})

コード

コードの全容は、以下になります。

    def get_midra_lab_articles(self, usernames):
        base_url = "https://zenn.dev/api/articles"

        for username in usernames:
            response = requests.get(base_url, params={'username': username, 'order': 'latest'})
            if response.status_code == 200:
                data = response.json()
                for article in data["articles"]:
                    # 'publication'が存在し、その'name'が'midra_lab'であるか確認
                    if article.get("publication") and article["publication"].get("name") == "midra_lab":

                        # 日付の解析とフォーマット
                        published_at = article.get("published_at")
                        if published_at:
                            date_obj = datetime.strptime(published_at, '%Y-%m-%dT%H:%M:%S.%f%z')
                            formatted_date = date_obj.strftime('%Y-%m-%d')
                        article_info = {
                            'title': article["title"],
                            'name': article["user"]["username"],
                            'url': f"https://zenn.dev{article['path']}",
                            'created_at': formatted_date
                        }
                        self.articles.append(article_info)
MidraLab(ミドラボ)

Discussion