七夕,送上这份最美情话+AI作诗的大礼

七夕到了,程序猿同志们都在想怎么送女朋友礼物,送包包?太俗气!送口红?没有新意!

没有点子的同志们不妨看看这篇,满满的干货:LDA 主题模型提取知乎情话中最美的意象 + AI 根据提取出的意象自动写情诗!送给女朋友一首这样的情诗,比口红包包什么的的有格调!

0.jpg

动手实现

不想看代码的同志可以跳过这部分去文末看实现效果和代码下载链接。

爬取知乎高赞回答

以话题【你听过哪些让人怦然心动的情话或者诗句?】为例,爬取该话题下质量最高的前 100 个回答。

1.png

首先分析接口,不难定位到回答在图示所在的接口返回的内容中。

2.png

切换到 headers 栏可查看该请求的 URL 地址为

https://www.zhihu.com/api/v4/questions/285989317/answers?include=data%5B%2A%5D.is_normal%2Cadmin_closed_comment%2Creward_info%2Cis_collapsed%2Cannotation_action%2Cannotation_detail%2Ccollapse_reason%2Cis_sticky%2Ccollapsed_by%2Csuggest_edit%2Ccomment_count%2Ccan_comment%2Ccontent%2Ceditable_content%2Cvoteup_count%2Creshipment_settings%2Ccomment_permission%2Ccreated_time%2Cupdated_time%2Creview_info%2Crelevant_info%2Cquestion%2Cexcerpt%2Crelationship.is_authorized%2Cis_author%2Cvoting%2Cis_thanked%2Cis_nothelp%2Cis_labeled%2Cis_recognized%2Cpaid_info%2Cpaid_info_content%3Bdata%5B%2A%5D.mark_infos%5B%2A%5D.url%3Bdata%5B%2A%5D.author.follower_count%2Cbadge%5B%2A%5D.topics&limit=5&offset=10&platform=desktop&sort_by=default

需要注意 offset 这个参数即可,用于请求翻页,一页答案的个数由参数 limit 决定。

编码发现,对于请求头信息,需要在代码中给出 user-agent 和 cookies,cookies 需要自己手动去知乎登录后获取。这部分代码如下:

headers = {
    'cookies': '''改成你自己的 cookies''',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0',
}

url = 'https://www.zhihu.com/api/v4/questions/285989317/answers?include=data%5B*%5D.is_normal%2Cadmin_closed_comment%2Creward_info%2Cis_collapsed%2Cannotation_action%2Cannotation_detail%2Ccollapse_reason%2Cis_sticky%2Ccollapsed_by%2Csuggest_edit%2Ccomment_count%2Ccan_comment%2Ccontent%2Ceditable_content%2Cvoteup_count%2Creshipment_settings%2Ccomment_permission%2Ccreated_time%2Cupdated_time%2Creview_info%2Crelevant_info%2Cquestion%2Cexcerpt%2Crelationship.is_authorized%2Cis_author%2Cvoting%2Cis_thanked%2Cis_nothelp%2Cis_labeled%2Cis_recognized%2Cpaid_info%2Cpaid_info_content%3Bdata%5B*%5D.mark_infos%5B*%5D.url%3Bdata%5B*%5D.author.follower_count%2Cbadge%5B*%5D.topics&offset={}&limit=5&sort_by=default&platform=desktop'

def worker(pageNum):
    try:
        res = requests.get(url=url.format(pageNum),headers=headers)
        data = res.json()['data']
        for item in data:
            author = item['author']['name']
            # 一条答案包括 content 和 excerpt 两部分
            content = item['content']
            excerpt = item['excerpt']
            answer = content + excerpt
            # 去掉富文本标签
            answer = re.sub("<.*?>","",answer)
            return [author,answer]

    except Exception as e:
        print(e)

在返回的 json 内容里答案分布在字段 content 和 excerpt 中,需要拼接,又由于内容里有许多富文本标签,不利于后续处理,在此利用正则表达式作了富文本过滤。

为了加速爬虫,使用了 concurrent.futures 中的 ThreadPoolExecutor,即线程池对象。

executor = ThreadPoolExecutor(max_workers=4)
# 只获取质量高的前 100 个回答
all_tasks = [executor.submit(worker, (i)) for i in range(100)]

同时需要获取线程执行结束后的结果,引入 concurrent.futures 中的 as_completed 方法,其用法如下:

answers = []
for future in as_completed(all_tasks):
    data = future.result()
    answers.append(data)

as_completed()方法是一个生成器,在没有任务完成的时候会阻塞,一旦有某个任务完成,会 yield 这个任务,从而执行 for 循环下面的语句,然后继续阻塞住,循环到所有的任务结束。

最后使用 pandas 模块把答案保存到 csv 文件中。

col = ['author','answer']
df = pd.DataFrame(data=answers,columns=col)

df.to_csv("answers.csv",encoding="utf-8")
3.png

这样就完成了三步走中的第一步!

LDA 模型抽取回答主题得到常见意象

当今社会是一个高度信息化的社会,如何从浩如烟海的文本中提取出主题,是一个具有挑战性的话题。主题提取有很多方法,其中最常见的就是隐含狄利克雷分布(Latent Dirichlet allocation),简称LDA。

LDA 是一种文档主题生成模型,也称为一个三层贝叶斯概率模型,包含词、主题和文档三层结构。所谓生成模型,就是说,我们认为一篇文章的每个词都是通过“以一定概率选择了某个主题,并从这个主题中以一定概率选择某个词语”这样一个过程得到。文档到主题服从多项式分布,主题到词服从多项式分布。

关于 LDA 的原理,我这里简单阐释下,有两个概率分布模型,一个是文档关于主题的,另一个是主题关于单词的,在初始条件下,这两个概率分布模型都不是准确的,甚至是随机给出的,根据贝叶斯公式,由这两个概率分布可以计算出文档关于单词的概率分布,而这个概率分布,也可以直接根据文档统计得出,如果不相符,则调整初始的两个概率分布,直至根据贝叶斯公式间接计算出的文档-单词概率分布模型同基于文档统计直接计算出来的概率分布模型相吻合。至于具体怎么调整概率分布,有兴趣的同学可以查阅相关资料。

在 Python 中,有直接实现了 LDA 的库 pyLDAvis,我们只需要指定单词个数上限和主题个数等参数即可,同时 pyLDAvis 也提供了非常好的动态交互可视化界面的 API。

上一步我们将高赞回答保存到了 csv,这一步首先加载这个文件,然后进行分词处理(也可自行设置停用词),分词向量化、调整 LDA 模型的参数,最后将数据填进模型,抽取出主题,并可视化出来。

这部分代码如下:

df = pd.read_csv("answers.csv")

def chinese_word_cut(text):
    return " ".join(jieba.cut(text))

df["answer"] = df.answer.apply(chinese_word_cut)


from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer

# 向量化
n_features = 1000

tf_vectorizer = CountVectorizer(strip_accents = 'unicode',
                                max_features=n_features,
                                stop_words='english',
                                max_df = 0.5,
                                min_df = 10)
tf = tf_vectorizer.fit_transform(df.answer)

from sklearn.decomposition import LatentDirichletAllocation

n_topics = 5
# LDA 处理
lda = LatentDirichletAllocation(n_topics=n_topics, max_iter=50,
                                learning_method='online',
                                learning_offset=50.,
                                random_state=0)
lda.fit(tf)

抽取出的 5 个主题中的前 20 高频词汇如下:

Topic 0:
39 我见 看过 森林 一切 之中 无数 看见 真的 还有 感受 他们 大海 如同 找到 呼吸 情书 月亮 一次 这样
Topic 1:
图片 三分 情话 只是 宇宙 大家 真的 生活 无数 我会 心里 时间 开始 以下 最后 生命 永恒 这样 想起 然后
Topic 2:
邓颖超 周恩来 妻子 官方 情话 心里 怎么 时间 怀里 一把 太阳 情书 坚定不移 身体 有来生 所有 看着 这个 那么 世界
Topic 3:
看到 不敢 从此 原因 世界 希望 这个 情话 温柔 不要 只有 所有 别人 怎么 一直 但是 真的 永远 一定 只是
Topic 4:
34 世界 所有 这个 希望 只有 温柔 一定 这样 不要 还是 永远 那么 情话 所以 可爱 遇见 不会 一样 心里

最后可视化:

import pyLDAvis.sklearn
data = pyLDAvis.sklearn.prepare(lda, tf, tf_vectorizer)
pyLDAvis.show(data)#可视化主题模型
4.png

可交互的动态图表还是非常具有视觉冲击力的:

5.gif

根据抽取出的主题 AI 作诗

AI 作诗是一门非常具有挑战性的自然语言处理课题,在尝试了很多模型未果后,我发现了九歌——人工智能诗歌写作系统,来自清华大学自然语言处理与社会人文计算实验室的研究成果,于是就索性采用九歌的接口,这个接口没有高级的反爬措施,但是请求结果却很奇怪,需要多次请求才能返回正确结果;根据上一步的提取出来的主题作诗,同时做了个简单的封装,其效果如下:

比如输入【情话】【大海】,会生成如下的诗歌:

天
大海东流日夜圆
情何限
把酒话离筵

输入 【爱】 【月亮】,生成诗歌:

渔
月白芦花爱水鱼
风吹帽
露湿小荷锄

非常含蓄的诗词,深究发现采用了多种修辞和艺术手法,读起来也别有一番韵味。

6.gif

相信这样的七夕礼物,一定别有一番情趣。

代码在微信公众号后台回复:七夕。即可获得。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,511评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,495评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,595评论 0 225
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,558评论 0 190
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,715评论 3 270
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,672评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,112评论 2 291
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,837评论 0 181
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,417评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,928评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,316评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,773评论 2 234
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,253评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,827评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,440评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,523评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,583评论 2 249