前面寫過一篇博客:在微信小程序上做一個「博客園年度總結」:解決前端獲取接口數據太慢的一種思路
當時是由於博客園接口獲取數據比較慢,所以從博客園拿到數據後,先把數據存到一個文件中,再從文件中讀取數據,這樣就不必每次都請求接口了
本次用redis來實現這個功能,把數據存儲到redis中,再從redis中讀取
1、本地安裝redis
因爲是在本地進行調試,所以要先在自己的電腦中安裝redis,
mac下安裝redis可參考:https://www.jianshu.com/p/2972c8e6d2f6
2、安裝rdm
爲了方便查看redis,安裝一個rdm軟件,
下載傳送門:鏈接: https://pan.baidu.com/s/1HSydI8sthcJ1ZgbIutfiAQ 密碼: 3ehk
3、使用redis
關於如何在python中使用redis,可以參考這篇博客,寫的比較清楚,傳送門:教你用Python玩轉Redis
(1)定義操作redis的基本方法
先創建一個conf_redis_db.py
文件
# coding: utf-8
"""
author: hmk
detail:
create_time:
"""
import redis
r = redis.Redis(host="127.0.0.1", port=6379, decode_responses=True, charset='UTF-8', encoding='UTF-8')
# r.set("name", "測試", ex=50)
# print(r.get("name"))
EXPIRES_TIME = 86400 # 過期時間,s
def set_redis_data(key, data):
"""redis寫入數據"""
r.set(name=key, value=data, ex=EXPIRES_TIME)
def get_redis_data(key):
"""redis讀取數據"""
data = r.get(key)
return data
(2)把博客園接口數據存儲到redis中
修改 get_cnblogs_data.py
博客園的數據是通過get_blogs_api()
方法獲取的,如下
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()
if data:
# 如果接口有返回數據,就把數據追加到blogs中,同時頁碼+1
blogs += data
i += 1
else:
# 如果接口返回空,說明當前傳入的頁碼已經沒有沒有數據了,結束循環
# print(data)
flag = False
new_blogs = list(map(self.deal_blogs, blogs)) # 調用map函數處理博客原始數據
first_blog = new_blogs[-1] # 發佈的第一篇博客
sort_blogs = sorted(new_blogs, key=lambda item: item["ViewCount"], reverse=True) # 按照ViewCount排序,降序
view_max_10 = sort_blogs[0:5] # 瀏覽量前10的文章
"""提取2022年的月度數據並處理"""
blog_date1 = [i["PostDate"][0:7] for i in new_blogs] # 提取每條數據的年月,組成一個列表
temp = Counter(blog_date1)
month_blog_date = dict(temp)
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})
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))
begin_year = first_blog["PostDate"][0:4] # 取發佈的第一篇博客所在的年份,因爲這就是博客起始年份
end_year = get_now_year() # 取當年年份爲結束年份
date_gap = int(end_year) - int(begin_year) + 1 # 計算年份差
years = []
for i in range(date_gap):
years.append(str(int(begin_year) + i))
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})
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 # 每年博客新增數量
}
return res
except Exception as e:
raise e
再寫一個方法把上述返回的數據存到redis中
from utils.conf_redis_db import *
def save_blogs(self, name):
data = self.get_blogs_api(name)
# print(data)
set_redis_data("blogs_data", json.dumps(data, ensure_ascii=False)) # 需要將data轉爲字符串,同時防止中文亂碼設置ensure_ascii
因爲get_blogs_api()
返回的數據爲字典格式,不能直接放到redis中,需要轉爲字符串
這裏使用json.dumps()
進行轉換,同時指定ensure_ascii
爲False
,以避免中文亂碼
執行這個方法後,redis中會存儲blogs_data
鍵,效果如下,
(3)調用redis數據
打開cnblog.py
,修改GetBlogs
方法,通過讀取redis中的key獲取數據
因爲在向redis寫入數據時,設置了過期時間,每隔24h會失效,當key失效時,我們會獲取到的是null
所以需要判斷這個情況,當key失效後,重新向redis寫入數據
class GetBlogs(Resource):
"""接口:獲取個人隨筆列表"""
"""使用redis數據"""
@staticmethod
def get():
blog_app = cn_blogs.conf["cn_blogs"]["blogApp"] # request.args.get("blog_app")
data = r.get("blogs_data")
if data is None: # 如果從redis讀取到空,說明key失效了,此時調用save_blogs()方法,重新向redis寫入數據
cn_blogs.save_blogs(blog_app)
return r.get("blogs_data")
else:
return data