馬哥原創,淄博燒烤分析大屏,含:詞雲圖、玫瑰圖、柱形圖、折線圖、地圖等圖表,jieba分詞、snownlp情感分析、stopwords停用詞、flask網頁服務等技術。 ...
目錄
一、開發背景
您好,我是@馬哥python說 ,一枚10年程式猿。
自從2023.3月以來,"淄博燒烤"現象持續占領熱搜流量,體現了後疫情時代眾多網友對人間煙火氣的美好嚮往,本現象級事件存在一定的數據分析實踐意義。
靜態截圖:
動態演示:
【大屏演示】Python可視化輿情大屏「淄博燒烤」
二、爬蟲代碼
2.1 爬微博列表
通過m端的搜索頁面,爬取以"淄博燒烤"為關鍵詞的微博id,獲取到微博id的目的,是傳給評論爬蟲。
發送請求部分:
# 請求地址
url = 'https://m.weibo.cn/api/container/getIndex'
# 請求參數
params = {
"containerid": "100103type=60&q={}".format(v_keyword),
"page_type": "searchall",
"page": page
}
# 發送請求
r = requests.get(url, headers=headers, params=params)
註意,type=60代表"熱門",如下:
解析數據部分:
# 解析json數據
cards = r.json()["data"]["cards"]
print('微博數量:', len(cards))
for card in cards:
# 微博id
id_list = card['mblog']['id']
id_list_list.append(id_list)
至此,已經獲取到以「淄博燒烤」為關鍵詞的微博id列表 id_list_list 了。
2.2 爬微博評論
從2.1章節獲取到微博id列表之後,傳入爬取微博評論函數 get_comments
這部分爬蟲講解可移步:
【2023微博評論爬蟲】用python爬上千條微博評論,突破15頁限制!
最終,爬取到的微博評論數據,示例如下:
說明:無論微博搜索頁,還是微博評論頁,都可以自定義設置max_page,滿足自己的個性化數據量要求。
2.3 導入MySQL資料庫
最核心的三行代碼:
# 讀取csv數據
df = pd.read_csv('去重後_' + comment_file)
# 把csv數據導入MySQL資料庫
df.to_sql(name='t_zbsk', con=engine, chunksize=1000, if_exists='replace', index=False)
print('導入資料庫完成!')
用create_engine創建資料庫連接,格式為:
create_engine('資料庫類型+資料庫驅動://用戶名:密碼@資料庫IP地址/資料庫名稱')
這樣,資料庫連接就創建好了。
然後,用pandas的read_csv函數讀取csv文件。
最後,用pandas的to_sql函數,把數據存入MySQL資料庫:
- name='college_t2' #mysql資料庫中的表名
- con=engine # 資料庫連接
- index=False #不包含索引欄位
- if_exists='replace' #如果表中存在數據,就替換掉
非常方便地完成了反嚮導入,即:從csv向資料庫的導入。
這個部分的講解視頻:
僅用Python三行代碼,實現資料庫和excel之間的導入導出!
三、可視化代碼
3.1 大標題
由於pyecharts組件沒有專門用作標題的圖表,我決定靈活運用Line組件實現大標題。
首先,找到一張星空圖作為大屏背景圖:
然後,在Line組件中加入js代碼,載入背景圖:
# 設置背景圖片
line3.add_js_funcs(
"""
var img = new Image(); img.src = './static/bg2.png';
"""
)
大標題效果如下:
3.2 詞雲圖(含:載入停用詞)
繪製詞雲圖,需要先進行中文分詞。既然分詞,就要先設置停用詞,避免干擾詞影響分析結果。
這裡採用哈工大停用詞作為停用詞詞典。
# 停用詞列表
with open('hit_stopwords.txt', 'r') as f:
stopwords_list = f.readlines()
stopwords_list = [i.strip() for i in stopwords_list]
這樣,所有停用詞就存入stopwords_list這個列表裡了。
如果哈工大停用詞仍然無法滿足需求,再加入一些自定義停用詞,extend到這個列表裡:
# 加入自定義停用詞
stopwords_list.extend(
['3', '5', '不', '都', '好', '人', '吃', '都', '去', '想', '說', '還', '很', '…', 'nan', '真的', '不是',
'沒', '會', '看', '現在', '覺得', ' ', '沒有', '上', '感覺', '大', '太', '真', '哈哈哈', '火', '挖', '做',
'一下', '不能', '知道', '這種', '快'])
現在就可以愉快的繪製詞雲圖了,部分核心代碼:
wc = WordCloud(init_opts=opts.InitOpts(width='600px', height=chart_height, theme=theme_config, chart_id='wc1'))
wc.add(series_name="評論內容",
data_pair=data300,
word_gap=1,
word_size_range=[20, 70],
) # 增加數據
wc.set_global_opts(
title_opts=opts.TitleOpts(pos_left='center',
pos_top='0%',
title=v_title,
title_textstyle_opts=opts.TextStyleOpts(font_size=20, color=title_color) # 設置標題
),
tooltip_opts=opts.TooltipOpts(is_show=True), # 顯示提示
)
詞雲圖效果:
3.3 玫瑰圖(含:snownlp情感分析)
先對評論數據進行情感判定,採用snownlp技術進行情感打分及判定結果:
for comment in cmt_list:
sentiments_score = SnowNLP(comment).sentiments
if 0 <= sentiments_score < 0.2: # 情感分小於0.2,判定為極其消極
tag = '極其消極'
neg_very_count += 1
elif 0.2 <= sentiments_score < 0.4: # 情感分在0.2和0.4之間,判定為比較消極
tag = '比較消極'
neg_count += 1
elif 0.4 <= sentiments_score < 0.6: # 情感分在0.4和0.6之間,判定為中性
tag = '中性'
mid_count += 1
elif 0.6 <= sentiments_score < 0.9: # 情感分在0.6和0.9之間,判定為比較積極
tag = '比較積極'
pos_count += 1
else: # 情感分大於0.9,判定為極其積極
tag = '極其積極'
pos_very_count += 1
將情感分析結果用pandas保存到一個Excel文件里,如下:
繪製玫瑰圖,部分核心代碼:
# 畫餅圖
pie = (
Pie(init_opts=opts.InitOpts(theme=theme_config, width=chart_width, height=chart_height, chart_id='pie1'))
.add(series_name="情感分類", # 系列名稱
data_pair=[ # 添加數據
['極其積極', pos_very_count],
['比較積極', pos_count],
['中性', mid_count],
['比較消極', neg_count],
['極其消極', neg_very_count],
],
rosetype="radius", # 是否展示成南丁格爾圖
radius=["20%", "65%"], # 扇區圓心角展現數據的百分比
) # 加入數據
.set_global_opts( # 全局設置項
title_opts=opts.TitleOpts(title=v_title,
pos_left='center',
title_textstyle_opts=opts.TextStyleOpts(color=title_color, ), ), # 標題
legend_opts=opts.LegendOpts(pos_left='center', pos_top='8%', orient='horizontal',
textstyle_opts=opts.TextStyleOpts(color='white', )) # 圖例字體顏色
)
)
玫瑰圖效果:
3.4 柱形圖-TOP10關鍵詞
先根據詞雲圖部分提取出TOP10高頻詞(過濾掉停用詞之後的):
data10 = collections.Counter(result).most_common(10)
然後帶入柱形圖,部分核心代碼:
# 畫柱形圖
bar = Bar(
init_opts=opts.InitOpts(theme=theme_config, width='780px', height=chart_height,
chart_id='bar1')) # 初始化條形圖
bar.add_xaxis(x_data) # 增加x軸數據
bar.add_yaxis("高頻辭彙", y_data) # 增加y軸數據
bar.set_series_opts(label_opts=opts.LabelOpts(position="top")) # Label出現位置
bar.set_global_opts(。。。)
柱形圖效果:
3.5 折線圖-討論熱度趨勢
首先,根據評論時間統計出每天的微博評論數量:
# 按日期分組統計評論數量
df_comments['評論日期'] = df_comments['評論時間'].astype(str).str[:10] # 提取日期
grp = df_comments.groupby('評論日期')['評論內容'].count()
然後,根據統計數據畫出折線圖,部分核心代碼:
line = Line(
init_opts=opts.InitOpts(width='780px', height=chart_height, theme=theme_config, chart_id='line1')) # 實例化
line.add_xaxis(x_data) # 加入X軸數據
line.add_yaxis('討論數量', y_data, is_smooth=True,
areastyle_opts=opts.AreaStyleOpts(color=JsCode(area_color_js), opacity=1), ) # 加入Y軸數據
line.set_global_opts(。。。)
折線圖效果:
3.6 地圖-IP分佈
由於IP屬地欄位都包含"來自"兩字,先進行數據清洗,將"來自"去掉:
# 數據清洗-ip屬地
ip_count = df_comments['評論者IP歸屬地'].str.replace('來自', '')
然後統計各個IP屬地的數量,方便後續帶入地圖可視化:
# 統計各IP數量
ip_count = ip_count.value_counts()
下麵開始繪製地圖,部分核心代碼:
f_map = (
Map(init_opts=opts.InitOpts(width='600px',
height='600px',
theme=theme_config,
page_title=v_title,
chart_id='map1',
bg_color=None))
.add(series_name="評論數量",
data_pair=list(zip(loc_list, value_list)),
maptype="china", # 地圖類型
is_map_symbol_show=False)
.set_global_opts(。。。)
.set_series_opts(label_opts=opts.LabelOpts(is_show=True, font_size=8, ),
markpoint_opts=opts.MarkPointOpts(
symbol_size=[90, 90], symbol='circle'),
effect_opts=opts.EffectOpts(is_show='True', )
)
)
地圖效果,如下:
當然,地圖中的顏色,都是自己設置的十六進位顏色,可以根據自己的喜好更改。
3.7 Page組合大屏
最後,也是最關鍵的一步,把以上所有圖表組合到一起,用Page組件,並且選用DraggablePageLayout方法,即拖拽的方式,組合圖表:
# 繪製:整個頁面
page = Page(
page_title='微博熱門評論可視化分析大屏-以"淄博燒烤"為例',
layout=Page.DraggablePageLayout,
)
page.add(
# 繪製:大標題
make_title(v_title='微博熱門評論可視化分析大屏-以"淄博燒烤"為例'),
# 繪製:詞雲圖
make_wordcloud(v_title='評論內容-詞雲圖'),
# 繪製:餅圖
make_analyse_pie(v_title='情感分佈-玫瑰圖'),
# 繪製:柱形圖
make_bar(v_title='TOP10關鍵詞-柱形圖'),
# 繪製:折線圖
make_line(v_title='討論熱度趨勢-折線圖'),
# 繪製:地圖
make_map(v_title='評論IP分佈-中國地圖'),
)
page.render('大屏_臨時.html')
本代碼執行完畢後,打開臨時html併排版,排版完點擊Save Config,把json文件放到本目錄下。
再執行最後一步,調用json配置文件,生成最終大屏文件。
Page.save_resize_html(
source="大屏_臨時.html", # 源html文件
cfg_file="chart_config.json", # 配置文件
dest="大屏_最終.html" # 目標html文件
)
至此,所有代碼執行完畢,生成了最終大屏html文件。
四、彩蛋-多種顏色主題
分享一個小技巧,我設置了一鍵更換顏色主題:
# 整體主題顏色
theme_config = ThemeType.SHINE
只需更換ThemeType參數,即可實現一鍵更換主題!
4.1 INFOGRAPHIC主題
4.2 MACARONS主題
4.3 SHINE主題
4.4 WALDEN主題
4.5 WESTEROS主題
4.6 WHITE主題
4.7 WONDERLAND主題
更多顏色主題等待小伙伴去發掘!
五、技術總結
技術開發流程:
- requests 爬蟲發送請求
- json 解析返回數據
- re 正則表達式清洗文本
- pandas保存csv文件
- sqlalchemy 保存MySQL數據
- pyecharts 可視化開發
- snownlp 情感分析
- jieba 中文分詞
- pyecharts+page 組合大屏
- flask 啟動網頁服務
六、線上體驗
為了方便大家體驗可視化動態交互效果,我把此大屏部署到了伺服器,請移步:
馬哥python說 - 效果演示
七、演示視頻
效果演示視頻:
【大屏演示】Python可視化輿情大屏「淄博燒烤」
八、獲取完整源碼
附完整源碼:【可視化大屏】“淄博燒烤”熱評輿情分析大屏
我是 @馬哥python說 ,持續分享python源碼乾貨中!