哈Ha
在Habraiting的最后一部分中,发布了一种为英语术语构建词云的方法。 当然,解析俄语单词的任务要复杂得多,但是正如注释中所建议的那样,已经有现成的库用于此操作。
让我们弄清楚如何构建这样的图片:

我们还将看到多年来的哈勃文章云。
谁在乎,发生了什么事,在猫的下面。
解析中
与前面的情况一样,初始数据集是csv,其中包含Habr从2006年到2019年的文章的标题。 如果有人有兴趣亲自尝试,可以
在此处下载。
首先,将数据加载到Pandas Dataframe中,然后选择所需年份的标题。
df = pd.read_csv(log_path, sep=',', encoding='utf-8', error_bad_lines=True, quotechar='"', comment='#') if year != 0: dates = pd.to_datetime(df['datetime'], format='%Y-%m-%dT%H:%MZ') df['datetime'] = dates df = df[(df['datetime'] >= pd.Timestamp(datetime.date(year, 1, 1))) & ( df['datetime'] < pd.Timestamp(datetime.date(year + 1, 1, 1)))]
为了从控制台输出中删除各种棘手的unicode字符(例如非标准引号),需要unicode2str函数-在OSX下也可以使用,并且在输出到Windows Powershell时,会发出错误“ UnicodeEncodeError:'charmap'编解码器无法编码字符”。 太懒了,无法处理Powershell设置,因此该方法被证明是最简单的。
下一步是将俄语单词与其他单词分开。 这很简单-我们将字符转换为ascii编码,然后看看还剩下什么。 如果剩下两个以上的字符,那么我们考虑使用“ full”一词(唯一想到的就是Go语言,但是,那些愿意的人可以自己添加)。
def to_ascii(s): try: s = s.replace("'", '').replace("-", '').replace("|", '') return s.decode('utf-8').encode("ascii", errors="ignore").decode() except: return '' def is_asciiword(s): ascii_word = to_ascii(s) return len(ascii_word) > 2
下一个任务是规范化单词-为了获得单词云,每个单词必须以一种大小写和十进制显示。 对于英语,我们只需删除末尾的“'s”,还删除其他不可读的字符,例如方括号。 我不确定这种方法在科学上是否正确(而且我不是语言学家),但是对于此任务来说已经足够了。
def normal_eng(s): for sym in ("'s", '{', '}', "'", '"', '}', ';', '.', ',', '[', ']', '(', ')', '-', '/', '\\'): s = s.replace(sym, ' ') return s.lower().strip()
现在,最重要的是,俄语的解析成为了一切真正开始的原因。 如上一部分的注释中所建议,对于Python,可以使用pymorphy2库来完成。 让我们看看它是如何工作的。
import pymorphy2 morph = pymorphy2.MorphAnalyzer() res = morph.parse(u"") for r in res: print r.normal_form, r.tag.case
对于此示例,我们得到以下结果:
NOUN,inan,masc sing,datv datv NOUN,inan,masc sing,loc2 loc2 NOUN,inan,neut sing,datv datv NOUN,inan,masc sing,gen2 gen2
对于“世界”一词,MorphAnalyzer将“正常形式”定义为名词“世界”(或“世界”,但是我不知道它是什么),单数形式,以及可能的情况,如dativ,genitiv或locative。
使用MorphAnalyzer进行解析非常简单-确保单词是名词,然后派生其正常形式。
morph = pymorphy2.MorphAnalyzer() def normal_rus(w): res = morph.parse(w) for r in res: if 'NOUN' in r.tag: return r.normal_form return None
它仍然可以收集所有内容并查看发生了什么。 代码看起来像这样(删除了不相关的片段):
from collections import Counter c_dict = Counter() for s in titles.values: for w in s.split(): if is_asciiword(w):
在输出中,我们有一个单词字典及其出现次数。 我们得出前100个词,并从中形成单词普及度云:
common = c_dict.most_common(100) wc = WordCloud(width=2600, height=2200, background_color="white", relative_scaling=1.0, collocations=False, min_font_size=10).generate_from_frequencies(dict(common)) plt.axis("off") plt.figure(figsize=(9, 6)) plt.imshow(wc, interpolation="bilinear") plt.title("%d" % year) plt.xticks([]) plt.yticks([]) plt.tight_layout() file_name = 'habr-words-%d.png' % year plt.show()
但是结果却很奇怪:

在文本形式中,它看起来像这样:
3958 3619 1828 840 2018 496 389 375 375
“表演”,“第二”和“世纪”这两个词大有作为。 而且,尽管从原则上讲是可能的(您可以想象这样的标题:“以每秒1000次的速度搜索密码将花费一个世纪的时间”),但令人怀疑的是,这些单词太多了。 并非徒劳无功-调试显示,MorphAnalyzer将单词“ c”定义为“秒”,而单词“ c”定义为“世纪”。 即 在标题“使用技术...”中,MorphAnalyzer突出显示了3个词-“第二”,“帮助”,“技术”,这显然是错误的。 接下来的晦涩单词是“ when”(当使用时...)和“已经”,分别被定义为名词“直接”和“已经”。 解决方案很简单-解析时,仅考虑长度超过2个字符的单词,然后输入要从分析中排除的俄语例外单词列表。 再次,也许这并不完全是科学的(例如,有关“已经观察到颜色变化”的文章可能会从分析中删除),但是对于此任务已经足够:)。
最终结果或多或少与真相相似(Go和有关蛇的可能文章除外)。 剩下的一切都保存在gif中(gif生成代码在
上一部分中 ),并且我们获得了动画效果,其形式是从2006年到2019年在Habr标题中关键字的流行度。

结论
如您所见,借助现成的库对俄语文本进行的分析非常简单。 当然,有些保留,口头语言是一种灵活的系统,有许多例外情况,并且取决于上下文,存在上下文感,在这里可能根本无法获得100%的确定性。 但是对于手头的任务,上面的代码就足够了。
顺便说一句,用Python本身对西里尔文字进行处理还远远不够完美-字符输出到控制台,打印输出的数组输出损坏,需要在Python 2.7的行中附加u“”等小问题,等等。在21世纪,看起来像KOI8-R或CP-1252之类的所有谬论都已经消失了,字符串编码问题仍然很重要。
最后,有趣的是,与
英文版本相比,将俄文单词添加到文本云中实际上并没有增加图片的信息内容-几乎所有IT术语都是讲英语的,因此十年来俄文单词列表的变化不大。 可能要查看俄语的变化,您需要等待50到100年-在指定的时间之后,将有机会再次更新文章;)