如何在大量文本中高效的匹配出字符串?

2021-07-15 17:01:16 +08:00
 v2zero

我不是专业做技术的,因此会有很多技术盲区,碰到棘手问题也不知如何自行寻找解决方案,因此提问,感谢诸位。

需求背景是这样的:

在数百万的网页 html 源代码里面,寻找出包含某个特定字符串(或匹配某条正则)的网页,输出其 URL 信息。

由于是数据分析用途,需要很频繁的为了突发的需求而多次运行。

目前的解决方案是这样的:

数据存在 MongoDB 里面( zstd 压缩),匹配的时候使用 Python 直接遍历出所有网页,再通过 Python 内置的方法( in 条件或者 re )来进行判断。

如果仅使用 in 条件,目前每秒平均能匹配 4000 多个网页,百万的网页全部运行一次需要十多分钟,比较费力。此外,已经配置了阿里云 ECS 的对应容量下可选的最高速度的 SSD 。

尝试过的其它方案有:

使用 ElasticSearch 来建立全文索引。但发现在占用了大量额外硬盘空间的代价下,需要全量导出匹配结果时候的效率仍然很低下,或许是 ES 仅在匹配 top n 结果的时候才是高效的?又或只是我哪里没做对?

也尝试过 MongoDB 取消压缩,发现速度变更慢了,或许瓶颈是在硬盘 IO 不是在 CPU 上面?

3587 次点击
所在节点    Python
25 条回复
TimePPT
2021-07-15 17:08:17 +08:00
Rush9999
2021-07-15 17:13:03 +08:00
est
2021-07-15 17:13:31 +08:00
> 或许瓶颈是在硬盘 IO 不是在 CPU 上面?

也有可能在网络传输上。你还是把百万网页都做成一个大 txt 然后 grep 算了。
guyueyiren
2021-07-15 17:34:55 +08:00
放到 linux 下用 grep 去正则匹配?
wzq001
2021-07-15 17:35:18 +08:00
1 、将每个 HTML 格式压缩为一行,每行标记 html 路径 >> 到 big.txt
2 、
wzq001
2021-07-15 17:36:06 +08:00
1 、将每个 HTML 格式压缩为一行,每行标记 html 路径 >> 到 big.txt
2 、grep 搞定

赞同#3 观点
GrayXu
2021-07-15 17:57:13 +08:00
in 的速度不快吧。。可以用 grep 试试

这个场景…mapreduce 启动!
CSM
2021-07-15 18:31:20 +08:00
用 ripgrep
ClericPy
2021-07-15 18:39:08 +08:00
本来以为在说 AC 自动机处理敏感词什么的, 点进来感觉又有点不一样...

如果是冷数据, S3 + Hadoop 能搞不
v2zero
2021-07-15 18:43:37 +08:00
@est 尝试了,10 万条数据匹配字符串用时 25 秒,每秒 4000 个,和原先几乎一样。
MrGoooo
2021-07-15 19:07:29 +08:00
数据分组,多线程,甚至多主机(mapreduce)
liuhan907
2021-07-15 20:53:02 +08:00
查询是在线的,那数据源更新的频繁程度如何呢?
est
2021-07-15 22:28:01 +08:00
@v2zero LC_ALL=C grep XXX 1.txt 试试。
est
2021-07-15 22:30:03 +08:00
如果上面的 grep 也很慢,先用 xz 把 1.txt 用最大压缩比压缩了。然后 xzgrep
akira
2021-07-15 23:16:45 +08:00
不需要芒果也不需要 ES,直接拆分成多个文本保存。然后你机器是几个核的,就开几个 PY 进程去跑, 分别输出就可以了

假设平均一个页面的大小是 100kb,一百万个页面 总字符数量大约是 1 亿个, 100MB 左右吧
1 亿个字符做 子字符串查询 的话,理论上 应该能在 1s 内完成
xy90321
2021-07-16 01:33:53 +08:00
除非你每个网页里面每个词都独一无二,否则自然语言的话应该是拆词,然后根据词来作为索引储存 URL 。

当然如果不是自然语言,或者不是单词查询的话,就得重新考虑策略了。
xiadong1994
2021-07-16 01:40:04 +08:00
@akira 每个页面 100KB,1M 个文件,总共有 100GB……
xiadong1994
2021-07-16 01:40:47 +08:00
mapreduce 好像就是干这种事情的
wangxn
2021-07-16 08:56:58 +08:00
+1 。存成一个大文件然后直接 rigrep
rigrep 匹配的速度基本就是 IO 的速度,没有别的更快的方法了
假如需要多次查询,为什么不把结果保存下来?
wangxn
2021-07-16 08:59:41 +08:00
更正:rigrep -> ripgrep

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

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

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

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

© 2021 V2EX