😗

dev.toの記事をいいね数で並び替え一覧表示したいんじゃ

2022/11/20に公開

はじめに

みなさん技術記事はどこで読み漁っていますか?日本語のサイトだと今ならQiitaZennといったところでしょうか?では英語のサイトなら?私は多くを知りませんが、DEVをよく巡回しています。

今日も暇つぶしにDEVを適当に見物していたら、ふと「最もいいね数が多い記事が読んでみたいんじゃ」という気持ちになりました。しかし、いいね数でソートする機能は提供されていないようでした(もしあったらごめんなさい🙇)。ないなら自分で作ろうということでこの記事に至ります。

API

DEVではAPIが提供されています。ちなみに、DEVはOSSのForemによるサイトなので、「APIドキュメントがDEVじゃなくてforemのものなんだが?」と思ってもそれはDEVのドキュメントとして読んで問題ないです。現在APIにはVersion-0Version-1が存在するようですが、今回はVersion-1を使用します。ただし、Version-1はAPIキーが必要ですので、まずはその準備から行います。

APIキーの発行はログインした状態で(https://dev.to/settings/extensions)にアクセスしてください。現在だと一番下にAPIキー発行のフォームがあります。

1ユーザー1APIキーではなく、いくつか発行できるようですのでDescriptionに任意の値を入力してGenerate API KeyボタンをクリックすればActive API Keysに発行されたAPIキーが表示されます。漏洩には各自注意してください。下準備はこれだけです。

今回はいいね数で記事をソートして取得したいわけですが、記事一覧を取得するAPIがあります。こちらにソート機能あればやりたいことはすぐに終わってしまうわけですが、ないので記事をすべて取得してローカルで並び替える戦法でいきます。

そのために記事のレスポンスがどんな感じか見ていきましょう。以下はドキュメントのレスポンス例から拝借。

[
  {
    "type_of": "article",
    "id": 4453,
    "title": "East of Eden168",
    "description": "Put a bird on it aesthetic narwhal xoxo pug. Disrupt slow-carb williamsburg crucifix...",
    "readable_publish_date": "Aug 23",
    "slug": "east-of-eden168-21ml",
    "path": "/username372/east-of-eden168-21ml",
    "url": "http://localhost:3000/username372/east-of-eden168-21ml",
    "comments_count": 0,
    "public_reactions_count": 0,
    "collection_id": null,
    "published_timestamp": "2022-08-23T12:08:21Z",
    "positive_reactions_count": 0,
    "cover_image": "http://localhost:3000/assets/24-377bc0861a9a539e8d1875ea9d4eea9e0226d93e1b6e9317e0c73c754699cc14.png",
    "social_image": "http://localhost:3000/assets/24-377bc0861a9a539e8d1875ea9d4eea9e0226d93e1b6e9317e0c73c754699cc14.png",
    "canonical_url": "http://localhost:3000/username372/east-of-eden168-21ml",
    "created_at": "2022-08-23T12:08:21Z",
    "edited_at": null,
    "crossposted_at": null,
    "published_at": "2022-08-23T12:08:21Z",
    "last_comment_at": "2022-08-23T12:08:21Z",
    "reading_time_minutes": 1,
    "tag_list": [
      "discuss"
    ],
    "tags": "discuss",
    "user": {
      "name": "Angelena \"Charis\" \\:/ Lang",
      "username": "username372",
      "twitter_username": "twitter372",
      "github_username": "github372",
      "user_id": 10747,
      "website_url": null,
      "profile_image": "/uploads/user/profile_image/10747/79dbb51d-a63a-4475-af29-a84fe417b9d8.jpeg",
      "profile_image_90": "/uploads/user/profile_image/10747/79dbb51d-a63a-4475-af29-a84fe417b9d8.jpeg"
    },
    "organization": {
      "name": "Vandervort-Sanford",
      "username": "org56",
      "slug": "org56",
      "profile_image": "/uploads/organization/profile_image/1275/45556538-13d9-44af-af7e-c9fcdbe2617c.png",
      "profile_image_90": "/uploads/organization/profile_image/1275/45556538-13d9-44af-af7e-c9fcdbe2617c.png"
    },
    "flare_tag": {
      "name": "discuss",
      "bg_color_hex": "#000000",
      "text_color_hex": "#ffffff"
    }
  }
]

ざっと記事に関するメタ情報が取得できている感じです。今回やりたいことはいいね数が欲しいわけですが、positive_reactions_countキーが存在しますね。対象の全記事を取得してこちらの値で並び替えれば、やりたいことが実現できそうですね。

スクリプト

ということでスクリプトどーん。特に技術的に面白いところはないので、興味のある方だけなめてください。以下の流れで単純な処理を行っているだけです。

  1. 並び変えたい記事をtag指定でフェッチしていったんローカル保存
  2. ローカルから再度読み直して記事のリストを生成
  3. いいね数でソート
  4. 表に整形して出力

対象の全記事数がわからなくてページ数が特定できなかったので、空配列が帰ってきたら全部取得できたということにしているのは言い訳ポイントです。

main.py
import json
import time
from datetime import datetime
from pathlib import Path

import requests

# directory
ROOT_DIR = Path(__file__).parent
TEMP_DIR = ROOT_DIR / ".temp"

# for request
API_KEY = "secret"
HEADERS = {
    "accept":"application/vnd.forem.api-v1+json",
    "api-key":API_KEY
}

def sanitize_filename(filename):
    return "".join([c for c in filename if c.isalpha() or c.isdigit() or c==' ']).rstrip()


def fetch_articles(directory, tag):
    for page in range(1,100):
        url = f"https://dev.to/api/articles?page={page}&per_page=1000&tag={tag}"

        req = requests.get(url, headers=HEADERS)
        print(req.status_code)
        if req.json() == []:
            break

        filename = sanitize_filename(url) + ".json"
        filepath = directory / filename
        filepath.write_bytes(req.content)

        time.sleep(5)


def load_articles(directory):
    articles = []

    articles_filepaths = directory.glob("*.json")
    for article_filepath in articles_filepaths:
        with open(article_filepath.as_posix()) as f:
            articles.extend(json.load(f))

    return articles


def create_table_row(rank_number, article):
    ranking = f"{rank_number}位"
    title = f"[{article['title']}]({article['url']})"
    author = f"[{article['user']['name']}](https://dev.to/{article['user']['username']})"
    published_at = f"{article['published_at']}"[:10].replace("-", "/")
    reading_time_minutes = f"{article['reading_time_minutes']}分"
    positive_reactions_count = f"{article['positive_reactions_count']}"
    return f"| {ranking} | {title} | {author} | {published_at} | {reading_time_minutes} | {positive_reactions_count} |"


if __name__ == "__main__":
    # setup directory
    TEMP_DIR.mkdir(exist_ok=True)
    work_dir = TEMP_DIR / f"{int(datetime.now().timestamp())}"
    work_dir.mkdir()

    # fetch all articles by tag
    fetch_articles(work_dir, "react")

    # load articles json and sort by public_reactions_count
    articles = load_articles(work_dir)
    sorted_articles = sorted(articles, key=lambda a : a["public_reactions_count"], reverse=True)

    # print top 100 articles as markdown table
    print("| 順位 | タイトル | 著者 | 公開日(UTC) | 読む時間 | いいね |")
    print("| - | - | - | - | - | - |")
    for i in range(0,100):
        print(create_table_row(i+1, sorted_articles[i]))

reactタグのついた記事のいいね数ランキング

スクリプトで出力した内容は以下になります。以下はあくまで、実行時(2022年11月20日16:12:08 )の最新情報でしかないので、この記事が古くなればなるほど信用できなくなるのでご注意を。

順位 タイトル 著者 公開日(UTC) 読む時間 いいね
1位 9 Projects you can do to become a Frontend Master Simon Holdorf 2019/10/06 7分 12696
2位 Clean Architecture on Frontend Alex Bespoyasov 2021/09/01 35分 5170
3位 The Complete Guide to Full Stack Ethereum and EVM Development Nader Dabit 2021/04/09 18分 3968
4位 The Ultimate Guide to Web Performance 🚀 ender minyard 2020/09/22 5分 3671
5位 35+ Free React templates and themes Davide Pacilio 2020/06/02 15分 3616
6位 22 Miraculous Tools for React Developers in 2019 jsmanifest 2019/08/06 13分 3428
7位 The React Cheatsheet for 2020 📄‬ (+ Real-World Examples) Reed Barger 2020/01/19 17分 3378
8位 300+ React Interview Questions Michael Sakhniuk 2021/01/05 128分 2968
9位 5 React Projects You Need In Your Portfolio 📂 Reed Barger 2020/01/26 7分 2895
10位 A Complete Beginner's Guide to React Ali Spittel 2018/08/28 15分 2829
11位 7 GitHub projects essential for every Javascript developer 👨🏽‍💻 🚀 Ankit Anand ✨ 2021/06/28 3分 2632
12位 ReactJS Roadmap 🗺 For Developers 💻 ThemeSelection 2020/10/06 9分 2508
13位 8 Projects with modern designs to become a Full-stack Master 2020 Thu Nghiem 2020/09/02 4分 2354
14位 Practical Ways to Write Better JavaScript Ryland G 2019/07/25 13分 2055
15位 React Interview Questions 🔥 Pramit Marattha 2021/11/16 15分 2008
16位 Design Patterns in JavaScript Zeeshan Haider Shaheen 2021/08/27 16分 1961
17位 The Complete Guide to Full Stack Solana Development with React, Anchor, Rust, and Phantom Nader Dabit 2021/09/15 18分 1948
18位 React Cheat sheet (Updated June 2021) Eric The Coder 2021/06/11 7分 1934
19位 Productive Tools🚀 For Web Development😎 Akshay Chougule 2020/02/22 2分 1925
20位 Become a Full Stack Developer by building these amazing applications Yogesh Chavan 2020/09/02 4分 1848
21位 8 Projects to Build to Master Your Front-End Skills 🥇🏆 Madza 2021/08/05 5分 1813
22位 5 full-stack projects to add to your portfolio before 2020 ends 🤯 Chris Bongers 2020/08/28 3分 1705
23位 Building a chat app with Socket.io and React 🚀 Nevo David 2022/08/15 16分 1695
24位 Video Chatting and Screen Sharing with React, Node, WebRTC(peerjs) Arjhun777 2021/01/02 7分 1667
25位 ⚛️ 🚀 React Component Patterns Alexi Taylor 🐶 2020/08/26 17分 1653
26位 21 React Example Projects to Learn From (Open-source, Beginner-Intermediate Level) Syakir Rahman 2020/09/28 9分 1636
27位 Cheat Sheets that always save my time during web development 🚀 Mahesh Patidar 2021/10/22 2分 1595
28位 How to learn React - The Effective way Shaan Alam 2021/09/07 4分 1563
29位 No More ../../../ Import in React Nilanth 2021/08/15 3分 1543
30位 16 Libraries You Should Know as a React Developer 💯🔥 Madza 2022/10/04 3分 1526
31位 15 Free React Templates for Your Next Project ExWhyZee 2021/04/15 6分 1521
32位 The vanilla Javascript basics to know before learning React JS Jane Tracy 👩🏽‍💻 2020/09/20 9分 1507
33位 My favorite resources being a freelancer as a side hustle 💎 leonardo jaques 👨🏻‍💻 2020/08/05 4分 1502
34位 Advanced JavaScript Design Patterns DhiWise 2021/11/24 11分 1501
35位 How I structure my React projects Lars Wächter 2021/08/31 5分 1490
36位 50 Cool Web And Mobile Project Ideas for 2021 Andrew Baisden 2021/03/26 15分 1473
37位 Why I Stopped Using Redux Gabriel Abud 2020/07/06 6分 1471
38位 ReactJs Roadmap🗺 for beginners - 2021 Suhail Shaikh 2021/08/19 6分 1431
39位 26 Miraculous VS Code Tools for JavaScript Developers in 2019 jsmanifest 2019/07/07 11分 1407
40位 20 GitHub Repositories to Become a React Master Martin Adams 2022/08/04 5分 1397
41位 Top 20 JavaScript tips and tricks to increase your Speed and Efficiency Kapil Raghuwanshi🖥 2021/06/08 6分 1367
42位 Moving away from ReactJs and VueJs on front-end using Clean Architecture Jorge Sánchez Fernández 2021/07/12 15分 1338
43位 8 Projects with Designs you can do to Become FRONT-END developer Thu Nghiem 2020/07/02 2分 1337
44位 8 Awesome React Hooks Simon Holdorf 2020/12/23 3分 1336
45位 Why You Shouldn't Use A Web Framework David Wickes 2018/07/26 4分 1329
46位 Modern Full-Stack Developer Tech Stack 2021 Andrew Baisden 2021/07/05 3分 1311
47位 How to deploy React App to GitHub Pages Ibrahim Ragab 2019/06/23 2分 1310
48位 How to Build a Full Stack NFT Marketplace - V2 (2022) Nader Dabit 2021/07/06 22分 1309
49位 JavaScript Basics Before You Learn React Nathan Sebhastian 2019/01/14 9分 1266
50位 Making Sense of React Hooks Dan Abramov 2018/11/02 11分 1217
51位 How to Reduce React App Loading Time By 70% Nilanth 2021/09/14 5分 1194
52位 Top 42 React resources every developer should bookmark [Latest] Sunil Joshi 2020/10/22 6分 1167
53位 useAxios : A simple custom hook for calling APIs using axios Yogini Bende 2021/05/18 4分 1166
54位 Don't waste your time on a portfolio website Johannes Kettmann 2020/10/20 8分 1158
55位 How to Build Scalable Architecture for your Next.js Project Alex Eagleson 2022/04/06 32分 1152
56位 How to Create and Publish a React Component Library Alex Eagleson 2021/11/17 24分 1140
57位 No, disabling a button is not app logic. David K. 🎹 2019/11/13 11分 1139
58位 17 Javascript optimization tips to know in 2021 🚀 Blessing Hirwa 2021/01/25 5分 1135
59位 Bad Habits of Mid-Level React Developers Sam Magura 2022/04/09 8分 1110
60位 Roadmap for React JS 2022 Digvijay Jadhav 2021/12/07 4分 1086
61位 React Libraries To Use In 2021: 17 Top Picks Yash Tiwari 2021/06/13 8分 1083
62位 Build a Pixel Perfect Skeleton Loader Using CSS 🚀 Ram Maheshwari ⚡ 2021/09/15 5分 1073
63位 37 App Ideas for Bootcamp Students & Code Newbies Sylwia Vargas 2019/12/01 4分 1066
64位 The Complete Modern React Developer 2022 Andrew Baisden 2022/05/10 29分 1066
65位 Free hosting providers for front-end & back-end applications Vuelancer 2020/09/10 2分 1058
66位 Just Redux: The Complete Guide Sanjeev Sharma 2021/09/23 10分 1030
67位 Use Javascript console like pro Suprabha 2021/05/16 3分 1021
68位 React Architecture for Enterprise Application Nilanth 2021/11/06 4分 999
69位 Some projects to build your resume! Unnati Bamania 2021/01/18 4分 999
70位 React Clean Code - Simple ways to write better and cleaner code Tyler Hawkins 2021/02/22 2分 993
71位 What Front-End Developer Skills Should You Focus on Leading Into 2020? Marc Grabanski 🏙💻 2019/08/19 5分 992
72位 Understanding Rendering in React ♻ ⚛️ Mateo Garcia 2021/01/31 6分 991
73位 Learn Deno: Chat app Aral Roca 2020/05/10 10分 986
74位 Building a Notion-like system with Socket.io And React 😍 Nevo David 2022/10/24 19分 982
75位 In defense of the modern web Rich Harris 2020/05/15 6分 974
76位 10 Must-Know Patterns for Writing Clean Code with React and TypeScript✨🛀 Alex Omeyer 2022/02/04 6分 968
77位 7 Tips for Clean React TypeScript Code you Must Know 🧹✨ Tapajyoti Bose 2022/07/17 5分 967
78位 Free React resources you should have in your pocket. Jane Tracy 👩🏽‍💻 2020/09/27 6分 960
79位 Top 10 React Hook libraries Juraj Pavlović 2020/10/19 6分 959
80位 39+ Advanced React Interview Questions (SOLVED) You Must Clarify (2020 Update) Alex 👨🏼‍💻FullStack.Cafe 2019/11/04 18分 957
81位 How to make realtime APIs with NodeJS and ReactJS using Socket.io Omar Diaaeldine Elwakeel 2021/08/25 5分 943
82位 I was creating Forms the wrong way all along in React.js 🤔 Kuvam Bhardwaj 2022/08/01 4分 933
83位 Building a Kanban board with Node.js, React and Websockets 📝 ✨ Nevo David 2022/09/28 18分 932
84位 Screaming Architecture - Evolution of a React folder structure Johannes Kettmann 2022/02/25 16分 919
85位 Python Chat Tutorial with Django and React Nick Parsons 2019/05/08 8分 917
86位 Redux Crash Course with Hooks 🎣 Chris Achard 2019/10/02 3分 912
87位 The Complete Guide to Next.js Authentication Nader Dabit 2020/09/21 8分 902
88位 7 code smells in your React components Anton Gunnarsson 2020/11/09 9分 902
89位 11 Advanced React Interview Questions you should absolutely know (with detailed answers) Tapajyoti Bose 2022/07/10 5分 880
90位 5 Good practices to scale your React projects easily Jeffrey Yu 2022/08/07 3分 875
91位 Front-End Resources bleedeleventh 2021/10/10 20分 873
92位 Want To Learn React in 2020? Here's The Blueprint to Follow. Reed Barger 2020/01/06 7分 872
93位 10 Awesome Free Courses for Devs by Devs Simon Holdorf 2021/01/04 8分 869
94位 How we reduced our initial JS/CSS size by 67% Guilherme Oenning 2018/11/26 8分 867
95位 5 Tips to Take your Website Lighthouse Score from Meh to WOW! Tapajyoti Bose 2021/11/07 4分 865
96位 34 UI Libraries For React, Vue And Angular Niemvuilaptrinh 2021/02/03 7分 861
97位 Building a chat - Browser Notifications with React, Websockets and Web-Push 🤯 Nevo David 2022/08/22 8分 859
98位 Building a sexy, mobile-ready navbar in any web framework Ben Holmes 2020/10/06 9分 845
99位 The Full-Stack Developer Vocabulary(The Full List!) Code_Jedi 2022/01/01 11分 841
100位 The React Cheatsheet for 2021‬ 📄 (+ Real-World Examples) Reed Barger 2021/01/09 23分 838

おわりに

今回はいろいろハードコードで済ませているところが多いので、皆さんもご自身のユースケースに合わせてスクリプトをいじるか汎用化して使ってもらったらいいかと思います。

Discussion