最近我们对我们平台的用户进行了一个用户标签提取, 这中间的主要流程如下图 3-1 所示:
图 3-1
一, 梳理做用户画像需要的数据
用户画像是基于业务数据而进行的, 如果前期没有考虑好这一点, 那么在真正实操时会发现做分析需要的数据存在不同的业务表里面, 甚至有些数据根本没有保存. 所以, 在做用户画像之前最需要做的事就是梳理清楚到底需要哪些数据, 如果业务上没有保存, 那么就增加保存, 如果数据非常分散, 最好是集中保存下, 否则后面随着数据越来越大, 从多个业务表里面汇总数据也是一个非常麻烦的事.
如上图, 如果我们要获取的是用户点赞, 评论, 分享, 浏览的数据, 那么可以使用 AOP 把用户做这些请求的数据记录到一个日志里面. 例如:
字段名 | 字段说明 | 示例 |
---|---|---|
user_id | 用户 id | 1 |
operation_type | 行为类型 | 1 - 点赞、2 - 评论、3 - 分享、4 - 浏览 |
operation_content_id | 内容 idt | 1 |
operation_time | 操作时间 | 2018.4.17 |
接下来就是对内容 id 进行去重, 可以直接使用 Set 去重, 去重之后可以去内容表里面通过内容 id 获取到内容的 URL 地址, 因为我们的内容是不保存在本地的, 所以需要通过内容的 URL 去第三方平台拿信息.
二, 通过 URL 获取内容的标题和正文
对于一篇文章来说, 标题和正文是最有价值的, 对于提取标签这个事来说, 也是需要标题和正文的. 提取的方式有很多, 比如可以单独写针对不同平台的爬虫进行提取信息, 但是这样的成本很大. 为了保证提取的内容确实是正文, 也不能简单的使用
driver.find_element_by_xpath('//body').text
的方式, 因为这样取出来的数据有很多干扰信息, 会把整个页面的所有信息都获取出来当作正文, 包括推荐的内容, 包括广告... 页面上呈现的所有内容. 代码如下:
- # 爬取文章内容
- driver = chrome_dirver()
- driver.set_page_load_timeout(20)
- # 假设文章的 URL 存放在 article.json 文件中
- with open('article.json') as f:
- article = f.read()
- article = json.loads(article)
- for k, v in article.iteritems():
- try:
- article_id = k
- article_url = v
- driver.get(v)
- article_title = driver.title
- article_info = driver.find_element_by_xpath('//body').text
- # 这里已经获取到文章标题和正文
- except Exception as e:
- print e
- continue
- driver.close()
- driver.quit()
GitHub 上有牛人写了一个基于行块分布函数的通用网页正文抽取算法的 Python 版本. 我们通过测试发现准确性是还可以的, GitHub 地址 https://github.com/chrislinan/cx-extractor-python
三, 通过百度的自然语言算法 AipNlp 计算出所有文章的标签及对应权重
获取到文章的标题和正文之后, 就是需要提取这篇文章的标签以及标签的权重. 当然我们可以自己使用开源的分词算法, 但是如果没有 "词语 - 有效标签" 的库, 就是把文章的分词做好之后也很难提取有效的标签. 我们这边考虑的是使用百度的自然语言算法 AipNlp 来帮助我们做这个事. 为什么使用百度云, 而不使用腾讯云或者阿里云? 因为腾讯的 "词语 - 有效标签" 库偏社交, 阿里的 "词语 - 有效标签" 偏电商, 百度就是库是最全的.
使用百度云中的自然语言处理 SDK 很简单, 可以直接查看他的 SDK 文档 https://cloud.baidu.com/doc/NLP/NLP-Java-SDK.html#.E5.BF.AB.E9.80.9F.E5.85.A5.E9.97.A8 , 有 Python,Java,PHP,Node 各种语言的.
例如使用 Java 的, 先增加 maven 依赖:
- <dependency>
- <groupId>com.baidu.aip</groupId>
- <artifactId>java-sdk</artifactId>
- <version>${version}</version>
- </dependency>
再就是使用, 最简单的样例如下:
- public class Sample {
- // 设置 APPID/AK/SK
- public static final String APP_ID = "你的 App ID";
- public static final String API_KEY = "你的 Api Key";
- public static final String SECRET_KEY = "你的 Secret Key";
- public static void main(String[] args) {
- // 初始化一个 AipNlp
- AipNlp client = new AipNlp(APP_ID, API_KEY, SECRET_KEY);
- // 调用接口
- String title = "一面 APP 是一款非常有意思的社交 APP";
- String content = "一面是一款基于文字, 视频, 图片的形式, 网罗各类资讯, 音乐, 运动, 旅行, 周边生活信息, 打折促销等内容的社交平台. 在一面上, 你可以创建各种类型的主题, 和家人, 恋人, 朋友, 同事, 同学, 邻居, 同伴等一起订阅专属信息. 真正做到关心你关心的人关心的一切, 让内容共享温暖我们的社交关系.";
- JSONObject res = client.keyword(title, content);
- }
- }
Body 请求示例:
- {
- "title":"一面 APP 是一款非常有意思的社交 APP",
- "content": "一面是一款基于文字, 视频, 图片的形式, 网罗各类资讯, 音乐, 运动, 旅行, 周边生活信息, 打折促销等内容的社交平台. 在一面上, 你可以创建各种类型的主题, 和家人, 恋人, 朋友, 同事, 同学, 邻居, 同伴等一起订阅专属信息. 真正做到关心你关心的人关心的一切, 让内容共享温暖我们的社交关系."
- }
返回示例:
- {
- "log_id": 4457308639853058292,
- "items": [
- {
- "score": 0.997762,
- "tag": "社交"
- },
- {
- "score": 0.861775,
- "tag": "资讯"
- },
- {
- "score": 0.845657,
- "tag": "订阅"
- }
- ]
- }
四, 通过用户, 行为类型, 文章的关系, 计算出每个用户的标签及权重
例如: 点赞权重为 0.8, 评论权重为 0.9, 分享权重为 1.0, 浏览权重为 0.3. 那就是根据这个用户对哪些文章以何种行为进行了关联, 把该文章的标签关联到这个用户上即可, 具体的算法我在用户画像 (一)|计划制定讲过, 大致如下:
3.6, 总结
综合上述分析, 用户画像的数据模型, 可以概括为下面的公式:
用户标识 + 时间 + 行为类型 + 接触点 (网址 + 内容)
某用户因为在什么时间, 某个地点, 对某个对象, 做了什么事. 所以会打上 XX 标签.
用户标签的权重可能随时间的增加而衰减, 因此定义时间为衰减因子 r, 行为类型, 网址决定了权重, 内容决定了标签, 进一步转换为公式:
标签权重 = 衰减因子 × 行为权重 × 位置权重
当然, 很多时候标签本身也是有权重的.
如: 用户 A, 昨天在发现频道浏览 "2018 年必看惊悚恐怖片之一: XXX 电影" 的主题内容.
我们为这个内容打的标签为: 恐怖 0.6, 电影 0.8
时间: 因为是昨天的行为, 假设衰减因子为: r=0.95
行为类型: 浏览行为记为权重 1
地点: 在发现频道为 0.6(相比在我的 - 我创建的主题中的 0.9)
则用户偏好标签是: 电影, 权重是 0.95*0.6 * 1=0.57, 即, 用户A: 恐怖 0.57, 电影 0.57. 最后再乘以标签自己的权重.
上述模型权重值的选取只是举例参考, 具体的权重值需要根据业务需求二次建模, 这里强调的是如何从整体思考, 去构建用户画像模型, 进而能够逐步细化模型.
来源: http://www.jianshu.com/p/7285187bbda7