七夕到了下面,程序猿同志們都在想怎么送女朋友禮物复颈,送包包?太俗氣沥割!送口紅耗啦?沒有新意!
沒有點(diǎn)子的同志們不妨看看這篇机杜,滿滿的干貨:LDA 主題模型提取知乎情話中最美的意象 + AI 根據(jù)提取出的意象自動(dòng)寫情詩芹彬!送給女朋友一首這樣的情詩,比口紅包包什么的的有格調(diào)叉庐!
動(dòng)手實(shí)現(xiàn)
不想看代碼的同志可以跳過這部分去文末看實(shí)現(xiàn)效果和代碼下載鏈接。
爬取知乎高贊回答
以話題【你聽過哪些讓人怦然心動(dòng)的情話或者詩句会喝?】為例陡叠,爬取該話題下質(zhì)量最高的前 100 個(gè)回答玩郊。
首先分析接口,不難定位到回答在圖示所在的接口返回的內(nèi)容中枉阵。
切換到 headers 欄可查看該請(qǐng)求的 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 這個(gè)參數(shù)即可译红,用于請(qǐng)求翻頁,一頁答案的個(gè)數(shù)由參數(shù) limit 決定兴溜。
編碼發(fā)現(xiàn)侦厚,對(duì)于請(qǐng)求頭信息,需要在代碼中給出 user-agent 和 cookies拙徽,cookies 需要自己手動(dòng)去知乎登錄后獲取刨沦。這部分代碼如下:
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
# 去掉富文本標(biāo)簽
answer = re.sub("<.*?>","",answer)
return [author,answer]
except Exception as e:
print(e)
在返回的 json 內(nèi)容里答案分布在字段 content 和 excerpt 中,需要拼接膘怕,又由于內(nèi)容里有許多富文本標(biāo)簽想诅,不利于后續(xù)處理,在此利用正則表達(dá)式作了富文本過濾岛心。
為了加速爬蟲来破,使用了 concurrent.futures 中的 ThreadPoolExecutor,即線程池對(duì)象忘古。
executor = ThreadPoolExecutor(max_workers=4)
# 只獲取質(zhì)量高的前 100 個(gè)回答
all_tasks = [executor.submit(worker, (i)) for i in range(100)]
同時(shí)需要獲取線程執(zhí)行結(jié)束后的結(jié)果徘禁,引入 concurrent.futures 中的 as_completed 方法,其用法如下:
answers = []
for future in as_completed(all_tasks):
data = future.result()
answers.append(data)
as_completed()方法是一個(gè)生成器髓堪,在沒有任務(wù)完成的時(shí)候會(huì)阻塞送朱,一旦有某個(gè)任務(wù)完成,會(huì) yield 這個(gè)任務(wù)旦袋,從而執(zhí)行 for 循環(huán)下面的語句骤菠,然后繼續(xù)阻塞住,循環(huán)到所有的任務(wù)結(jié)束疤孕。
最后使用 pandas 模塊把答案保存到 csv 文件中商乎。
col = ['author','answer']
df = pd.DataFrame(data=answers,columns=col)
df.to_csv("answers.csv",encoding="utf-8")
這樣就完成了三步走中的第一步!
LDA 模型抽取回答主題得到常見意象
當(dāng)今社會(huì)是一個(gè)高度信息化的社會(huì)祭阀,如何從浩如煙海的文本中提取出主題鹉戚,是一個(gè)具有挑戰(zhàn)性的話題。主題提取有很多方法专控,其中最常見的就是隱含狄利克雷分布(Latent Dirichlet allocation)抹凳,簡(jiǎn)稱LDA。
LDA 是一種文檔主題生成模型伦腐,也稱為一個(gè)三層貝葉斯概率模型赢底,包含詞、主題和文檔三層結(jié)構(gòu)。所謂生成模型幸冻,就是說粹庞,我們認(rèn)為一篇文章的每個(gè)詞都是通過“以一定概率選擇了某個(gè)主題,并從這個(gè)主題中以一定概率選擇某個(gè)詞語”這樣一個(gè)過程得到洽损。文檔到主題服從多項(xiàng)式分布庞溜,主題到詞服從多項(xiàng)式分布。
關(guān)于 LDA 的原理碑定,我這里簡(jiǎn)單闡釋下流码,有兩個(gè)概率分布模型,一個(gè)是文檔關(guān)于主題的延刘,另一個(gè)是主題關(guān)于單詞的漫试,在初始條件下,這兩個(gè)概率分布模型都不是準(zhǔn)確的访娶,甚至是隨機(jī)給出的商虐,根據(jù)貝葉斯公式,由這兩個(gè)概率分布可以計(jì)算出文檔關(guān)于單詞的概率分布崖疤,而這個(gè)概率分布秘车,也可以直接根據(jù)文檔統(tǒng)計(jì)得出,如果不相符劫哼,則調(diào)整初始的兩個(gè)概率分布叮趴,直至根據(jù)貝葉斯公式間接計(jì)算出的文檔-單詞概率分布模型同基于文檔統(tǒng)計(jì)直接計(jì)算出來的概率分布模型相吻合。至于具體怎么調(diào)整概率分布权烧,有興趣的同學(xué)可以查閱相關(guān)資料眯亦。
在 Python 中,有直接實(shí)現(xiàn)了 LDA 的庫 pyLDAvis般码,我們只需要指定單詞個(gè)數(shù)上限和主題個(gè)數(shù)等參數(shù)即可妻率,同時(shí) pyLDAvis 也提供了非常好的動(dòng)態(tài)交互可視化界面的 API。
上一步我們將高贊回答保存到了 csv,這一步首先加載這個(gè)文件板祝,然后進(jìn)行分詞處理(也可自行設(shè)置停用詞)宫静,分詞向量化、調(diào)整 LDA 模型的參數(shù)券时,最后將數(shù)據(jù)填進(jìn)模型孤里,抽取出主題,并可視化出來橘洞。
這部分代碼如下:
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 個(gè)主題中的前 20 高頻詞匯如下:
Topic 0:
39 我見 看過 森林 一切 之中 無數(shù) 看見 真的 還有 感受 他們 大海 如同 找到 呼吸 情書 月亮 一次 這樣
Topic 1:
圖片 三分 情話 只是 宇宙 大家 真的 生活 無數(shù) 我會(huì) 心里 時(shí)間 開始 以下 最后 生命 永恒 這樣 想起 然后
Topic 2:
鄧穎超 周恩來 妻子 官方 情話 心里 怎么 時(shí)間 懷里 一把 太陽 情書 堅(jiān)定不移 身體 有來生 所有 看著 這個(gè) 那么 世界
Topic 3:
看到 不敢 從此 原因 世界 希望 這個(gè) 情話 溫柔 不要 只有 所有 別人 怎么 一直 但是 真的 永遠(yuǎn) 一定 只是
Topic 4:
34 世界 所有 這個(gè) 希望 只有 溫柔 一定 這樣 不要 還是 永遠(yuǎn) 那么 情話 所以 可愛 遇見 不會(huì) 一樣 心里
最后可視化:
import pyLDAvis.sklearn
data = pyLDAvis.sklearn.prepare(lda, tf, tf_vectorizer)
pyLDAvis.show(data)#可視化主題模型
可交互的動(dòng)態(tài)圖表還是非常具有視覺沖擊力的:
根據(jù)抽取出的主題 AI 作詩
AI 作詩是一門非常具有挑戰(zhàn)性的自然語言處理課題捌袜,在嘗試了很多模型未果后,我發(fā)現(xiàn)了九歌——人工智能詩歌寫作系統(tǒng)炸枣,來自清華大學(xué)自然語言處理與社會(huì)人文計(jì)算實(shí)驗(yàn)室的研究成果虏等,于是就索性采用九歌的接口弄唧,這個(gè)接口沒有高級(jí)的反爬措施,但是請(qǐng)求結(jié)果卻很奇怪博其,需要多次請(qǐng)求才能返回正確結(jié)果套才;根據(jù)上一步的提取出來的主題作詩,同時(shí)做了個(gè)簡(jiǎn)單的封裝慕淡,其效果如下:
比如輸入【情話】【大海】沸毁,會(huì)生成如下的詩歌:
天
大海東流日夜圓
情何限
把酒話離筵
輸入 【愛】 【月亮】峰髓,生成詩歌:
漁
月白蘆花愛水魚
風(fēng)吹帽
露濕小荷鋤
非常含蓄的詩詞,深究發(fā)現(xiàn)采用了多種修辭和藝術(shù)手法息尺,讀起來也別有一番韻味携兵。
相信這樣的七夕禮物,一定別有一番情趣搂誉。
代碼在微信公眾號(hào)后臺(tái)回復(fù):七夕徐紧。即可獲得。