一般大家用什么办法判断 url 已经被爬过了? 用 hashmap 感觉内存消耗无上限啊,几十 G 内存唰唰唰就满了,用 sqlite 感觉 HDD 会成瓶颈?
1
wmttom 2017-03-09 00:24:14 +08:00 via iPhone
bloom filter
|
2
cdwyd 2017-03-09 00:30:15 +08:00 via Android
吓一跳,看成了爬虫重判
|
3
cdwyd 2017-03-09 00:32:28 +08:00 via Android
hashmap 也不会嗖嗖几十个 g 吧,检查下流程,是不是哪里错了。
|
4
gouchaoer 2017-03-09 00:46:31 +08:00 via Android
数据库加索引就完了,搞那么复杂
|
5
jiangzhuo 2017-03-09 01:15:52 +08:00 1
首先大家应该是用 url 判重,一般是选取 hostname 、 path 和一部分或者全部的 query 来组合进行 hash 判重。
就拿把 hash 作为 key 以 string 类型存在 redis 中来说。 计算出来的 key 的 sds 大小是 64 字节,值只有 1 字节, sds 大小 16 字节。 在没有修改 redis 配置的情况下。 然后根据 http://www.worldwidewebsize.com/ Google 索引 47 亿多一点 如果有 47 亿个不同的 url 的话,占用内存是 4700000000*( 16+16+16+64 )+8589934592*4 = 522.25G (卧槽,打自己脸了 再算算 如果楼主爬 5 亿个不同网址,大概需要 54G 的 redis ,这应该是一般能买的起的 64G 或者 96G 内存的机器。 5 亿个网址好像也超过现在的必应了。 |
6
scnace 2017-03-09 01:32:53 +08:00 via Android
Bloomfilter 或 数据库加索引
|
7
samcode 2017-03-09 02:27:44 +08:00 1
先 crc 或者啥 hash 一下
|
9
1a1a11a OP 检查过了,主要是 url 数据量太大了,写入磁盘的已经几百 GB 了,不过有些 url 是没意义的,需要想办法过滤掉。
|
12
1a1a11a OP @jiangzhuo 为什么我 72G 的内存刷刷刷就满了 :(,估计有不少费 url ,加上 python 可能比较费内存,你发的这个网址挺好玩的,不知道为什么中间突然降下去了,我一直觉得网页总数是单调增加的,不过从这个网站看,还挺稳定的。
|
13
1a1a11a OP @jiangzhuo 哦,对,你的数值错了,是 470 亿,单位是 10 亿,不是 1 亿,所以你的计算要再乘以 10
|
14
binux 2017-03-09 07:25:34 +08:00
@1a1a11a #9 你已经写磁盘了?没有去重就已经写磁盘了?那么看起来你并没有实时去重的需求啊。那简单,把 url 排个序 sort | uniq 就行了。
|
15
bjlbeyond 2017-03-09 07:57:34 +08:00 via iPhone
对爬取过的 url 计数,超过一定次数后丢弃
|
16
wmttom 2017-03-09 09:43:29 +08:00 via iPhone 2
@1a1a11a 很多时候几个 9 的准确性已经足够了。
或者可以利用 Bloomfilter 的特性,不存在的一定不在,存在的再去查询存储索引,看是不是真的存在。 |
17
Lax 2017-03-09 09:44:38 +08:00
用 HLL ,内存占用很少,有些误差
|
18
v2pro 2017-03-09 09:47:06 +08:00 1
simhash
|
19
1a1a11a OP @binux 我把去重完的 url 写磁盘了和待爬 url 队列写磁盘了,要不内存不一会儿就满,服务器是前兆带宽,我满载了在爬。。。
|
21
allgy 2017-03-09 10:59:39 +08:00
#1 楼正解
|
25
jiangzhuo 2017-03-09 11:58:42 +08:00
@1a1a11a 果然大半夜事多了就是精力不集中, 1#说的对 bloomfilter+个 bigtable 什么的足够了
|
27
Lax 2017-03-11 17:22:51 +08:00 1
@1a1a11a HyperLogLog , redis 内置支持 https://redis.io/commands/pfadd
|