How to use the Dev.to API to fetch your article statistics
Tags: python, api, statistics, devto
Published: 2021-02-02 15:00:32

I was curious to figure out if I could retrieve the number of views the posts I create on the Dev.to community and see how the numbers evolve over time. I found that the Dev.to platform has a good extensive and well documented API: [https://docs.dev.to/api/](https://docs.dev.to/api/) where you can read the information I was looking for. In the documentation you can see how to create your person access token. Remember to insert this token into the script below where you find the string `YOUR-PRIVATE-API-KEY-HERE`.

The script is meant to be run by a scheduler once every day to retrieve the article statistics. The script will persist the retrieved article statistics into a JSON file named devToArticleStats.json. It looks like the admins at Dev.to only updates your statistics once a day, so no need to run the script more than once every day.

The script is in Python and it does the following:
* Read the 'devToArticleStats.json' file if it already exists
* Fetch the article statistics from the Dev.to API
* For each article retrieved:
	* If the article does not exists in the internal structure then create a new instance and add it to the internal structure.
	* If the statistics for today already exists the update them with the retrieved data, else create a new instance of the statistics for today.
* Save the internal structure into the 'devToArticleStats.json' file in JSON format.

Now you have the data in JSON format and then its up to you how you want to have fun with it. You could start by visualizing the data :-)

Remember to create a scheduled task in the Windows Scheduler, the Cron scheduler on Linux or the 'whatever-its-called' scheduler on macOS.

This is the script:
```python
import requests
import json
import datetime
import dateutil.parser
from os import path
from typing import List

class ArticleStats(object):
    def __init__(self, date: str, page_views_count: int, public_reactions_count: int, comments_count: int):
        self.date = date
        self.page_views_count = page_views_count
        self.public_reactions_count = public_reactions_count
        self.comments_count = comments_count

class Article(object):
    def __init__(self, title: str, published: str, stats: List[ArticleStats] = []):
        self.title = title
        self.published = published
        self.stats = stats

class DevStats(object):
    def __init__(self, articles: List[Article]):
        self.articles = articles

    def toJSON(self):
        return json.dumps(self, default=lambda o: o.__dict__, sort_keys=True, indent=4)


url = "https://dev.to/api/articles/me"
headers = {
    'api-key': 'YOUR-PRIVATE-API-KEY-HERE', # You have to put your own api-key here. How to get a api-key: https://docs.dev.to/api/#section/Authentication/api_key
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36'
}

statsFilename = "devToArticleStats.json"
if(path.exists(statsFilename)): # If the statistics json file already exist then read it so we later can append the retrieved data to it
    statsFile = open(statsFilename, 'r')
    devToStatsJson = str(statsFile.read())
    statsFile.close()
else:
    devToStatsJson = '{ "articles": []  }'

devToJson = requests.get(url, headers=headers).json() # Call the api to retrieve the statustics
devToStatsDict = json.loads(devToStatsJson)
devToStats = DevStats(**devToStatsDict)

articleStats = ""
for articleFromDev in devToJson:
    publishedObj = dateutil.parser.isoparse(articleFromDev['published_at'])
    publishedStr = datetime.datetime.strftime(publishedObj, "%d-%m-%Y %H:%M:%S")
    title = articleFromDev['title']
    pageViews = articleFromDev['page_views_count']
    reactions = articleFromDev['public_reactions_count']
    comments = articleFromDev['comments_count']
    existingArticle = next((article for article in devToStats.articles if article['title'] == title), None) # Get the article from the dictionary if it exists else add a new instance
    if existingArticle == None:
      existingArticle = {'title': title, 'published': publishedStr, 'stats': []}
      devToStats.articles.append(existingArticle)
    
    today = str(datetime.date.today())
    articleStats = next((stats for stats in existingArticle['stats'] if stats['date'] == today), None)  # Get the stats for today from the dictionary if it exists else add a new instance
    if articleStats == None:
      articleStats = ArticleStats(today, pageViews, reactions, comments)
      existingArticle['stats'].append(articleStats)
    else:
      articleStats['page_views_count'] = pageViews
      articleStats['public_reactions_count'] = reactions
      articleStats['comments_count'] = comments

statsFile = open(statsFilename, 'w') # Save the article stats to the statistics json file 
statsFile.write(devToStats.toJSON())
statsFile.close()
```