Python 如何高效的在大量文本里面搜索匹配大量词

2020-04-04 18:27:04 +08:00
 v2zero

数千万篇文章,寻找其中包含成语的句子。成语有数万条。

目前没有对文章内容建立过全文索引,鉴于这个事情是一次性的,为此搞个索引可能也成本过高。

暂时的解决方案是,把成语都放在一条 re.compile('乌合之众|鸡犬相闻|...')里面去搜索文章,但效率总觉得不理想。

求教,是否可能有更高效的解决方案。

4452 次点击
所在节点    Python
14 条回复
superrichman
2020-04-04 18:36:41 +08:00
文章内容很长的话,正则的效率是很低的。全文搜索还是要用 elasticsearch 或者 solr 比较靠谱。
fishCatcher
2020-04-04 18:38:40 +08:00
AC 自动机
ClericPy
2020-04-04 19:06:58 +08:00
直接套 AC 自动机, 专门搞敏感词过滤和发现的, 现成的库就挺快了, 貌似是 C 写的给 py 调

套正则, 四五万字的 "或" 条件, 还不如直接用 Python 字符串的 for 和 in
ypw
2020-04-04 19:08:11 +08:00
成语长度固定四个字的话,建一个集合 set,然后暴力搜也是可以的,复杂度 O(n),与成语集合大小无关。
v2zero
2020-04-04 19:10:24 +08:00
@fishCatcher 感动,一个词解决一个大难题。业余写代码,自己也实现不了这种东西,网上找了个 Python 实现。原来预计一周多的运行时间,瞬间就缩减到一天了。
v2zero
2020-04-04 19:11:35 +08:00
@ypw 成语这种东西吧,有的还带逗号。。。也挺麻烦的
v2zero
2020-04-04 19:12:58 +08:00
@ClericPy 以前自己做了个敏感词过滤,就是用的正则,现在看来还是蛮蠢的了。
superrichman
2020-04-04 19:16:39 +08:00
@fishCatcher
@ClericPy
涨知识了,感谢
ClericPy
2020-04-04 20:02:13 +08:00
@v2zero #7 这事我实习时候干过啊... 不过不是用竖线, 用的是超长裹脚布版的零宽断言...... 后来发现还不如一个个 in 去判断呢...

@superrichman #8 你这么提问其实挺好的, 背景, 思路, 自己的尝试, 甚至没什么语文错误
上次见一个类似的需求, 说了一大堆自己的思路, 实际一开始就跑偏了, 带着起码二十多楼跟着歪了, 哈哈, 共同学习
lithbitren
2020-04-04 20:29:40 +08:00
@ClericPy 带佬,有稳定好用 py3 支持 utf8 的 ac 自动机 c 拓展嘛,我之前没找到,自己用纯 py 手撕了一个,算法上应该优化到极限了,但 40 万词启动还建树是用了两秒多,查词还好基本忽略不计了,用起来没啥问题,就是启动太难。
ClericPy
2020-04-04 20:56:13 +08:00
@lithbitren #10 你手撸已经比我强多了... 我都五六年没动 NLP 的东西了...
lithbitren
2020-04-05 22:32:48 +08:00
说起来,当时找 ac 自动机解决方案还是有坑的,py 的对于复杂算法的模板不多,csdn 上搜到的 py 的 ac 自动机是有问题,建树竟然用 remove 首元素来处理队列,让队列处理在 c 层面的时间复杂度变成了 O(N^2),小规模的屏蔽词过滤看不出啥,大规模词语处理时间会陡增,40 万词要处理将近四分钟,不过改数据解构用 deque 和 popleft 大概就好了。另外搜到过 2 个 pipy 上的开源库,一个是 py2 时代的,一个是重叠的关键字词输出会有问题,最后才决定手撸的。。
qsnow6
2020-04-11 17:33:22 +08:00
@v2zero #7
之前在过滤 black list 时找过相关的资料,长文本的搜索适合上 AC 自动机。短文本建议直接 x in s 就完事了,Python 编译器做了优化,效率更快,写起来也方便。

可以看这个答案: https://stackoverflow.com/questions/3389574/check-if-multiple-strings-exist-in-another-string#comment105454320_3389574

PS:楼主是做 SEO 的?可以加个好友交流下啊,我平时接触爬虫、数据清洗、NLP 这些领域比较多。
v2zero
2020-04-11 21:11:10 +08:00
@qsnow6 过于明显了么。微信,去空格: 182 1055 2814

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/659404

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX