Python Flask实现微博单用户画像生成器

发布 : 2017-06-03 分类 : Python 浏览 :
1
2
3
4
5
Flask是Django之外用Python实现的另一优秀Web框架

相对于功能全面的Django,Flask以自由、灵活著称

在开发一些小应用的时候,使用Django会有"杀鸡用牛刀"的感觉,而使用Flask就非常合适

开发步骤

1
2
3
4
5
(1)抓取微博用户数据

(2)分析数据,生成用户画像

(3)网站实现,美化界面

1.微博抓取

1
2
3
4
5
6
7
8
9
10
11
12
13
本例数据来源于爬取新浪微博移动端(m.weibo.cn)的数据

"发现"中搜索"迪丽热巴",点击进入她的主页;

开始分析请求报文, 右击打开调试窗口,选择调试窗口的"网络(network)"标签

选择"Preserve Log",刷新页面

分析各条请求过程可以发现博文的数据是从

https://m.weibo.cn/api/container/getIndex?XXX 类似的地址中得到的

其主要参数为type(固定值)、value(博主ID)、containerid(标识,请求中返回)、page(页码)

Markdown

1.1.爬取博文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# -*- coding: utf-8 -*-
import requests
from time import sleep


# 定义获取博主信息的函数

def get_user_info(page):
# 发送请求
# result = requests.get('https://m.weibo.cn/api/container/getIndex?uid=1669879400&luicode=10000011&lfid=1076031669879400&featurecode=20000320&type=all&containerid=1076031669879400&page=3')

result = requests.get(
'https://m.weibo.cn/api/container/getIndex?uid=1669879400&luicode=10000011&lfid=1076031669879400&featurecode=20000320&type=all&containerid=1076031669879400&page={}'.format(
page))
print(result.json())
json_data = result.json()
userinfo = {
'name': json_data['cards'][1]['mblog']['user']['screen_name'], # 获取用户名称
'description': json_data['cards'][1]['mblog']['user']['description'], # 获取用户描述
'follow_count': json_data['cards'][1]['mblog']['user']['follow_count'], # 获取关注数
'followers_count': json_data['cards'][1]['mblog']['user']['followers_count'], # 获取粉丝数
'profile_image_url': json_data['cards'][1]['mblog']['user']['profile_image_url'], # 获取头像
'verified_reason': json_data['cards'][1]['mblog']['user']['verified_reason'], # 认证信息
'containerid': json_data['cardlistInfo']['containerid'] # 此字段在获取博文中需要
}
print(userinfo)


# 获取迪丽热巴的信息
get_user_info(1)

返回的信息

Markdown

可以使用谷歌浏览器插件postman分析返回的json数据

Markdown

1.2.获取迪丽热巴所有博文信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 获取迪丽热巴的信息
# get_user_info(1)
def get_all_post(uid, containerid, pages):
# 从第一页开始
page = 0
# 这个用来存放博文列表
posts = []
# while True:
for i in range(page, pages):
# 请求博文列表
result = requests.get(
'https://m.weibo.cn/api/container/getIndex?uid=' + uid + '&luicode=10000011&lfid=1076031669879400&featurecode=20000320&type=all&containerid=' + containerid + '&page={}'.format(
i))
json_data = result.json()

# 当博文获取完毕,退出循环
if not json_data['cards']:
break

# 循环将新的博文加入列表
for i in json_data['cards']:
posts.append(i['mblog']['text'])
# print(i['mblog']['text'])

# 停顿半秒,避免被反爬虫
sleep(0.5)

# page += 1

return posts


posts = get_all_post('1669879400', '1076031669879400', 10)

# 查看博文条数
# print(len(posts))

# 显示前10个
print(posts[:10])

用户数据已准备就绪

Markdown

2.生成用户画像

2.1.提取关键词

pip安装jieba分词

1
pip3 install -i https://pypi.douban.com/simple/ jieba

Markdown

pip安装html2text

1
pip3 install -i https://pypi.douban.com/simple/ html2text

Markdown

1
从博文列表中提取出关键字,分析出博主的发表的热词
1
2
3
4
5
6
7
8
9
10
11
12
import jieba.analyse
from html2text import html2text

content = '\n'.join([html2text(i) for i in posts])

# 这里使用jieba的textrank提取出1000个关键词及其比重
result = jieba.analyse.textrank(content, topK=1000, withWeight=True)

# 生成关键词比重字典
keywords = dict()
for i in result:
keywords[i[0]] = i[1]

Markdown

2.2.生成词语图

pip安装numpy

1
pip3 install -i https://pypi.douban.com/simple/ numpy

pip安装matplotlib

1
pip3 install -i https://pypi.douban.com/simple/ matplotlib

pip安装wordcloud

1
pip3 install -i https://pypi.douban.com/simple/ wordcloud
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from PIL import Image, ImageSequence
import numpy as np
import matplotlib.pyplot as plt
from wordcloud import WordCloud, ImageColorGenerator

# 初始化图片
image = Image.open('./resourse/美女.png')
graph = np.array(image)

# 生成云图,这里需要注意的是WordCloud默认不支持中文,所以这里需要加载中文黑体字库
wc = WordCloud(font_path='./resourse/simhei.ttf',
background_color='white', max_words=300, mask=graph)
wc.generate_from_frequencies(keywords)
image_color = ImageColorGenerator(graph)
# 显示图片
plt.imshow(wc)
plt.imshow(wc.recolor(color_func=image_color))
plt.axis("off") # 关闭图像坐标系
plt.show()

准备png图片

Markdown

词云图生成效果

Markdown

3.实现Flask应用

1
开发Flask不像Django那么复杂,小应用几个文件就可以完成

3.1.安装

使用pip安装flask

1
pip3 install -i https://pypi.douban.com/simple/ flask

Markdown

3.2.实现应用逻辑

1
一个Flask应用就是一个Flask类,由route函数控制它的url请求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# -*- coding: utf-8 -*-
from flask import Flask
import requests
from time import sleep
import jieba.analyse
from html2text import html2text
from PIL import Image, ImageSequence
import numpy as np
import matplotlib.pyplot as plt
from wordcloud import WordCloud, ImageColorGenerator
from collections import OrderedDict
from flask import render_template, request

# 创建一个Flask应用
app = Flask(__name__)


#####################################
# 微博相关函数 #

# 定义获取博主信息的函数
# 参数uid为博主的id

# 定义获取博主信息的函数
def get_user_info(page):
# 发送请求
# result = requests.get('https://m.weibo.cn/api/container/getIndex?uid=1669879400&luicode=10000011&lfid=1076031669879400&featurecode=20000320&type=all&containerid=1076031669879400&page=3')

result = requests.get(
'https://m.weibo.cn/api/container/getIndex?uid=1669879400&luicode=10000011&lfid=1076031669879400&featurecode=20000320&type=all&containerid=1076031669879400&page={}'.format(
page))
print(result.json())
json_data = result.json()
# 获取性别,微博中m表示男性,f表示女性
if json_data['cards'][1]['mblog']['user']['gender'] == 'm':
gender = '男'
elif json_data['cards'][1]['mblog']['user']['gender'] == 'f':
gender = '女'
else:
gender = '未知'
userinfo = {
'name': json_data['cards'][1]['mblog']['user']['screen_name'], # 获取用户名称
'gender': gender,
'description': json_data['cards'][1]['mblog']['user']['description'], # 获取用户描述
'follow_count': json_data['cards'][1]['mblog']['user']['follow_count'], # 获取关注数
'followers_count': json_data['cards'][1]['mblog']['user']['followers_count'], # 获取粉丝数
'profile_image_url': json_data['cards'][1]['mblog']['user']['profile_image_url'], # 获取头像
'verified_reason': json_data['cards'][1]['mblog']['user']['verified_reason'], # 认证信息
'containerid': json_data['cardlistInfo']['containerid'] # 此字段在获取博文中需要
}
return userinfo


# 获取迪丽热巴的信息
# get_user_info(1)
def get_all_post(uid, containerid, pages):
# 从第一页开始
page = 0
# 这个用来存放博文列表
posts = []
while True:
# for i in range(page, pages):
# 请求博文列表
result = requests.get(
'https://m.weibo.cn/api/container/getIndex?uid=' + uid + '&luicode=10000011&lfid=1076031669879400&featurecode=20000320&type=all&containerid=' + containerid + '&page={}'.format(
page))
json_data = result.json()

# 当博文获取完毕,退出循环
if not json_data['cards']:
break

# 循环将新的博文加入列表
for i in json_data['cards']:
posts.append(i['mblog']['text'])
# print(i['mblog']['text'])

# 停顿半秒,避免被反爬虫
sleep(0.5)

page += 1

return posts


# posts = get_all_post('1669879400', '1076031669879400', 10)

# 查看博文条数
# print(len(posts))

# 显示前10个
# post = posts[:20]


##############################33
## 云图相关函数
# 生成云图
def generate_personas(uid, data_list):
content = '\n'.join([html2text(i) for i in data_list])
# print(content)

# 使用jieba的textrank提取出300个关键词及比重
result = jieba.analyse.textrank(content, topK=1000, withWeight=True)

# 生成关键词比重字典
keywords = dict()
for i in result:
print(i[0], i[1])
keywords[i[0]] = i[1]

# 初始化图片
image = Image.open('./resourse/dili.png')
graph = np.array(image)

# 生成云图,这里需要注意的是WordCloud默认不支持中文,所以这里需要加载中文黑体字库
wc = WordCloud(font_path='./resourse/simhei.ttf',
background_color='white', max_words=300, mask=graph)
wc.generate_from_frequencies(keywords)
image_color = ImageColorGenerator(graph)
# 显示图片
plt.imshow(wc)
plt.imshow(wc.recolor(color_func=image_color))
plt.axis("off") # 关闭图像坐标系
plt.show()
dest_img = './resourse/{}.png'.format(uid)
plt.savefig(dest_img)
return dest_img

#######################################
# 定义路由
# 指定根路径请求的响应函数
@app.route('/', methods=['GET', 'POST'])
def index():
# 初始化模版数据为空
userinfo = {}
# 如果是一个Post请求,并且有微博用户id,则获取微博数据并生成相应云图
# request.method的值为请求方法
# request.form既为提交的表单
if request.method == 'POST' and request.form.get('uid'):
uid = request.form.get('uid')
print(uid)
page = 0
userinfo = get_user_info(page)
posts = get_all_post(uid, userinfo['containerid'],page)
dest_img = generate_personas(uid, posts)
userinfo['personas'] = dest_img
return render_template('index.html', **userinfo)


if __name__ == '__main__':
app.run()

3.3.3.模版开发

1
2
3
4
5
6
7
模版需要有一个输入的表单和用户信息展示,基于Jinja2模版引擎

熟悉Django模版的应该可以很快上手,流程也和Django类型

在项目根目录下

新建一个名为templates的文件夹并新建一个名为index.html的文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="../css/style.css">
<title>Python Flask实现微博单用户画像生成器</title>
</head>
<body>
<!--提交微博id的表单-->
<div>
<form action="/" method="post" id="search-form">
<input type="text" name="uid" class="search" value="1669879400">
<input type="submit" class="submit" value="生成画像">
</form>
</div>
<!--下面是用户的展示信息-->
<!--使用了模版的if语法,如果有才展示这块内容-->

</body>
</html>
1
然后浏览器打开http://127.0.0.1:5000地址,观察效果

Markdown

Markdown

Markdown

本文作者 : Matrix
原文链接 : https://matrixsparse.github.io/2017/06/03/Python Falsk实现微博单用户画像生成器/
版权声明 : 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!

知识 & 情怀 | 二者兼得

微信扫一扫, 向我投食

微信扫一扫, 向我投食

支付宝扫一扫, 向我投食

支付宝扫一扫, 向我投食

留下足迹