“整篇文章較長,干貨很多干毅!建議收藏后宜猜,分章節(jié)閱讀∠醴辏”
一姨拥、設(shè)計方案
整體設(shè)計方案思維導(dǎo)圖:整篇文章,也將按照這個結(jié)構(gòu)來講解渠鸽。
若有重點關(guān)注部分叫乌,可點擊章節(jié)目錄直接跳轉(zhuǎn)!
二徽缚、項目背景
針對TOP250排行榜的數(shù)據(jù)憨奸,開發(fā)一套可視化數(shù)據(jù)大屏系統(tǒng),展示各維度數(shù)據(jù)分析結(jié)果凿试。
TOP250排行榜
三排宰、電影爬蟲
3.1 導(dǎo)入庫
import requests # 發(fā)送請求
from bs4 import BeautifulSoup # 解析網(wǎng)頁
import pandas as pd # 存取csv
from time import sleep # 等待時間
from sqlalchemy import create_engine # 連接數(shù)據(jù)庫
3.2 發(fā)送請求
定義一些空列表,用于臨時存儲爬取下的數(shù)據(jù):
movie_name = [] # 電影名稱
movie_url = [] # 電影鏈接
movie_star = [] # 電影評分
movie_star_people = [] # 評分人數(shù)
movie_director = [] # 導(dǎo)演
movie_actor = [] # 主演
movie_year = [] # 上映年份
movie_country = [] # 國家
movie_type = [] # 類型
short_comment = [] # 一句話短評
向網(wǎng)頁發(fā)送請求:
res = requests.get(url, headers=headers)
3.3 解析頁面
利用BeautifulSoup庫解析響應(yīng)頁面:
soup = BeautifulSoup(res.text, 'html.parser')
用BeautifulSoup的select函數(shù)那婉,(css解析的方法)編寫代碼邏輯板甘,部分核心代碼:
for movie in soup.select('.item'):
name = movie.select('.hd a')[0].text.replace('\n', '') # 電影名稱
movie_name.append(name)
url = movie.select('.hd a')[0]['href'] # 電影鏈接
movie_url.append(url)
star = movie.select('.rating_num')[0].text # 電影評分
movie_star.append(star)
star_people = movie.select('.star span')[3].text # 評分人數(shù)
star_people = star_people.strip().replace('人評價', '')
其中,需要說明的是详炬,《大鬧天宮》這部電影和其他電影頁面排版不同:所以盐类,這里特殊處理一下:
if name == '大鬧天宮 / 大鬧天宮 上下集 / The Monkey King': # 大鬧天宮,特殊處理
year0 = movie_infos.split('\n')[1].split('/')[0].strip()
year1 = movie_infos.split('\n')[1].split('/')[1].strip()
year2 = movie_infos.split('\n')[1].split('/')[2].strip()
year = year0 + '/' + year1 + '/' + year2
movie_year.append(year)
country = movie_infos.split('\n')[1].split('/')[3].strip()
movie_country.append(country)
type = movie_infos.split('\n')[1].split('/')[4].strip()
movie_type.append(type)
3.4 存儲到csv
最后痕寓,將爬取到的數(shù)據(jù)保存到csv文件中:
def save_to_csv(csv_name):
"""
數(shù)據(jù)保存到csv
:return: None
"""
df = pd.DataFrame() # 初始化一個DataFrame對象
df['電影名稱'] = movie_name
df['電影鏈接'] = movie_url
df['電影評分'] = movie_star
df['評分人數(shù)'] = movie_star_people
df['導(dǎo)演'] = movie_director
df['主演'] = movie_actor
df['上映年份'] = movie_year
df['國家'] = movie_country
df['類型'] = movie_type
df.to_csv(csv_name, encoding='utf_8_sig') # 將數(shù)據(jù)保存到csv文件
其中傲醉,把各個list賦值為DataFrame的各個列,就把list數(shù)據(jù)轉(zhuǎn)換為了DataFrame數(shù)據(jù)呻率,然后直接to_csv保存。
3.5 講解視頻
同步講解視頻:
https://www.zhihu.com/zvideo/1465578220191592448
四呻引、數(shù)據(jù)持久化存儲
然后礼仗,就可以把csv數(shù)據(jù)導(dǎo)入到MySQL數(shù)據(jù)庫,做持久化存儲了逻悠。
4.1 導(dǎo)入庫
import pandas as pd # 存取csv
from sqlalchemy import create_engine # 連接數(shù)據(jù)庫
4.2 存入MySQL
最核心的三行代碼:
# 把csv導(dǎo)入mysql數(shù)據(jù)庫
engine = create_engine('mysql+pymysql://root:123456@localhost/db_bigscreen')
df = pd.read_csv('Movie250.csv')
df.to_sql(name='t_film', con=engine, chunksize=1000, if_exists='replace', index=None)
用create_engine創(chuàng)建數(shù)據(jù)庫連接元践,格式為:
create_engine('數(shù)據(jù)庫類型+數(shù)據(jù)庫驅(qū)動://用戶名:密碼@數(shù)據(jù)庫IP地址/數(shù)據(jù)庫名稱')
這樣,數(shù)據(jù)庫連接就創(chuàng)建好了童谒。
然后单旁,用pandas的read_csv函數(shù)讀取csv文件。
最后饥伊,用pandas的to_sql函數(shù)象浑,把數(shù)據(jù)存入MySQL數(shù)據(jù)庫:
name='college_t2' #mysql數(shù)據(jù)庫中的表名
con=engine # 數(shù)據(jù)庫連接
index=False #不包含索引字段
if_exists='replace' #如果表中存在數(shù)據(jù)蔫饰,就替換掉,另外愉豺,還支持append(追加數(shù)據(jù))
非常方便地完成了反向?qū)肼ㄓ酰矗簭腸sv向數(shù)據(jù)庫的導(dǎo)入。
4.3 講解視頻
同步講解視頻:
https://www.zhihu.com/zvideo/1496218294043009024
五蚪拦、開發(fā)可視化大屏
如文章開頭的思維導(dǎo)圖所說杖剪,首先把各個子圖表開發(fā)出來,然后用pyecharts的Page組件驰贷,把這些子圖表拼裝組合起來盛嘿,形成大屏。
下面括袒,依次講解每個子圖表的實現(xiàn)次兆。
5.1 柱形圖
pyecharts官網(wǎng)-柱形圖:A Python Echarts Plotting Library built with love.
因為需要實現(xiàn)分段區(qū)間統(tǒng)計,所以先定義出一個區(qū)間對象:
# 設(shè)置分段
bins = [0, 100000, 200000, 300000, 500000, 1000000, 3000000]
# 設(shè)置標簽
labels = ['0-10w', '10w-20w', '20w-30w', '30w-50w', '50w-100w', '100w-300w']
然后箱熬,對數(shù)據(jù)進行按段切割类垦,并統(tǒng)計個數(shù):
# 按分段離散化數(shù)據(jù)
segments = pd.cut(cmt_count_list, bins, labels=labels) # 按分段切割數(shù)據(jù)
counts = pd.value_counts(segments, sort=False).values.tolist() # 統(tǒng)計個數(shù)
最后,采用pyecharts里的Bar對象城须,畫出柱形圖:
bar = Bar(
init_opts=opts.InitOpts(theme=theme_config, width="450px", height="350px", chart_id='bar_cmt2')) # 初始化條形圖
bar.add_xaxis(labels, ) # 增加x軸數(shù)據(jù)
bar.add_yaxis("評價數(shù)", counts) # 增加y軸數(shù)據(jù)
bar.set_global_opts(
legend_opts=opts.LegendOpts(pos_left='right'),
title_opts=opts.TitleOpts(title="評價數(shù)量區(qū)間分布-柱形圖", pos_left='center'), # 標題
toolbox_opts=opts.ToolboxOpts(is_show=False, ), # 不顯示工具箱
xaxis_opts=opts.AxisOpts(name="評論數(shù)", # x軸名稱
axislabel_opts=opts.LabelOpts(font_size=8)), # 字體大小
yaxis_opts=opts.AxisOpts(name="電影數(shù)量",
axislabel_opts={"rotate": 0},
splitline_opts=opts.SplitLineOpts(is_show=True,
linestyle_opts=opts.LineStyleOpts(type_='solid')),
), # y軸名稱
)
# 標記最大值
bar.set_series_opts(
markpoint_opts=opts.MarkPointOpts(data=[opts.MarkPointItem(type_="max", name="最大值"), ],
symbol_size=35) # 標記符號大小
)
bar.render("評價數(shù)分布-柱形圖.html") # 生成html文件
print('生成完畢:評價數(shù)分布-柱形圖.html')
圖表效果:5.2 餅圖
pyecharts官網(wǎng)-餅圖:A Python Echarts Plotting Library built with love.
繪制情感分布的餅圖蚤认。所以,首先要對評價數(shù)據(jù)進行情感分析糕伐。
鑒于電影評價內(nèi)容都是中文文本設(shè)計砰琢,情感分析采用snownlp技術(shù)進行。
score_list = [] # 情感評分值
tag_list = [] # 打標分類結(jié)果
pos_count = 0 # 計數(shù)器-積極
mid_count = 0 # 計數(shù)器-中性
neg_count = 0 # 計數(shù)器-消極
for comment in v_cmt_list:
tag = ''
sentiments_score = SnowNLP(comment).sentiments
if sentiments_score < 0.4: # 情感分小于0.4判定為消極
tag = '消極'
neg_count += 1
elif 0.4 <= sentiments_score <= 0.6: # 情感分在[0.4,0.6]直接判定為中性
tag = '中性'
mid_count += 1
else: # 情感分大于0.6判定為積極
tag = '積極'
pos_count += 1
score_list.append(sentiments_score) # 得分值
tag_list.append(tag) # 判定結(jié)果
df['情感得分'] = score_list
df['分析結(jié)果'] = tag_list
df.to_excel('情感判定結(jié)果.xlsx', index=None) # 把情感分析結(jié)果保存到excel文件
按照情感得分值劃分區(qū)間:
情感得分值小于0.4良瞧,判定為消極
情感得分值在0.4與0.6之間陪汽,判定為中性
情感得分值大于0.6,判定為積極
最終將結(jié)果保存到Excel文件中褥蚯,查看下:
將此結(jié)果中的數(shù)據(jù)挚冤,帶入到Pie組件中,畫出餅圖:
# 畫餅圖
pie = (
Pie(init_opts=opts.InitOpts(theme=theme_config, width="450px", height="350px", chart_id='pie1'))
.add(series_name="評價情感分布", # 系列名稱
data_pair=[['積極', pos_count], # 添加數(shù)據(jù)
['中性', mid_count],
['消極', neg_count]],
rosetype="radius", # 是否展示成南丁格爾圖
radius=["30%", "55%"], # 扇區(qū)圓心角展現(xiàn)數(shù)據(jù)的百分比赞庶,半徑展現(xiàn)數(shù)據(jù)的大小
) # 加入數(shù)據(jù)
.set_global_opts( # 全局設(shè)置項
title_opts=opts.TitleOpts(title="短評情感分布-餅圖", pos_left='center'), # 標題
legend_opts=opts.LegendOpts(pos_left='right', orient='vertical') # 圖例設(shè)置項,靠右,豎向排列
)
.set_series_opts(label_opts=opts.LabelOpts(formatter="训挡: {c}"))) # 樣式設(shè)置項
pie.render('情感分布_餅圖.html') # 生成html文件
print('生成完畢:情感分布_餅圖.html')
圖表效果:5.3 詞云圖
pyecharts官網(wǎng)-詞云圖:A Python Echarts Plotting Library built with love.
針對TOP250的電影名稱,繪制出詞云圖歧强。
先對數(shù)據(jù)做清洗操作澜薄,然后直接畫出詞云圖即可:
wc = WordCloud(init_opts=opts.InitOpts(width="450px", height="350px", theme=theme_config, chart_id='wc1'))
wc.add(series_name="電影名稱",
data_pair=data,
word_size_range=[15, 20],
width='400px', # 寬度
height='300px', # 高度
word_gap=5 # 單詞間隔
) # 增加數(shù)據(jù)
wc.set_global_opts(
title_opts=opts.TitleOpts(pos_left='center',
title="電影名稱分析-詞云圖",
title_textstyle_opts=opts.TextStyleOpts(font_size=20) # 設(shè)置標題
),
tooltip_opts=opts.TooltipOpts(is_show=True), # 不顯示工具箱
)
wc.set_series_opts(label_opts=opts.LabelOpts(is_show=True))
wc.render('電影名稱_詞云圖.html') # 生成html文件
print('生成完畢:電影名稱_詞云圖.html')
圖表效果:5.4 數(shù)據(jù)表格
pyecharts官網(wǎng)-表格:A Python Echarts Plotting Library built with love.
把排名前10的電影詳情數(shù)據(jù),展現(xiàn)到大屏上摊册,采用pyecharts里的Table組件實現(xiàn)肤京。
從MySQL數(shù)據(jù)庫讀取到數(shù)據(jù)后,直接進行繪制表格:
table = (
Table(page_title='我的表格標題', )
.add(headers=['排名', '電影名稱', '評分', '評論數(shù)', '上映年', '一句話短評'], rows=data_list, attributes={
"align": "left",
"border": False,
"padding": "20px",
"style": "background:{}; width:450px; height:350px; font-size:10px; color:#C0C0C0;padding:3px;".format(
table_color)
})
.set_global_opts(title_opts=opts.TitleOpts(title='這是表格1'))
)
table.render('電影排名TOP10_數(shù)據(jù)表格.html')
print('生成完畢:電影排名TOP10_數(shù)據(jù)表格.html')
圖表效果:5.5 漣漪散點圖
pyecharts官網(wǎng)-漣漪散點圖:A Python Echarts Plotting Library built with love.
針對電影的上映年份和評分值茅特,兩個緯度的數(shù)據(jù)忘分,繪制出漣漪散點圖(漣漪散點圖和普通散點圖的區(qū)別棋枕,就是漣漪散點圖是動態(tài)圖,圖上的每個點都在閃爍饭庞,像水面上的漣漪一樣)戒悠。
sc = (EffectScatter(init_opts=opts.InitOpts(width="450px", height="350px", theme=theme_config, chart_id='scatter1'))
.add_xaxis(xaxis_data=x_data)
.add_yaxis(
series_name="",
y_axis=y_data,
symbol_size=10,
label_opts=opts.LabelOpts(is_show=False),
)
.set_series_opts()
.set_global_opts(
# 忽略部分代碼
)
)
sc.render('評分年份分布-散點圖.html')
print('生成完畢:散點圖.html')
圖表效果:5.6 條形圖
pyecharts官網(wǎng)-條形圖:A Python Echarts Plotting Library built with love.
針對評論數(shù)最多的10個電影名稱,繪制出橫向條形圖舟山。
# 畫條形圖
bar = Bar(
init_opts=opts.InitOpts(theme=theme_config, width="450px", height="350px", chart_id='bar_cmt1')) # 初始化條形圖
bar.add_xaxis(x_data) # 增加x軸數(shù)據(jù)
bar.add_yaxis("評論數(shù)量", y_data) # 增加y軸數(shù)據(jù)
bar.reversal_axis() # 設(shè)置水平方向
bar.set_series_opts(label_opts=opts.LabelOpts(position="right")) # Label出現(xiàn)位置
bar.set_global_opts(
legend_opts=opts.LegendOpts(pos_left='right'),
title_opts=opts.TitleOpts(title="評論數(shù)TOP10作者-條形圖", pos_left='center'), # 標題
toolbox_opts=opts.ToolboxOpts(is_show=False, ), # 不顯示工具箱
xaxis_opts=opts.AxisOpts(name="評論", # x軸名稱
axislabel_opts=opts.LabelOpts(font_size=8, rotate=0),
splitline_opts=opts.SplitLineOpts(is_show=False)
),
yaxis_opts=opts.AxisOpts(name="電影", # y軸名稱
axislabel_opts=opts.LabelOpts(font_size=7, rotate=45), # y軸名稱
)
)
bar.render("評論數(shù)TOP10_條形圖.html") # 生成html文件
print('生成完畢:評論數(shù)TOP10_條形圖.html')
圖表效果:5.7 大標題
由于pyecharts組件沒有專門用作標題的圖表绸狐,我決定靈活運用Table組件實現(xiàn)大標題。即累盗,讓Table只有標題header寒矿,沒有數(shù)據(jù)行row,再針對header做一些樣式調(diào)整(字體增大等)若债,即可實現(xiàn)一行大標題符相。
table = Table()
table.add(headers=[v_title], rows=[], attributes={
"align": "center",
"border": False,
"padding": "2px",
"style": "background:{}; width:1350px; height:50px; font-size:25px; color:#C0C0C0;".format(table_color)
})
table.render('大標題.html')
print('生成完畢:大標題.html')
圖表效果:5.8 Page組合
最后,也是最關(guān)鍵的一步蠢琳,把以上所有圖表組合到一起啊终,用Page組件,并且選用DraggablePageLayout方法傲须,即拖拽的方式蓝牲,組合圖表:
# 繪制:整個頁面
page = Page(
page_title="基于Python的電影數(shù)據(jù)分析大屏",
layout=Page.DraggablePageLayout, # 拖拽方式
)
page.add(
# 增加:大標題
make_title(v_title='基于Python的電影數(shù)據(jù)分析大屏'),
# 繪制:中下方數(shù)據(jù)表格
make_table(v_df=df_table),
# 繪制:電影名稱詞云圖
filmname_wordcloud(v_str=film_all_list),
# 繪制:TOP10評論數(shù)-條形圖
make_top10_comment_bar(v_df=df),
# 繪制情感分布餅圖
make_analyse_pie(v_cmt_list=comment_all_list),
# 繪制:評價數(shù)分段統(tǒng)計-柱形圖
make_cmt_count_bar(v_df=df),
# 繪制:散點圖
make_scatter(x_data=year_list, y_data=score_list)
)
page.render('大屏_臨時.html') # 執(zhí)行完畢后,打開臨時html并排版,排版完點擊Save Config,把json文件放到本目錄下
print('生成完畢:大屏_臨時.html')
本代碼執(zhí)行完畢后,打開臨時html并排版,排版完點擊SaveConfig泰讽,把json文件放到本目錄下例衍。
再執(zhí)行最后一步,調(diào)用json配置文件已卸,生成最終大屏文件佛玄。
# 執(zhí)行之前,請確保:1、已經(jīng)把json文件放到本目錄下 2累澡、把json中的title和table的id替換掉
Page.save_resize_html(
source="大屏_臨時.html",
cfg_file="chart_config.json",
dest="大屏_最終_0426.html"
)
拖拽過程的演示視頻:
https://www.zhihu.com/zvideo/1502249430140616704
至此梦抢,所有代碼執(zhí)行完畢,生成了最終大屏html文件愧哟。
六惑申、彩蛋-多種主題
為了實現(xiàn)不同顏色主題的大屏可視化效果,我開發(fā)了一個實現(xiàn)邏輯翅雏,只需修改一個參數(shù),即可展示不同顏色主題人芽。
全局設(shè)置主題顏色
theme_config = ThemeType.CHALK # 顏色方案
由于Table組件是不能設(shè)置顏色主題的望几,所以我手寫了一個邏輯(用取色器獲取的RGB值,又轉(zhuǎn)成十六進制的顏色S┨)橄抹,如下:
# 表格和標題的顏色
table_color = ""
if theme_config == ThemeType.DARK:
table_color = '#333333'
elif theme_config == ThemeType.CHALK:
table_color = '#293441'
elif theme_config == ThemeType.PURPLE_PASSION:
table_color = '#5B5C6E'
elif theme_config == ThemeType.ROMANTIC:
table_color = '#F0E8CD'
elif theme_config == ThemeType.ESSOS:
table_color = '#FDFCF5'
else:
table_color = ''
最終實現(xiàn)了多種顏色主題靴迫,包含以下。
6.1 CHALK主題
6.2 PURPLE主題
6.3 ESSOS主題
6.4 ROMANTIC主題
6.5 DARK主題
通過5種主題顏色楼誓,展示同一個大屏效果玉锌,有被炫到嘛?
七疟羹、拖拽演示視頻
拖拽過程演示視頻:
https://www.zhihu.com/zvideo/1502249430140616704
八主守、全流程講解視頻
全流程講解:
https://www.zhihu.com/zvideo/1503013679826690048
by 馬哥python說