python 用户画像(python实现用户画像)

Flask是Django之外用Python实现的另一优秀Web框架

今天用它

Flask以自由、灵活著称。在开发一些小应用的时候,使用Django会有“杀鸡用牛刀”的赶脚,而使用Flask就非常合适。本文将使用Flask开发一个微博用户画像的生成器,最后效果如下:

python 用户画像(python实现用户画像)

开发步骤如下:

  1. 抓取微博用户数据;
  2. 分析数据,生成用户画像;
  3. 网站实现,美化界面。

一、微博抓取

这里使用移动端的微博(m.weibo.cn),以为例。本教程使用chrome浏览器进行调试。

  1. 在“发现”中搜索“古力娜扎”,点击进入她的主页;
  2. 开始分析请求报文, 右击打开调试窗口,选择调试窗口的"网络(network)"标签;
  3. 选择"Preserve Log",刷新页面;
  4. 分析各条请求过程可以发现博文的数据是从https://m.weibo.cn/api/container/getIndex?XXX 类似的地址中得到的。其主要参数为type(固定值)、value(博主ID)、containerid(标识,请求中返回)、page(页码)

python 用户画像(python实现用户画像)

下面开始实现爬取博文的代码。

# 导入相关库<p>import requests</p>

from time import sleep

# 定义获取博主信息的函数<p># 参数uid为博主的id</p><p>defget_user_info(uid):</p><p> # 发送请求</p><p> result = requests.get('https://m.weibo.cn/api/container/getIndex?type=uid&value={}'</p><p> .format(uid))</p><p> json_data = result.json() # 获取繁华信息中json内容</p><p> userinfo = {</p><p> 'name': json_data['userInfo']['screen_name'], # 获取用户头像</p><p> 'description': json_data['userInfo']['description'], # 获取用户描述</p><p> 'follow_count': json_data['userInfo']['follow_count'], # 获取关注数</p><p> 'followers_count': json_data['userInfo']['followers_count'], # 获取粉丝数</p><p> 'profile_image_url': json_data['userInfo']['profile_image_url'], # 获取头像</p><p> 'verified_reason': json_data['userInfo']['verified_reason'], # 认证信息</p><p> 'containerid': json_data['tabsInfo']['tabs'][1]['containerid'] # 此字段在获取博文中需要</p><p> }</p><p> # 获取性别,微博中m表示男性,f表示女性</p><p> if json_data['userInfo']['gender'] == 'm':</p><p> gender = '男'</p><p> elif json_data['userInfo']['gender'] == 'f':</p><p> gender = '女'</p><p> else:</p><p> gender = '未知'</p><p> userinfo['gender'] = gender</p>

return userinfo

# 获取古力娜扎信息

userinfo = get_user_info('1350995007')

# 信息如下

userinfo

{'containerid': '1076031350995007',<p>'description': '工作请联系:nazhagongzuo@163.com',</p><p>'follow_count': 529,</p><p>'followers_count': 12042995,</p><p>'name': '我是娜扎',</p><p>'profile_image_url': 'https://tvax2.sinaimg.cn/crop.0.0.1242.1242.180/50868c3fly8fevjzsp2j4j20yi0yi419.jpg',</p>

'verified_reason': '演员,代表作《择天记》'}

In [33]:

# 循环获取所有博文<p>defget_all_post(uid,containerid):</p><p> # 从第一页开始</p><p> page = 0</p><p> # 这个用来存放博文列表</p><p> posts = []</p><p> while True:</p><p> # 请求博文列表</p><p> result = requests.get('https://m.weibo.cn/api/container/getIndex?type=uid&value={}&containerid={}&page={}'</p><p> .format(uid, containerid, page))</p><p> json_data = result.json()</p><p> # 当博文获取完毕,退出循环</p><p> if not json_data['cards']:</p><p> break</p><p> # 循环将新的博文加入列表</p><p> for i in json_data['cards']:</p><p> posts.append(i['mblog']['text'])</p><p> # 停顿半秒,避免被反爬虫</p><p> sleep(0.5)</p><p> # 跳转至下一页</p><p> page += 1</p><p> # 返回所有博文</p>

return posts

posts = get_all_post('1350995007', '1076031350995007')
# 查看博文条数

len(posts)

1279
# 显示前3个

posts[:3]

python 用户画像(python实现用户画像)

至此,用户的数据已准备就绪,接下来开始生成用户画像。

二、生成用户画像

1.提取关键词

这里从博文列表中提取出关键字,分析出博主的发表的热词

import jieba.analyse<p>from html2text import html2text</p><p>content = 'n'.join([html2text(i) for i in posts])</p><p># 这里使用jieba的textrank提取出1000个关键词及其比重</p><p>result = jieba.analyse.textrank(content, topK=1000, withWeight=True)</p><p># 生成关键词比重字典</p><p>keywords = dict()</p><p>for i in result:</p>

keywords[i[0]] = i[1]

2.生成词云图

from PIL import Image, ImageSequence<p>import numpy as np</p><p>import matplotlib.pyplot as plt</p><p>from wordcloud import WordCloud, ImageColorGenerator</p><p># 初始化图片</p><p>image = Image.open('./static/images/personas.png')</p><p>graph = np.array(image)</p><p># 生成云图,这里需要注意的是WordCloud默认不支持中文,所以这里需要加载中文黑体字库</p><p>wc = WordCloud(font_path='./fonts/simhei.ttf',</p><p> background_color='white', max_words=300, mask=graph)</p><p>wc.generate_from_frequencies(keywords)</p>

image_color = ImageColorGenerator(graph)

# 显示图片<p>plt.imshow(wc)</p><p>plt.imshow(wc.recolor(color_func=image_color))</p><p>plt.axis("off") # 关闭图像坐标系</p>

plt.show()

python 用户画像(python实现用户画像)

三、实现Flask应用

开发Flask不像Django那么复杂,小应用几个文件就可以完成。步骤如下:

1. 安装

使用pip安装flask,命令如下:

$ pip install flask

2.实现应用逻辑

简单来说,一个Flask应用就是一个Flask类,由route函数控制它的url请求。代码实现如下:

# app.py<p>from flask import Flask</p><p>import requests</p><p>from PIL import Image, ImageSequence</p><p>import numpy as np</p><p>import matplotlib.pyplot as plt</p><p>from wordcloud import WordCloud, ImageColorGenerator</p><p>import jieba.analyse</p><p>from html2text import html2text</p><p>from time import sleep</p><p>from collections import OrderedDict</p><p>from flask import render_template, request</p><p># 创建一个Flask应用</p><p>app = Flask(__name__)</p><p>##################################</p><p># 微博相关函数 #</p><p># 定义获取博主信息的函数</p><p># 参数uid为博主的id</p><p>def get_user_info(uid):</p><p> # 发送请求</p><p> result = requests.get('https://m.weibo.cn/api/container/getIndex?type=uid&value={}'</p><p> .format(uid))</p><p> json_data = result.json() # 获取繁华信息中json内容</p><p> # 获取性别,微博中m表示男性,f表示女性</p><p> if json_data['userInfo']['gender'] == 'm':</p><p> gender = '男'</p><p> elif json_data['userInfo']['gender'] == 'f':</p><p> gender = '女'</p><p> else:</p><p> gender = '未知'</p><p> userinfo = OrderedDict()</p><p> userinfo['昵称'] = json_data['userInfo']['screen_name'] # 获取用户头像</p><p> userinfo['性别'] = gender # 性别</p><p> userinfo['关注数'] = json_data['userInfo']['follow_count'] # 获取关注数</p><p> userinfo['粉丝数'] = json_data['userInfo']['followers_count'] # 获取粉丝数</p><p> userinfo['认证信息'] = json_data['userInfo']['verified_reason'] # 获取粉丝数</p><p> userinfo['描述'] = json_data['userInfo']['description'] # 获取粉丝数</p><p> data = {</p><p> 'profile_image_url': json_data['userInfo']['profile_image_url'], # 获取头像</p><p> 'containerid': json_data['tabsInfo']['tabs'][1]['containerid'], # 此字段在获取博文中需要</p><p> 'userinfo': '<br>'.join(['{}:{}'.format(k, v) for (k,v) in userinfo.items()])</p><p> }</p><p> return data</p><p># 循环获取所有博文</p><p>def get_all_post(uid, containerid):</p><p> # 从第一页开始</p><p> page = 0</p><p> # 这个用来存放博文列表</p><p> posts = []</p><p> while True:</p><p> # 请求博文列表</p><p> result = requests.get('https://m.weibo.cn/api/container/getIndex?type=uid&value={}&containerid={}&page={}'</p><p> .format(uid, containerid, page))</p><p> json_data = result.json()</p><p> # 当博文获取完毕,退出循环</p><p> if not json_data['cards']:</p><p> break</p><p> # 循环将新的博文加入列表</p><p> for i in json_data['cards']:</p><p> posts.append(i['mblog']['text'])</p><p> # 停顿半秒,避免被反爬虫</p><p> sleep(0.5)</p><p> # 跳转至下一页</p><p> page += 1</p><p> # 返回所有博文</p><p> return posts</p><p>##############################</p><p>## 云图相关函数</p><p># 生成云图</p><p>def generate_personas(uid, data_list):</p><p> content = '<br>'.join([html2text(i) for i in data_list])</p><p> # 这里使用jieba的textrank提取出1000个关键词及其比重</p><p> result = jieba.analyse.textrank(content, topK=1000, withWeight=True)</p><p> # 生成关键词比重字典</p><p> keywords = dict()</p><p> for i in result:</p><p> keywords[i[0]] = i[1]</p><p> # 初始化图片</p><p> image = Image.open('./static/images/personas.png')</p><p> graph = np.array(image)</p><p> # 生成云图,这里需要注意的是WordCloud默认不支持中文,所以这里需要加载中文黑体字库</p><p> wc = WordCloud(font_path='./static/fonts/simhei.ttf',</p><p> background_color='white', max_words=300, mask=graph)</p><p> wc.generate_from_frequencies(keywords)</p><p> image_color = ImageColorGenerator(graph)</p><p> plt.imshow(wc)</p><p> plt.imshow(wc.recolor(color_func=image_color))</p><p> plt.axis("off") # 关闭图像坐标系</p><p> dest_img = './static/personas/{}.png'.format(uid)</p><p> plt.savefig(dest_img)</p><p> return dest_img</p><p>#######################################</p><p># 定义路由</p><p># 指定根路径请求的响应函数</p><p>@app.route('/', methods=['GET', 'POST'])</p><p>def index():</p><p> # 初始化模版数据为空</p><p> userinfo = {}</p><p> # 如果是一个Post请求,并且有微博用户id,则获取微博数据并生成相应云图</p><p> # request.method的值为请求方法</p><p> # request.form既为提交的表单</p><p> if request.method == 'POST' and request.form.get('uid'):</p><p> uid = request.form.get('uid')</p><p> userinfo = get_user_info(uid)</p><p> posts = get_all_post(uid, userinfo['containerid'])</p><p> dest_img = generate_personas(uid, posts)</p><p> userinfo['personas'] = dest_img</p><p> return render_template('index.html', **userinfo)</p><p>if __name__ == '__main__':</p><p> app.run()</p>

以上就是全部的代码,简单吧?当然,单文件结构只适合小的应用,随着功能和代码量的增加,还是需要把代码分离中不同的文件结构中以便开发和维护。最后,还差一个页面的模版文件。

3.模版开发

模版需要有一个输入的表单和用户信息展示,基于Jinja2模版引擎。熟悉Django模版的应该可以很快上手,流程也和Django类型,在项目根目录下建一个名为templates的文件夹并新建一个名为index.html的文件,代码如下:

<!DOCTYPE html><p><html></p><p><head></p><p> <meta charset="UTF-8"></p><p> <link rel="stylesheet" type="text/css" href="./static/css/style.css"></p><p> <title>Flask之微博单用户画像生成器</title></p><p></head></p><p><body></p><p><!--提交微博id的表单--></p><p><div></p><p> <form action="/" method="post" ></p><p> <input type="text" name="uid"  placeholder="微博用户ID"></p><p> <input type="submit"  value="生成画像"></p><p> </form></p><p></div></p><p><!--下面是用户的展示信息--></p><p><!--使用了模版的if语法,如果有才展示这块内容--></p><p></body></p><p></html></p>

这样,应用实现完毕,项目结构如下:

$ tree .<p>weibo_personas</p><p>├── app.py</p><p>├── static</p><p>│ ├── css</p><p>│ │ └── style.css</p><p>│ ├── fonts</p><p>│ │ └── simhei.ttf</p><p>│ └── images</p><p>│ └── personas.png</p><p>└── templates</p>

└── index.html

进入项目文件夹,启动项目:

$ python app.py

* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

然后浏览器打开http://127.0.0.1:5000 地址就可以看到本教程最上面的效果。

以上只是一个初步实现,还有很多需要完善的地方。比如,如果发布的博文比较多时,获取时间比较长,可以考虑加个缓存,存储已获取的用户,避免重复请求,前端也可以加个loading效果。本教程展示的只是单用户,后面也可以批量获取用户信息,生成一个群体的用户画像

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发表评论

登录后才能评论