MeteorCat / 搭建自我信息茧房

Created Sat, 19 Oct 2024 15:27:44 +0800 Modified Wed, 29 Oct 2025 23:24:53 +0800
3016 Words

搭建自我信息茧房

信息茧房 是指人们关注的信息领域会习惯性地被自己的兴趣所引导, 从而将自己的生活桎梏于像蚕茧一般的 "茧房" 中的现象.

在日常自媒体资讯流当中会根据你日常习惯来推送给你所需的相关资讯, 比如喜欢日常浏览 经济 相关新闻会推送时事相关对应的新闻, 而消息提供方之中会将该账号生成 用户个人画像 指明用户希望查看到相关的 经济人士 相关资讯新闻从而等待后续相关新闻推送.

只提取自己感兴趣的新闻就像 当中只看自己相关消息, 这种方式很容易封闭自己的新闻渠道

日常新闻资源得益于 rss 可以采集相关数据从而提取所需的, 这里以 知乎 官方 rss 源做解析:

知乎RSS: https://www.zhihu.com/rss

该接口可以提取出每日的新闻数据, 可以以内部的 原文url 做唯一key标识

这里提供下另外新闻 JSON 格式来做实例, 这解析 RSS 之后数据库入库的消息示例:

[
  {
    "author": "zhihu",
    "link": "https://www.zhihu.com/aaa",
    "title": "指环王动画电影《指环王:洛汗之战》发布概念海报制作特辑",
    "content": "测试内容AAA",
    "key": "2e78390ab87d41ecd3bd1f301c51e8c6",
    "createAt": 1729328629
  },
  {
    "author": "zhihu",
    "link": "https://www.zhihu.com/bbb",
    "title": "2024年Q3国产游戏收入创新高,点点互动产品领跑9月出海榜",
    "content": "测试内容BBBB",
    "key": "0cc44849bda5d4f6a170515041700248",
    "createAt": 1729328568
  }
]

RSS 的数据源可以通过自己编写定时 Python 脚本爬虫抓取解析处理并且做数据库入库处理

爬虫消息入库靠 feedparser(RSS解析)|pymysql(MySQL数据库)|hashlib(MD5哈希) 就可以处理, 因为比较简单所以直接跳过说明.

NLP

另外的重点: NLP(Natural Language Processing, 自然语言处理), 其实简单来说就是将一段文字提取出以下内容:

  • 自动摘要
  • 观点提取
  • 文本分类
  • 问题回答
  • 文本语义对比
  • 语音识别

这更像是给对应新闻分类, 让其新闻自己给自己做标记从而方便将其归类推送给用户, 实现用户的 人物画像.

这里采用 Pythonjieba 库中文 NLP 分词:

# NLP安装, 指定官方源安装会有编码错误问题, 建议直接全自动安装
pip install --upgrade paddlepaddle -i https://mirrors.aliyun.com/pypi/simple
pip install --upgrade jieba -i https://mirrors.aliyun.com/pypi/simple
# 启用 paddlepaddle 支持, PaddlePaddle 深度学习框架
pip install --upgrade paddlepaddle==2.6.0 -i https://mirrors.aliyun.com/pypi/simple

之后就是编写脚本导出数据库入库的新闻标题内容并且 NLP 处理:

# !/usr/bin/python
# -*- coding: UTF-8 -*-
# ===================================================
# RSS NLP
# ===================================================
import json
import jieba
import jieba.posseg as psg

# 项目入口
if __name__ == "__main__":
    # 假设目前从数据库提取的新闻内容
    rows = ('[{"author":"zhihu","link":"https://www.zhihu.com/aaa","title":"指环王动画电影《指环王:洛汗之战》发布概念海报制作特辑",'
            '"content":"测试内容AAA","key":"2e78390ab87d41ecd3bd1f301c51e8c6","createAt":1729328629},{"author":"zhihu",'
            '"link":"https://www.zhihu.com/bbb","title":"2024年Q3国产游戏收入创新高,点点互动产品领跑9月出海榜","content":"测试内容BBBB",'
            '"key":"0cc44849bda5d4f6a170515041700248","createAt":1729328568}]')
    rss = json.loads(rows)

    # 启动 paddle 模式. 0.40版之后开始支持,早期版本不支持
    jieba.enable_paddle()

    # 加载自定义关键词的词典, 用来加载最新热词关键字
    # jieba.load_userdict('keyboards.txt')

    # 遍历解构所有新闻标题
    for data in rss:
        title = data['title']

        # PaddlePaddle 深度学习框架检索, 必须启用 jieba.enable_paddle()
        keyboards = jieba.cut(title, use_paddle=True)

        # 本地简单全匹配模式, 会将 "动画电影" 拆分关键字 "动画", "电影", "动画电影" 三个字
        # keyboards = jieba.cut(title, cut_all=True)

        # 精确匹配模式, 提取关键词会直接名词转化 "动画电影" 不会被解析裂变三个词
        # keyboards = jieba.cut(title, cut_all=False)

        # 搜索引擎模式, 尽可能把语句内容关键字全部分解出来提取
        # keyboards = jieba.cut_for_search(title)

        # 打印关键字内容
        print("title:", title)
        print("keyboards:", ",".join(keyboards))

        # 词性分析分析出内容的关键字名词、动词、代词等
        keyboards = psg.cut(title, use_paddle=True)
        for keyboard in keyboards:
            print("word:", keyboard.word, "flag:", keyboard.flag)

最后导出结果内容数据, 可以看出语句:

keyboards: 指环王,动画电影,《,指环王,:,洛汗,之战,》,发布,概念,海报,制作,特辑
word: 指环王 flag: n
word: 动画电影 flag: n
word: 《 flag: x
word: 指环王 flag: n
word: : flag: x
word: 洛汗 flag: ns
word: 之 flag: u
word: 战 flag: n
word: 》 flag: x
word: 发布 flag: v
word: 概念 flag: n
word: 海报 flag: n
word: 制作 flag: vn
word: 特辑 flag: n
title: 2024年Q3国产游戏收入创新高,点点互动产品领跑9月出海榜
keyboards: 2024,年,Q3,国产,游戏,收入,创新,高,,,点点,互动,产品,领跑,9,月,出海,榜
word: 2024 flag: m
word: 年 flag: m
word: Q3 flag: eng
word: 国产 flag: n
word: 游戏 flag: n
word: 收入 flag: v
word: 创新 flag: v
word: 高 flag: a
word: , flag: x
word: 点点 flag: n
word: 互动 flag: d
word: 产品 flag: n
word: 领跑 flag: v
word: 9 flag: m
word: 月 flag: m
word: 出海 flag: v
word: 榜 flag: n

需要注意标题提取的词性和专名类别标签集合如下表,其中我们将最常用的4个专名类别标记为大写的形式:

标签 含义 标签 含义 标签 含义 标签 含义
n 普通名词 f 方位名词 s 处所名词 nw 作品名
nz 其他专名 v 普通动词 vd 动副词 vn 名动词
a 形容词 ad 副形词 an 名形词 d 副词
m 数量词 q 量词 r 代词 p 介词
c 连词 u 助词 xc 其他虚词 w 标点符号
PER 人名 LOC 地名 ORG 机构名 TIME 时间

可以看到 word: 指环王 flag: n, 代表指环王词性为 n = 普通名词

这里面可以筛选关键词意, 比如提取出来的 动画电影 之类含义关键字可以给 用户画像 追加, 后续如果有其他新闻触及到该词意就可以直接推送给用户.

语音播报

上面已经生成出大量的新闻消息并且通过 Python 处理好数据入库放入 MySQL, 之后就是完善自己的数据来源需要将标题数据语音 mp3 支持外部播放.

这里主要还是以 Python 处理, 建议数据库预留字段放置音频文件目录, 然后分开脚本做数据入库和音频生成

不要把爬虫功能和语音生成的功能放一起, 而是要拆分出来防止功能出现耦合

这里采用 pyttsx3 做音频生成:

# !/usr/bin/python
# -*- coding: UTF-8 -*-
# ===================================================
# RSS NLP
# ===================================================
import json
import argparse
import os
import pyttsx3

# 项目入口
if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Export RSS Voice")
    parser.add_argument("-o", "--output", help="Output dictionary", required=True)
    args = parser.parse_args()

    # 输出目录
    if not os.path.exists(args.output):
        raise Exception("Output Non Exists")

    # 假设目前从数据库提取的新闻内容
    rows = ('[{"author":"zhihu","link":"https://www.zhihu.com/aaa","title":"指环王动画电影《指环王:洛汗之战》发布概念海报制作特辑",'
            '"content":"测试内容AAA","key":"2e78390ab87d41ecd3bd1f301c51e8c6","createAt":1729328629},{"author":"zhihu",'
            '"link":"https://www.zhihu.com/bbb","title":"2024年Q3国产游戏收入创新高,点点互动产品领跑9月出海榜","content":"测试内容BBBB",'
            '"key":"0cc44849bda5d4f6a170515041700248","createAt":1729328568}]')
    feeds = json.loads(rows)

    # 语音引擎
    engine = pyttsx3.init()
    engine.setProperty('rate', 190)  # 语速
    engine.setProperty('volume', 1.0)  # 音量

    # 遍历解构所有新闻标题
    for feed in feeds:
        key = feed["key"]
        title = feed["title"]
        filename = os.path.join(args.output, key + ".mp3")
        print("key:", key, ", filename:", filename, ", title:", title)

        # 保存输出
        engine.save_to_file(title, filename)
        engine.runAndWait()

    # 关闭引擎
    engine.stop()

这里带参数 -d 处理就可以导出对应的音频数据

这里只是作为初版, 实际上不能将大量音频放置在同一目录之中, 而是需要加上 Ymd(年月日) 做层二级目录