Flask之微博單用戶畫像生成器
Flask是Django之外用Python實現的另一優秀Web框架。相對於功能全面的Django,Flask以自由、靈活著稱。在開發一些小應用的時候,使用Django會有「殺雞用牛刀」的趕腳,而使用Flask就非常合適。本文將使用Flask開發一個微博用戶畫像的生成器,最後效果如下:
開發步驟如下:
- 抓取微博用戶數據;
- 分析數據,生成用戶畫像;
- 網站實現,美化界面。
一、微博抓取
這裡使用移動端的微博(http://m.weibo.cn),以為例。本教程使用chrome瀏覽器進行調試。
- 在「發現」中搜索「古力娜扎」,點擊進入她的主頁;
- 開始分析請求報文, 右擊打開調試窗口,選擇調試窗口的"網路(network)"標籤;
- 選擇"Preserve Log",刷新頁面;
- 分析各條請求過程可以發現博文的數據是從https://m.weibo.cn/api/container/getIndex?XXX 類似的地址中得到的。其主要參數為type(固定值)、value(博主ID)、containerid(標識,請求中返回)、page(頁碼)
下面開始實現爬取博文的代碼。
# 導入相關庫nimport requestsnfrom time import sleepn# 定義獲取博主信息的函數n# 參數uid為博主的idnndef get_user_info(uid):n# 發送請求n result = requests.get(https://m.weibo.cn/api/container/getIndex?type=uid&value={}n .format(uid))n json_data = result.json() # 獲取繁華信息中json內容n userinfo = {n name: json_data[userInfo][screen_name], # 獲取用戶頭像n description: json_data[userInfo][description], # 獲取用戶描述n follow_count: json_data[userInfo][follow_count], # 獲取關注數n followers_count: json_data[userInfo][followers_count], # 獲取粉絲數n profile_image_url: json_data[userInfo][profile_image_url], # 獲取頭像n verified_reason: json_data[userInfo][verified_reason], # 認證信息n containerid: json_data[tabsInfo][tabs][1][containerid] # 此欄位在獲取博文中需要n }nn# 獲取性別,微博中m表示男性,f表示女性nif json_data[userInfo][gender] == m:n gender = 男nelif json_data[userInfo][gender] == f:n gender = 女nelse:n gender = 未知n userinfo[gender] = gendernreturn userinfon# 獲取古力娜扎信息nuserinfo = get_user_info(1350995007)n# 信息如下nuserinfon{containerid: 1076031350995007,n description: 工作請聯繫:nazhagongzuo@163.com,n follow_count: 529,n followers_count: 12042995,n name: 我是娜扎,n profile_image_url: https://tvax2.sinaimg.cn/crop.0.0.1242.1242.180/50868c3fly8fevjzsp2j4j20yi0yi419.jpg,n verified_reason: 演員,代表作《擇天記》}n
In [33]:
# 循環獲取所有博文nndef get_all_post(uid, containerid):n# 從第一頁開始n page = 0n# 這個用來存放博文列表n posts = []nwhile True:n# 請求博文列表n result = requests.get(https://m.weibo.cn/api/container/getIndex?type=uid&value={}&containerid={}&page={}n .format(uid, containerid, page))n json_data = result.json()nn# 當博文獲取完畢,退出循環nif not json_data[cards]:nbreaknn# 循環將新的博文加入列表nfor i in json_data[cards]:n posts.append(i[mblog][text])nn# 停頓半秒,避免被反爬蟲n sleep(0.5)nn# 跳轉至下一頁n page += 1nn# 返回所有博文nreturn postsnposts = get_all_post(1350995007, 1076031350995007)n# 查看博文條數nlen(posts)n1279n# 顯示前3個nposts[:3]n
至此,用戶的數據已準備就緒,接下來開始生成用戶畫像。
二、生成用戶畫像
1.提取關鍵詞
這裡從博文列表中提取出關鍵字,分析出博主的發表的熱詞
import jieba.analysenfrom html2text import html2textnncontent = n.join([html2text(i) for i in posts])nn# 這裡使用jieba的textrank提取出1000個關鍵詞及其比重nresult = jieba.analyse.textrank(content, topK=1000, withWeight=True)nn# 生成關鍵詞比重字典nkeywords = dict()nfor i in result:n keywords[i[0]] = i[1]n
2.生成詞雲圖
from PIL import Image, ImageSequencenimport numpy as npnimport matplotlib.pyplot as pltnfrom wordcloud import WordCloud, ImageColorGeneratornn# 初始化圖片nimage = Image.open(./static/images/personas.png)ngraph = np.array(image)nn# 生成雲圖,這裡需要注意的是WordCloud默認不支持中文,所以這裡需要載入中文黑體字型檔nwc = WordCloud(font_path=./fonts/simhei.ttf,n background_color=white, max_words=300, mask=graph)nwc.generate_from_frequencies(keywords)nimage_color = ImageColorGenerator(graph)n# 顯示圖片nplt.imshow(wc)nplt.imshow(wc.recolor(color_func=image_color))nplt.axis("off") # 關閉圖像坐標系nplt.show()n
三、實現Flask應用
開發Flask不像Django那麼複雜,小應用幾個文件就可以完成。步驟如下:
1. 安裝
使用pip安裝flask,命令如下:
$ pip install flaskn
2.實現應用邏輯
簡單來說,一個Flask應用就是一個Flask類,由route函數控制它的url請求。代碼實現如下:
# app.pynnnfrom flask import Flasknimport requestsnfrom PIL import Image, ImageSequencenimport numpy as npnimport matplotlib.pyplot as pltnfrom wordcloud import WordCloud, ImageColorGeneratornimport jieba.analysenfrom html2text import html2textnfrom time import sleepnfrom collections import OrderedDictnfrom flask import render_template, requestnn# 創建一個Flask應用napp = Flask(__name__)nnn##################################n# 微博相關函數 #nn# 定義獲取博主信息的函數n# 參數uid為博主的idnndef get_user_info(uid):n# 發送請求n result = requests.get(https://m.weibo.cn/api/container/getIndex?type=uid&value={}n .format(uid))n json_data = result.json() # 獲取繁華信息中json內容n# 獲取性別,微博中m表示男性,f表示女性n if json_data[userInfo][gender] == m:n gender = 男n elif json_data[userInfo][gender] == f:n gender = 女n else:n gender = 未知nn userinfo = OrderedDict()n userinfo[昵稱] = json_data[userInfo][screen_name] # 獲取用戶頭像n userinfo[性別] = gender # 性別n userinfo[關注數] = json_data[userInfo][follow_count] # 獲取關注數n userinfo[粉絲數] = json_data[userInfo][followers_count] # 獲取粉絲數n userinfo[認證信息] = json_data[userInfo][verified_reason] # 獲取粉絲數n userinfo[描述] = json_data[userInfo][description] # 獲取粉絲數n data = {n profile_image_url: json_data[userInfo][profile_image_url], # 獲取頭像n containerid: json_data[tabsInfo][tabs][1][containerid], # 此欄位在獲取博文中需要n userinfo: <br>.join([{}:{}.format(k, v) for (k,v) in userinfo.items()])n }nn return datannn# 循環獲取所有博文nndef get_all_post(uid, containerid):n# 從第一頁開始n page = 0n# 這個用來存放博文列表n posts = []n while True:n# 請求博文列表n result = requests.get(https://m.weibo.cn/api/container/getIndex?type=uid&value={}&containerid={}&page={}n .format(uid, containerid, page))n json_data = result.json()nn# 當博文獲取完畢,退出循環n if not json_data[cards]:n breaknn# 循環將新的博文加入列表n for i in json_data[cards]:n posts.append(i[mblog][text])nn# 停頓半秒,避免被反爬蟲n sleep(0.5)nn# 跳轉至下一頁n page += 1nn# 返回所有博文n return postsnnn##############################n## 雲圖相關函數nn# 生成雲圖ndef generate_personas(uid, data_list):n content = <br>.join([html2text(i) for i in data_list])nn# 這裡使用jieba的textrank提取出1000個關鍵詞及其比重n result = jieba.analyse.textrank(content, topK=1000, withWeight=True)nn# 生成關鍵詞比重字典n keywords = dict()n for i in result:n keywords[i[0]] = i[1]nn# 初始化圖片n image = Image.open(./static/images/personas.png)n graph = np.array(image)nn# 生成雲圖,這裡需要注意的是WordCloud默認不支持中文,所以這裡需要載入中文黑體字型檔n wc = WordCloud(font_path=./static/fonts/simhei.ttf,n background_color=white, max_words=300, mask=graph)n wc.generate_from_frequencies(keywords)n image_color = ImageColorGenerator(graph)n plt.imshow(wc)n plt.imshow(wc.recolor(color_func=image_color))n plt.axis("off") # 關閉圖像坐標系n dest_img = ./static/personas/{}.png.format(uid)n plt.savefig(dest_img)n return dest_imgnnn#######################################n# 定義路由n# 指定根路徑請求的響應函數n@app.route(/, methods=[GET, POST])ndef index():n# 初始化模版數據為空n userinfo = {}n# 如果是一個Post請求,並且有微博用戶id,則獲取微博數據並生成相應雲圖n# request.method的值為請求方法n# request.form既為提交的表單n if request.method == POST and request.form.get(uid):n uid = request.form.get(uid)n userinfo = get_user_info(uid)n posts = get_all_post(uid, userinfo[containerid])n dest_img = generate_personas(uid, posts)n userinfo[personas] = dest_imgn return render_template(index.html, **userinfo)nnnif __name__ == __main__:n app.run()n
以上就是全部的代碼,簡單吧?當然,單文件結構只適合小的應用,隨著功能和代碼量的增加,還是需要把代碼分離中不同的文件結構中以便開發和維護。最後,還差一個頁面的模版文件。
3.模版開發
模版需要有一個輸入的表單和用戶信息展示,基於Jinja2模版引擎。熟悉Django模版的應該可以很快上手,流程也和Django類型,在項目根目錄下建一個名為templates的文件夾並新建一個名為index.html的文件,代碼如下:
<!DOCTYPE html>n<html>n<head>n <meta charset="UTF-8">n <link rel="stylesheet" type="text/css" href="./static/css/style.css">n <title>Flask之微博單用戶畫像生成器</title>n</head>n<body>n<!--提交微博id的表單-->n<div>n <form action="/" method="post" id="search-form">n <input type="text" name="uid" class="search" placeholder="微博用戶ID">n <input type="submit" class="submit" value="生成畫像">n </form>n</div>n<!--下面是用戶的展示信息-->n<!--使用了模版的if語法,如果有才展示這塊內容-->nn</body>n</html>n
這樣,應用實現完畢,項目結構如下:
$ tree .nweibo_personasn├── app.pyn├── staticn│ ├── cssn│ │ └── style.cssn│ ├── fontsn│ │ └── simhei.ttfn│ └── imagesn│ └── personas.pngn└── templatesn └── index.htmln
進入項目文件夾,啟動項目:
$ python app.pyn* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)n
然後瀏覽器打開http://127.0.0.1:5000 地址就可以看到本教程最上面的效果。
以上只是一個初步實現,還有很多需要完善的地方。比如,如果發布的博文比較多時,獲取時間比較長,可以考慮加個緩存,存儲已獲取的用戶,避免重複請求,前端也可以加個loading效果。本教程展示的只是單用戶,後面也可以批量獲取用戶信息,生成一個群體的用戶畫像。
作者:Walker
出處:Flask之微博單用戶畫像生成器公眾號:Python愛好者社區(微信ID:python_shequ)小編個人微信:tsdatajob ,來不急回復的,可以加小編微信溝通,謝謝。
推薦閱讀:
※淺談風控領域中的用戶畫像
※用戶畫像之標籤權重演算法
※揭秘!一個節日是這樣誕生的,用戶畫像在營銷的實戰應用
※mongo集群可以用來進行海量數據分析嗎?