日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python数据可视化:使用dash给博客制作一个dashboard

發布時間:2023/12/14 python 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python数据可视化:使用dash给博客制作一个dashboard 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

項目部署在:https://ffzs-blog-dashboard.herokuapp.com/
項目代碼在:https://github.com/ffzs/dash_blog_dashboard

1.dashboard

儀表板通常提供與特定目標或業務流程相關的關鍵績效指標(KPI)的概覽。另一方面,“儀表板”具有“進度報告”或“報告”的另一個名稱。

“儀表板”通常顯示在網頁上,該網頁鏈接到允許報告不斷更新的數據庫。例如,制造儀表板可以顯示與生產率相關的數字,例如制造的零件數量,或每小時失敗的質量檢查的數量。同樣,人力資源儀表板可能會顯示與員工招聘,保留和組成相關的數字,例如,或平均天數或每次招聘成本。

2.功能確定

寫之前先確定一些要實現的功能:

2.1. 博客基本數據跟蹤


上圖中的博客中的數據進行實時跟蹤,且1分鐘一刷新一次(之前用10秒,ip被封了。。。。),將這些數據橫向放在一個row里,博客名稱和頭像放在頁頭。
實現效果如下:

2.2. 圖表確定

2.2.1 展示每月寫作情況的柱狀圖

其實就是博客上下面的數據:

2.2.2 展示不同類型文章的餅圖

這里我對我文章類型重新劃分了類型,博客上劃分的有點亂,而且我確定了每篇文章只有一個類型, 具體代碼如下:

def get_type(title):the_type = '其他'article_types = ['項目', 'pytorch', 'flask', 'scikit-learn', 'pyspark', '數據預處理', '每日一練', '數據分析', '爬蟲','數據可視化', 'java', '增長黑客']for article_type in article_types:if article_type in title:the_type = article_typebreakreturn the_type

2.2.3 各類文章的總/平均閱讀情況

文章的閱讀情況是作者比較關系的數據,這里用柱狀圖展示沒類文章總的閱讀數,用折線圖展示沒類文章平均閱讀情況:

2.2.4 用熱圖展示每日寫作情況

通過顏色的深淺表示當天發布文章的數量, 通過下拉菜單選擇年份:

這個圖是不是看著很眼熟。。

其實就是模仿gayhub的樣式。

2.2.5 文章列表

顯示文章的標題,點擊跳轉到相應網頁,關聯圖片,通過點擊圖表對文章顯示做選擇:

2.2.6 色調選擇

為啥用綠色?有如下幾個原因:

  • 春天快來了,萬物復蘇,動物們又到了交。。。。。反正就是有生機
  • 模仿github的熱圖樣式
  • 要想生活過得去。。。
  • 請原諒我的不正經[滑稽]

    3 數據獲取

    數據獲取主要分兩個部分:基本數據獲取(1分鐘刷新一次),文章數據獲取(1小時刷新一次)

    3.1 基本數據獲取

    博客沒有api,只能自己爬取,注意不要訪問頻率太高,會封ip
    代碼如下:

    def get_info():headers = {'User-Agent': 'Mozilla/5.0 (MSIE 10.0; Windows NT 6.1; Trident/5.0)','referer': 'https: // passport.csdn.net / login',}url = random.choice(blog_list)try:resp = requests.get(url, headers=headers)now = dt.datetime.now().strftime("%Y-%m-%d %X")soup = BeautifulSoup(resp.text, 'lxml')head_img = soup.find('div', class_='avatar-box d-flex justify-content-center flex-column').find('a').find('img')['src']author_name = soup.find('div', class_='user-info d-flex justify-content-center flex-column').get_text(strip=True)row1_nums = soup.find('div', class_='data-info d-flex item-tiling').find_all('span', class_='count')row2_nums = soup.find('div', class_='grade-box clearfix').find_all('dd')rank = soup.find('div', class_='grade-box clearfix').find_all('dl')[-1]['title']info = {'date': now,'head_img': head_img,'author_name': author_name,'article_num': int(row1_nums[0].get_text()),'fans_num': int(row1_nums[1].get_text()),'like_num': int(row1_nums[2].get_text()),'comment_num': int(row1_nums[3].get_text()),'level': int(row2_nums[0].find('a')['title'][0]),'visit_num': int(row2_nums[1]['title']),'score': int(row2_nums[2]['title']),'rank': int(rank),}df_info = pd.DataFrame([info.values()], columns=info.keys())return df_infoexcept Exception as e:print(e)

    3.2 博客文章獲取

    獲取博客的所有文章的相關數據,并存儲到sqlite中,代碼如下:

    def get_blog():headers = {'User-Agent': 'Mozilla/5.0 (MSIE 10.0; Windows NT 6.1; Trident/5.0)','referer': 'https: // passport.csdn.net / login',}base_url = 'https://blog.csdn.net/tonydz0523/article/list/'resp = requests.get(base_url+"1", headers=headers, timeout=3)max_page = int(re.findall(r'var listTotal = (\d+) ;', resp.text)[0])//20+2 # 在js中獲取文章數df = pd.DataFrame(columns=['url', 'title', 'date', 'read_num', 'comment_num', 'type'])count = 0for i in range(1, max_page):url = base_url + str(i)resp = requests.get(url, headers=headers)soup = BeautifulSoup(resp.text, 'lxml')articles = soup.find("div", class_='article-list').find_all('div', class_='article-item-box csdn-tracking-statistics')for article in articles[1:]:a_url = article.find('h4').find('a')['href']title = article.find('h4').find('a').get_text(strip=True)[1:]issuing_time = article.find('span', class_="date").get_text(strip=True)num_list = article.find_all('span', class_="num")read_num = num_list[0].get_text(strip=True)comment_num = num_list[1].get_text(strip=True)the_type = get_type(title)df.loc[count] = [a_url, title, issuing_time, int(read_num), int(comment_num), the_type]count += 1time.sleep(random.choice([1, 1.1, 1.3]))return dfdf_article = get_blog() df_article.to_sql('blogs', con=engine, if_exists='replace', index=True)

    獲取數據的沒有難點,獲取頁數可以在js代碼中找

    4 數據交互

    如想使用交互是的顯示數據,那么就需要使數據在前后段進行傳輸,dash使用react.js創建了很多相關表單組件,通過配合后端的callback函數進行數據的更新

    Dash組件

    dash提供了許多使用react.js編寫的組件,這樣方便了前后端的交互,詳細見:https://dash.plot.ly/dash-core-components
    本例主要使用了:

  • Interval:固定時間刷新頁面數據
  • Dropdown:下拉菜單樣式的表單
  • Graph:用于展示使用plotly繪制的圖表
  • Callback函數

    Callback函數是有數據前后端傳輸的功能,通過Input和Output中id與項目layout中id進行關聯,一個Callback可以有很多輸入,但是只能有一個輸出。
    看下面代碼:

    @app.callback(Output('heatmap', 'figure'),[Input("dropdown1", "value"), Input('river', 'n_intervals')]) def get_heatmap(value, n):df = get_df()grouped_by_year = df.groupby('year')data = grouped_by_year.get_group(value)cross = pd.crosstab(data['weekday'], data['week'])cross.sort_index(inplace=True)trace = go.Heatmap(x=['第{}周'.format(i) for i in cross.columns],y=["星期{}".format(i+1) if i != 6 else "星期日" for i in cross.index],z=cross.values,colorscale="Greens",reversescale=True,xgap=4,ygap=5,showscale=False)layout = go.Layout(# width=len(cross.columns)*33+100,# height=335,margin=dict(l=50, r=40, t=30, b=50),xaxis=dict(showgrid=False),yaxis=dict(showgrid=False))return go.Figure(data=[trace], layout=layout)

    上面代碼會將使用plotly繪制的heatmap圖像返回到app.layout中的id為heatmap的地方,返回的形式是什么?Output('heatmap', 'figure')的第二個參數figure。
    這里Input傳入了兩個參數[Input("dropdown1", "value"), Input('river', 'n_intervals')]一個是下拉表單的value,另一個是intterval的計數值,這兩個值傳遞到get_heatmap(value, n):中。一旦Input數據發生變化變回觸發回調,對Output數據進行更改。

    • Callback函數還要另外一種使用State用于暫時保留狀態,等有Input觸發
    • 第二個參數本例中是figure,它是根據返回的內容而定,跟網頁元素相關就是children,或者也可以是html.A中的src

    html布局

    在dash的layout中使用html語言的組件進行網頁結構的布局。

    head = html.Div([html.Div(html.Img(src=info['head_img'][0], height="100%"), style={"float": "left", "height": "100%"}),html.Span("{}博客的Dashboard".format(info['author_name'][0]), className='app-title'), ], className="row header")

    上面代碼中可見:

  • html.Div:就是對應創建了一個<div></div>
  • style:就是使用style更改風格
  • className:用以關聯css
  • css載入

    網絡css:

    external_css = ["https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css","https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css", ]for css in external_css:app.css.append_css({"external_url": css})

    通過上面方法載入,也可用過html.Link。

    本地css:

    放到項目根目錄的assets文件夾中,則會自動載入。

    title修改

    dash的title等模板是默認的,可以通過下面方法進行修改:

    app.index_string = ''' <!DOCTYPE html> <html><head>{%metas%}<title>泛泛之素的Dashboard</title>{%favicon%}{%css%}</head><body>{%app_entry%}<footer>{%config%}{%scripts%}</footer></body> </html> '''

    favicon修改就是將該格式圖片放到,assets文件夾中即可。

    數據緩存

    多次使用的數據可以進行緩存,有兩種模式:

  • 寫入redis
  • 寫入本地文件
  • 具體見官網:https://dash.plot.ly/sharing-data-between-callbacks
    因為要部署在heroku,本例使用的寫到本地:

    from flask_caching import Cachecache = Cache(app.server, config={'CACHE_TYPE': 'filesystem','CACHE_DIR': 'cache-directory' })@cache.memoize(timeout=3590) def get_df():df = pd.read_sql('blogs', con=engine)df['date_day'] = df['date'].apply(lambda x: x.split(' ')[0]).astype('datetime64[ns]')df['date_month'] = df['date'].apply(lambda x: x[:7].split('-')[0] + "年" + x[:7].split('-')[-1] + "月")df['weekday'] = df['date_day'].dt.weekdaydf['year'] = df['date_day'].dt.yeardf['month'] = df['date_day'].dt.monthdf['week'] = df['date_day'].dt.weekreturn df

    timeout是緩存時間,時間一到自動釋放緩存

    運行

    使用app.run_server(debug=True, threaded=True, port=7777)運行,因為后端使用flask,基本跟flask相同,這里可以更改port,host
    等。

    注:jupyter不能使用debug模式,使用會報錯

    5 部署

    本例部署在heroku上,部署方法可以看我之前寫的文章 https://blog.csdn.net/tonydz0523/article/details/82707569
    也可以見官網:https://dash.plot.ly/deployment

    如果heroku無法訪問的話,也可部署在云主機等,也可以和你的其他flask應用部署在一起,部署方式同flask一樣。

    總結

    以上是生活随笔為你收集整理的python数据可视化:使用dash给博客制作一个dashboard的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 久国产视频 | 久久久全国免费视频 | 国产黄色片av | www.毛片| 日本一二区视频 | 天天爽av| 日韩欧美国产一区二区三区在线观看 | 激情综合网婷婷 | 色网导航站 | 一级久久久久 | 人妻精品一区二区在线 | 久久这里只有精品久久 | 久久久久久国产精品一区 | 黄色日韩 | 精品一区二区在线观看视频 | 亚洲欧美日韩精品在线 | 免费av毛片 | 欧美一级在线 | 亚天堂| 亚洲香蕉 | 久久免费播放视频 | 影音先锋男人天堂 | av免费黄色| 日韩av在线播放不卡 | 看全黄大色黄大片 | 给我看高清的视频在线观看 | 亚洲高清一区二区三区 | 九九视频网 | 国内精品999 | 伊人一区二区三区四区 | 亚洲午夜精品一区二区三区 | 国产对白羞辱绿帽vk | 日本毛片在线观看 | 亚洲九九热 | 亚洲图片88 | 人人妻人人澡人人爽人人dvd | 国产a级大片 | 国外成人性视频免费 | 韩国女主播一区二区 | 成人久久一区 | 国产亚洲综合在线 | 美女扒开下面让男人捅 | 2019日韩中文字幕mv | jzjzjzjzj亚洲成熟少妇 | 久久国产激情 | 动漫av一区二区三区 | 黄色一级二级 | 日韩美女毛片 | 岛国av一区| 欧美交| 国产亚洲欧美在线精品 | 色老汉av一区二区三区 | 麻豆传媒网 | 久久久久国产精品国产 | 久久国语 | 在线观看亚洲免费视频 | 99久久久国产精品无码免费 | 污污视频在线观看网站 | 日韩久久免费视频 | av片国产| 日韩有码中文字幕在线观看 | 91精品视频一区二区三区 | 男人天堂视频网 | 日本国产一区二区三区 | 91男女视频 | 亚洲无限av | 熟女少妇一区二区 | 91在线色| 天天天天天天操 | 亚洲欧美在线成人 | 老妇女av | cao在线| va在线视频 | 香蕉精品视频在线观看 | 国产精品久久久一区二区三区 | 久操精品| 一级视频免费观看 | 国产亚洲天堂网 | 久久久久亚洲AV成人 | 天天天天 | 91成人在线观看国产 | 成人免费福利 | 亚洲天堂国产 | 精品无码在线观看 | 97色吧| 国产精品人人做人人爽人人添 | 激情 亚洲 | 亚洲国产欧美视频 | 国产经典一区二区 | 丰满人妻一区二区三区53号 | 欧洲熟妇精品视频 | 中国特级黄色片 | 国产欧美在线看 | 亚洲国产精品女人 | 深爱激情综合 | 久久免费少妇高潮99精品 | 午夜婷婷色 | 三级视频小说 | 日韩欧美手机在线 |