Python如何畫(huà)好看的 知識(shí)圖譜!

來(lái)源 | Python爬蟲(chóng)數(shù)據(jù)分析挖掘
1
前言
最近想搞一點(diǎn)好玩的事情(技術(shù)),今天打算做一個(gè)小程序:一鍵查詢明星個(gè)人信息。(從數(shù)據(jù)抓取到知識(shí)圖譜展示,全程代碼完成原創(chuàng),不涉及調(diào)用api包)
思路:從爬取網(wǎng)頁(yè)數(shù)據(jù)(某度百科),進(jìn)行數(shù)據(jù)處理,最后通過(guò)知識(shí)圖譜圖進(jìn)行展示。
最后會(huì)將代碼開(kāi)源放在文章末尾!
下面先看演示:
圖片版

動(dòng)圖版

2
采集數(shù)據(jù)
1.分析鏈接

https://baike.baidu.com/item/劉德華/114923?fr=aladdin
鏈接上中有兩個(gè)參數(shù):
明星名字:劉德華
編號(hào):114923
編號(hào)是通過(guò)另外一個(gè)鏈接獲?。ㄎ覀兿M侵苯虞斎朊餍敲志涂梢垣@取網(wǎng)頁(yè)),因此我們需要去根據(jù)明星獲取編號(hào)!
2.獲取編號(hào)
url="https://baike.baidu.com/search/word?word=劉德華"
s = requests.Session()
response = s.get(url, headers=headers)
text = response.text

可以看到這個(gè)鏈接中獲取的數(shù)據(jù)包含編號(hào)
t_split = text.split('id="J-vars" data-lemmaid="')[1].split('" data-lemmatitle="')[0]
print(text)
這樣就可以獲取到編號(hào)(根據(jù)明星名稱就可以獲取到編號(hào))
3.解析網(wǎng)頁(yè)數(shù)據(jù)

F12查看網(wǎng)頁(yè)源代碼,可以看到左邊信息在class=basicInfo-block basicInfo-left,右邊的信息在class=basicInfo-block basicInfo-right
其中屬性在dt標(biāo)簽,值在dd標(biāo)簽。
basicInfo_left = selector.xpath('//*[@class="basicInfo-block basicInfo-left"]')[0]
dt.append(basicInfo_left.xpath('.//dt'))
dd.append(basicInfo_left.xpath('.//dd'))
basicInfo_right = selector.xpath('//*[@class="basicInfo-block basicInfo-right"]')[0]
dt.append(basicInfo_right.xpath('.//dt'))
dd.append(basicInfo_right.xpath('.//dd'))
代碼部分:
url="https://baike.baidu.com/item/劉德華/114923?fr=aladdin"
res = requests.get(url,headers=headers)
res.encoding = 'utf-8'
text = res.text
selector = etree.HTML(text)
#屬性
key = []
#值
value = []
dt =[]
dd =[]
basicInfo_left = selector.xpath('//*[@class="basicInfo-block basicInfo-left"]')[0]
dt.append(basicInfo_left.xpath('.//dt'))
dd.append(basicInfo_left.xpath('.//dd'))
basicInfo_right = selector.xpath('//*[@class="basicInfo-block basicInfo-right"]')[0]
dt.append(basicInfo_right.xpath('.//dt'))
dd.append(basicInfo_right.xpath('.//dd'))
for j in dt:
for i in j:
text = i.xpath('.//text()')
if len(text)==1:
text = text[0].replace(" ","").replace("\n","").replace("\xa0","")
else:
text = "-".join(text)
text = text.replace(" ", "").replace("\n", "").replace("\xa0", "")
key.append(text)
for j in dd:
for i in j:
text = i.xpath('.//text()')
if len(text) == 1:
text = text[0].replace(" ", "").replace("\n", "").replace("\xa0", "")
else:
text = "-".join(text)
text = text.replace(" ", "").replace("\n", "").replace("\xa0", "").replace("-", " ")
value.append(text)
for k in range(0,len(key)):
print(key[k]+":"+value[k])

3
處理數(shù)據(jù)
1.換行處理
爬取的文本中含有\xa0、換行\n、空格等,需要進(jìn)行處理
text = i.xpath('.//text()')
if len(text)==1:
text = text[0].replace(" ","").replace("\n","").replace("\xa0","")
else:
text = "-".join(text)
text = text.replace(" ", "").replace("\n", "").replace("\xa0", "")2.多值處理

像代表作品,主要成就這些有很多值,為了方便繪制知識(shí)圖譜圖,保留其中一個(gè)值就可以。
if key[k]=="代表作品" or key[k]=="主要成就":
v = value[k].split(" ")
dict = {'source': str(name_i), 'target': str(v[0]+v[1]), 'rela': str(key[k]), 'type': 'resolved'}
links.append(dict)
else:
dict= {'source': str(name_i), 'target': str(value[k]), 'rela': str(key[k]), 'type': 'resolved'}
links.append(dict)
3.數(shù)據(jù)格式處理

這個(gè)是知識(shí)圖譜要求數(shù)據(jù)格式
source表示明星,比如劉德華
target表示value,比如中國(guó)
rela表示key,比如國(guó)籍
for k in range(0,len(key)):
if key[k]=="代表作品" or key[k]=="主要成就":
v = value[k].split(" ")
dict = {'source': str(name_i), 'target': str(v[0]+v[1]), 'rela': str(key[k]), 'type': 'resolved'}
links.append(dict)
else:
dict= {'source': str(name_i), 'target': str(value[k]), 'rela': str(key[k]), 'type': 'resolved'}
links.append(dict)
4
繪制知識(shí)圖
1.后端部分
這里通過(guò)Flask框架來(lái)制作網(wǎng)頁(yè)展示
#獲取數(shù)據(jù)
@app.route('/getdata')
def getdata():
name_i = request.args.get('name')
# 采集數(shù)據(jù)
links = getlist(name_i)
#return Response(json.dumps(links), mimetype='application/json')
return render_template('index.html', linkss=json.dumps(links))
if __name__ == "__main__":
"""初始化"""
app.run(host=''+ip, port=5000,threaded=True)
其中的getlist,是爬蟲(chóng)代碼封裝的函數(shù)(完整代碼下方獲取)
用戶訪問(wèn)一下鏈接,并傳過(guò)來(lái)明星的名字
http://localhost:5000/getdata?name=劉德華
flask就調(diào)用爬蟲(chóng)程序getlist,獲取到數(shù)據(jù),然后攜帶數(shù)據(jù)linkss跳轉(zhuǎn)到index.html,展示數(shù)據(jù)。
2.網(wǎng)頁(yè)部分
var links=eval('{{linkss|safe }}');
var nodes = {};
links.forEach(function(link)
{
link.source = nodes[link.source] || (nodes[link.source] = {name: link.source});
link.target = nodes[link.target] || (nodes[link.target] = {name: link.target});
});
links接收到數(shù)據(jù)后,在進(jìn)行forEach取出進(jìn)行展示。
這里就只貼了修改改動(dòng)的部分代碼,其他的都是不需要改動(dòng),完整的html可以在下方獲取。
3.效果


5
總結(jié)


1.教大家如何爬取某度百科,其中難點(diǎn)就是如何獲取編號(hào)!
2.對(duì)爬取的數(shù)據(jù)進(jìn)行相應(yīng)的處理和格式轉(zhuǎn)化!
3.Flask的簡(jiǎn)單使用(小白入門非常適用)。
4.可視化方面,如何制作知識(shí)結(jié)構(gòu)圖(知識(shí)圖譜)。
5.本文全是干貨(涉及爬蟲(chóng)、數(shù)據(jù)處理、Flask網(wǎng)頁(yè)、知識(shí)結(jié)構(gòu)圖的繪制),推薦收藏?。?!
6.源碼:https://gitee.com/lyc96/star-visualization
