在微信小程序上做一個「博客園年度總結」:後端部分 基於jira數據開發一個質量看板

2022年馬上要結束了,最近突然有個想法,利用微信小程序+博客園接口做了一個「博客園年度總結」,統計下自己寫博客這些年的數據情況,最終效果如下

在開始之前先捋一捋思路,大致要實現以下幾個功能:

1、使用flask提供後端服務,調用博客園接口獲取數據,然後作進一步處理,給微信小程序提供接口;

2、在小程序中通過上劃/下划來切換頁面;

3、在小程序中展示數據圖表(接入echarts);

4、在最後一頁能夠通過點擊按鈕進行回看和分享;

 

本章來寫一下後端處理邏輯

 

本次需要調用博客園如下接口來獲取相關數據:

1、獲取當前登錄用戶信息,接口文檔:https://api.cnblogs.com/help#4e598eb53dda7bd5ed0291edd7155871

這個接口返回你的「博客名」、「園齡」、「粉絲數」等,如下

{
    "UserId": "xxx",
    "SpaceUserID": xxx,
    "BlogId": xxx,
    "DisplayName": "我是冰霜",
    "Face": "https://pic.cnblogs.com/face/1158674/20201224122945.png",
    "Avatar": "https://pic.cnblogs.com/avatar/1158674/20201224122945.png",
    "Seniority": "5年5個月",
    "BlogApp": "hanmk",
    "FollowingCount": 16,
    "FollowerCount": 532
}

2、獲取個人博客信息,接口文檔:https://api.cnblogs.com/help#f8c559cde161e9a9d08c9e84cb106cc3

這個接口主要返回你的「博客數量」、「博客簽名」等

{
    "blogId": xxx,
    "title": "我是冰霜",
    "subtitle": "I am just a sunflower, waiting for my only sunshine.",
    "postCount": 245,
    "pageSize": 10,
    "enableScript": true
}

3、獲取個人博客隨筆列表,接口文檔:https://api.cnblogs.com/help#691c5586990ad52adc500024fc6f260b

這個接口返回你的博客隨筆列表

[
  {
    "Id": 1,
    "Title": "sample string 2",
    "Url": "sample string 3",
    "Description": "sample string 4",
    "Author": "sample string 5",
    "BlogApp": "sample string 6",
    "Avatar": "sample string 7",
    "PostDate": "2017-06-25T20:15:30.2514989+08:00",
    "ViewCount": 9,
    "CommentCount": 10,
    "DiggCount": 11
  },
  {
    "Id": 1,
    "Title": "sample string 2",
    "Url": "sample string 3",
    "Description": "sample string 4",
    "Author": "sample string 5",
    "BlogApp": "sample string 6",
    "Avatar": "sample string 7",
    "PostDate": "2017-06-25T20:15:30.2514989+08:00",
    "ViewCount": 9,
    "CommentCount": 10,
    "DiggCount": 11
  }
]

前2個接口比較簡單,數據拿來後可以直接返給前端去用,但是最後一個「獲取隨筆列表」接口,從博客園拿到數據後還需要加工一下,達到如下目的

  1. 把發佈的第一篇博客單獨拎出來;
  2. 提取瀏覽量排名前6的隨筆;
  3. 統計每年創建的隨筆總數;
  4. 統計一年當中每個月創建的隨筆總數;

重點代碼實現邏輯

1、獲取當前登錄用戶信息

def get_users(self):
    """獲取當前登錄用戶信息接口"""
    url = "https://api.cnblogs.com/api/users"
    try:
        res = requests.get(url=url, headers=self.headers)
        data = res.json()
        # print(res.request.headers)
        # print(data)
        return data

    except Exception as e:
        raise e

2、獲取個人博客信息

def get_blog_info(self, blog_name):
    """獲取個人博客信息接口"""

    url = "https://api.cnblogs.com/api/blogs/" + blog_name

    try:
        res = requests.get(url=url, headers=self.headers)
        data = res.json()
        # print(data)
        return data

    except Exception as e:
        raise e

3、獲取個人博客隨筆列表

def deal_blogs(blogs):
    """處理從博客園獲取到的隨筆數據"""
    new_data = None
    if blogs:
        new_data = {
            "Title": blogs["Title"],  # 標題
            "PostDate": blogs["PostDate"].split("T")[0],  # 發佈時間(截取日期部分,如2022-09-07)
            "ViewCount": blogs["ViewCount"],  # 瀏覽次數
            "CommentCount": blogs["CommentCount"],  # 評論次數
            "DiggCount": blogs["DiggCount"]  # 點擊次數
        }
    return new_data

def get_blogs_api(self, blog_name):
    """獲取個人隨筆列表接口"""
    flag = True
    try:
        blogs = []
        i = 1
        while flag is True:

            url = "https://api.cnblogs.com/api/blogs/{}/posts?pageIndex={}".format(blog_name, i)
            res = requests.get(url=url, headers=self.headers)
            data = res.json()
            # print(data)
            # print(i)
            if data:
                blogs += data
                i += 1
            else:
                # print(data)
                flag = False
        # print(len(blogs))
        # print(blogs)
        # print("123")
        new_blogs = list(map(self.deal_blogs, blogs))
        # [{'Title': 'xx', 'PostDate': 'xx-xx-xx', 'ViewCount': xx, 'CommentCount': 0, 'DiggCount': 0}, {}, {}]
        # print(new_blogs)

        first_blog = new_blogs[-1]  # 發佈的第一篇博客
        # {'Title': 'xx', 'PostDate': 'xx-xx-xx', 'ViewCount': xx, 'CommentCount': 0, 'DiggCount': 0}
        # print(first_blog)

        sort_blogs = sorted(new_blogs, key=lambda item: item["ViewCount"], reverse=True)  # 按照ViewCount排序,降序
        print(sort_blogs)

        view_max_10 = sort_blogs[0:10]  # 瀏覽量前10的文章
        # print(view_max_10)

        """提取2022年的月度數據並處理"""
        blog_date1 = [i["PostDate"][0:7] for i in new_blogs]  # 提取每條數據的年月,組成一個列表
        # print(blog_date1)
        temp = Counter(blog_date1)
        month_blog_date = dict(temp)
        # print(month_blog_date)

        months = ["2022-01", "2022-02", "2022-03", "2022-04", "2022-05", "2022-06",
                  "2022-07", "2022-08", "2022-09", "2022-10", "2022-11", "2022-12"]

        month_result = []  # 2022年每月博客新增數量

        for j in months:  # 遍歷日期範圍列表
            if j in month_blog_date:
                # 如果一個日期在bug列表中,說明這個日期有值,取bug字典中該日期的值賦給bug_num,同時date取當前日期,組合爲一個字典
                month_result.append({"date": j, "value": month_blog_date[j]})
            else:
                # 否則這個日期對應的value=0
                month_result.append({"date": j, "value": 0})

        # print(month_result)
        now_year_blog_sum = sum([i["value"] for i in month_result])  # 2022年新增博客總數
        # print(now_year_blog_sum)

        """提取年度數據並處理"""
        blog_date2 = [i["PostDate"][0:4] for i in new_blogs]  # 提取每條數據的年,組成一個列表
        year_blog_date = dict(Counter(blog_date2))
        # print(year_blog_date)
        begin_year = first_blog["PostDate"][0:4]
        # print(begin_year)
        end_year = get_now_year()
        # print(end_year)
        # print(type(begin_year), type(end_year))
        date_gap = int(end_year) - int(begin_year) + 1
        years = []
        for i in range(date_gap):
            years.append(str(int(begin_year) + i))
        # print(years)

        year_result = []  # 每年博客新增數量
        for j in years:  # 遍歷日期範圍列表
            if j in year_blog_date:
                # 如果一個日期在bug列表中,說明這個日期有值,取bug字典中該日期的值賦給bug_num,同時date取當前日期,組合爲一個字典
                year_result.append({"date": j, "value": year_blog_date[j]})
            else:
                # 否則這個日期對應的value=0
                year_result.append({"date": j, "value": 0})

        # print(year_result)

        res = {
            "first_blog": first_blog,  # 發佈的第一篇博客
            "view_max_10": view_max_10,  # 瀏覽量前10的文章
            "now_year_blog_sum": now_year_blog_sum,  # 2022年新增博客總數
            "month_result": month_result,  # 2022年每月博客新增數量
            "year_result": year_result  # 每年博客新增數量
        }
        print(res)

        return res

    except Exception as e:
        raise e

代碼說明:

1、deal_blogs()函數

我打算使用python的map函數來處理原始數據,所以這裏先定義一個數據處理函數,

從博客園接口獲取到的數據格式如下,一個列表包含多個字典

[
  {
    "Id": 1,
    "Title": "sample string 2",
    "Url": "sample string 3",
    "Description": "sample string 4",
    "Author": "sample string 5",
    "BlogApp": "sample string 6",
    "Avatar": "sample string 7",
    "PostDate": "2017-06-25T20:15:30.2514989+08:00",
    "ViewCount": 9,
    "CommentCount": 10,
    "DiggCount": 11
  },
  ...
  ...
  ...
]

每個字典中有很多字段,我只想提取其中一些必要的字段,只保留TitlePostDateViewCount等字段

def deal_blogs(blogs):
    """處理從博客園獲取到的隨筆數據"""
    new_data = None
    if blogs:
        new_data = {
            "Title": blogs["Title"],  # 標題
            "PostDate": blogs["PostDate"].split("T")[0],  # 發佈時間(截取日期部分,如2022-09-07)
            "ViewCount": blogs["ViewCount"],  # 瀏覽次數
            "CommentCount": blogs["CommentCount"],  # 評論次數
            "DiggCount": blogs["DiggCount"]  # 點擊次數
        }
    return new_data

2、get_blogs_api()函數

爲了方便,我把數據處理過程都寫到這個函數中了,然後統一返回出去

(1)循環分頁調用獲取隨筆列表接口

在調用博客園隨筆列表接口時,需要傳入pageIndex

因爲我們並不知道一共有多少頁數據,所以這裏我使用了while循環,當接口返回空時說明到了最後一頁

... ...
... ...
flag = True
try:
    blogs = []
    i = 1
    while flag is True:

        url = "https://api.cnblogs.com/api/blogs/{}/posts?pageIndex={}".format(blog_name, i)
        res = requests.get(url=url, headers=self.headers)
        data = res.json()
        # print(data)
        # print(i)
        if data:
            # 如果接口有返回數據,就把數據追加到blogs中,同時頁碼+1
            blogs += data
            i += 1
        else:
            # 如果接口返回空,說明當前傳入的頁碼已經沒有沒有數據了,結束循環
            # print(data)
            flag = False

    new_blogs = list(map(self.deal_blogs, blogs))  # 調用map函數處理博客原始數據
... ...
... ...

(2)提取發佈的的第一篇博客

因爲博客園隨筆列表接口返回的數據默認是按照倒序排列的,所以最後一條就是發佈的第一篇博客

first_blog = new_blogs[-1]  # 發佈的第一篇博客

(3)獲取瀏覽量爲前10的博客

需要對數據按照「瀏覽量」進行排序,然後取前10條即可

可以通過sorted()函數來實現

sort_blogs = sorted(new_blogs, key=lambda item: item["ViewCount"], reverse=True)  # 按照ViewCount排序,降序
print(sort_blogs)

view_max_10 = sort_blogs[0:10]  # 瀏覽量前10的文章

打印結果

[{'Title': '如何查看linux服務器內存使用情況', 'PostDate': '2019-03-19', 'ViewCount': 200087, 'CommentCount': 4, 'DiggCount': 0}, {'Title': 'python+selenium基礎之XPATH定位(第一篇)', 'PostDate': '2018-05-06', 'ViewCount': 109768, 'CommentCount': 9, 'DiggCount': 0}, {'Title': 'oracle導入dmp文件的2種方法', 'PostDate': '2017-07-26', 'ViewCount': 102784, 'CommentCount': 1, 'DiggCount': 0}, {'Title': 'python爬蟲學習(一):BeautifulSoup庫基礎及一般元素提取方法', 'PostDate': '2018-04-05', 'ViewCount': 100563, 'CommentCount': 9, 'DiggCount': 0}, {'Title': 'python讀取配置文件&&簡單封裝', 'PostDate': '2018-10-24', 'ViewCount': 87415, 'CommentCount': 0, 'DiggCount': 0}, {'Title': 'oracle導出dmp文件的2種方法', 'PostDate': '2017-07-26', 'ViewCount': 75031, 'CommentCount': 0, 'DiggCount': 0}, {'Title': '利用拷貝data目錄文件的方式遷移mysql數據庫', 'PostDate': '2017-12-05', 'ViewCount': 64000, 'CommentCount': 3, 'DiggCount': 0}, {'Title': 'linux下查看進程id時用到的命令', 'PostDate': '2019-03-18', 'ViewCount': 63239, 'CommentCount': 0, 'DiggCount': 0}, {'Title': '在python中使用正則表達式(一)', 'PostDate': '2018-06-06', 'ViewCount': 58195, 'CommentCount': 2, 'DiggCount': 0}, {'Title': 'postman(十一):添加cookie', 'PostDate': '2019-04-29', 'ViewCount': 54866, 'CommentCount': 0, 'DiggCount': 0}, {'Title': '使用Dockerfile創建一個tomcat鏡像,並運行一個簡單war包', 'PostDate': '2018-03-10', 'ViewCount': 39556, 'CommentCount': 2, 'DiggCount': 0}, {'Title': 'postman(六):詳解在Pre-request Script中如何執行請求', 'PostDate': '2018-12-30', 'ViewCount': 37908, 'CommentCount': 11, 'DiggCount': 0}, {'Title': '如何在jenkins上新建一個項目及其簡單配置', 'PostDate': '2017-05-04', 'ViewCount': 28941, 'CommentCount': 0, 'DiggCount': 0}, {'Title': 'python日誌模塊的使用', 'PostDate': '2019-02-28', 'ViewCount': 28605, 'CommentCount': 1, 'DiggCount': 0}, {'Title': 'nginx反向代理實例', 'PostDate': '2018-07-10', 'ViewCount': 27529, 'CommentCount': 1, 'DiggCount': 0}, {'Title': 'SQL查詢--索引', 'PostDate': '2019-08-31', 'ViewCount': 26935, 'CommentCount': 0, 'DiggCount': 0}, {'Title': 'postman(二):使用postman發送get or post請求', 'PostDate': '2018-12-20', 'ViewCount': 24487, 'CommentCount': 0, 'DiggCount': 0}, {'Title': 'python基礎:刪除列表中特定元素的幾種方法', 'PostDate': '2020-10-11', 'ViewCount': 23846, 'CommentCount': 0, 'DiggCount': 0}, {'Title': '使用pymysql操作數據庫', 'PostDate': '2018-06-22', 'ViewCount': 23806, 'CommentCount': 0, 'DiggCount': 0}, {'Title': 'python之做一個簡易的翻譯器(一)', 'PostDate': '2019-04-14', 'ViewCount': 17938, 'CommentCount': 1, 'DiggCount': 0}, {'Title': 'python爬蟲學習(三):使用re庫爬取"淘寶商品",並把結果寫進txt文件', 'PostDate': '2018-04-08', 'ViewCount': 17260, 'CommentCount': 2, 'DiggCount': 0}, {'Title': '在不安裝oracle客戶端的情況下,使用PLSQL', 'PostDate': '2018-11-27', 'ViewCount': 15983, 'CommentCount': 2, 'DiggCount': 0}, {'Title': '使用“rz -be”命令上傳文件至服務器;使用“sz 文件名”從服務器下載文件到本地', 'PostDate': '2018-07-02', 'ViewCount': 15654, 'CommentCount': 0, 'DiggCount': 0}, {'Title': 'python多線程:控制線程數量', 'PostDate': '2020-05-30', 'ViewCount': 15577, 'CommentCount': 0, 'DiggCount': 0}, {'Title': '理解css相鄰兄弟選擇器', 'PostDate': '2018-05-19', 'ViewCount': 15303, 'CommentCount': 3, 'DiggCount': 0},... ...]

(4)本次我要做2張柱狀圖圖表:2022年月度新增隨筆趨勢、2017~2022年度新增隨筆趨勢

因爲之前有提取jira數據做質量看板的經驗,這次處理起來就駕輕就熟了(傳送門:基於jira數據開發一個質量看板

下面是月度數據和年度數據的處理邏輯

"""提取2022年的月度數據並處理"""
blog_date1 = [i["PostDate"][0:7] for i in new_blogs]  # 提取每條數據的年月,組成一個列表
# print(blog_date1)
temp = Counter(blog_date1)
month_blog_date = dict(temp)
# print(month_blog_date)

months = ["2022-01", "2022-02", "2022-03", "2022-04", "2022-05", "2022-06",
          "2022-07", "2022-08", "2022-09", "2022-10", "2022-11", "2022-12"]

month_result = []  # 2022年每月博客新增數量

for j in months:  # 遍歷日期範圍列表
    if j in month_blog_date:
        # 如果一個日期在bug列表中,說明這個日期有值,取bug字典中該日期的值賦給bug_num,同時date取當前日期,組合爲一個字典
        month_result.append({"date": j, "value": month_blog_date[j]})
    else:
        # 否則這個日期對應的value=0
        month_result.append({"date": j, "value": 0})

# print(month_result)
now_year_blog_sum = sum([i["value"] for i in month_result])  # 2022年新增博客總數
"""提取年度數據並處理"""
blog_date2 = [i["PostDate"][0:4] for i in new_blogs]  # 提取每條數據的年,組成一個列表
year_blog_date = dict(Counter(blog_date2))
# print(year_blog_date)
begin_year = first_blog["PostDate"][0:4] # 取發佈的第一篇博客所在的年份,因爲這就是博客起始年份
# print(begin_year)
end_year = get_now_year() # 取當年年份爲結束年份
# print(end_year)
# print(type(begin_year), type(end_year))
date_gap = int(end_year) - int(begin_year) + 1 # 計算年份差

years = [] # 定義年份範圍
for i in range(date_gap):
    years.append(str(int(begin_year) + i))
# print(years)

year_result = []  # 每年博客新增數量
for j in years:  # 遍歷年份範圍列表
    if j in year_blog_date:
        # 如果一個日期在bug列表中,說明這個日期有值,取bug字典中該日期的值賦給bug_num,同時date取當前日期,組合爲一個字典
        year_result.append({"date": j, "value": year_blog_date[j]})
    else:
        # 否則這個日期對應的value=0
        year_result.append({"date": j, "value": 0})

# print(year_result)

最後把這些數據放到一個字典中返回出去即可

res = {
    "first_blog": first_blog,  # 發佈的第一篇博客
    "view_max_10": view_max_10,  # 瀏覽量前10的文章
    "now_year_blog_sum": now_year_blog_sum,  # 2022年新增博客總數
    "month_result": month_result,  # 2022年每月博客新增數量
    "year_result": year_result  # 每年博客新增數量
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章