|
1 | 1 | # Dedup |
2 | 2 |
|
3 | | -未完待续 |
| 3 | +Dedup是feapder大数据去重模块,内置3种去重机制,使用方式一致,可容纳的去重数据量与内存有关。不同于BloomFilter,去重受槽位数量影响,Dedup使用了弹性的去重机制,可容纳海量的数据去重。 |
| 4 | + |
| 5 | + |
| 6 | +## 去重方式 |
| 7 | + |
| 8 | +### 临时去重 |
| 9 | + |
| 10 | +> 基于redis,支持批量,去重有时效性。去重一万条数据约0.26秒,一亿条数据占用内存约1.43G |
| 11 | +
|
| 12 | +```python |
| 13 | +from feapder.dedup import Dedup |
| 14 | + |
| 15 | +data = {"xxx": 123, "xxxx": "xxxx"} |
| 16 | +datas = ["xxx", "bbb"] |
| 17 | + |
| 18 | +def test_ExpireFilter(): |
| 19 | + dedup = Dedup( |
| 20 | + Dedup.ExpireFilter, expire_time=10, redis_url="redis://@localhost:6379/0" |
| 21 | + ) |
| 22 | + |
| 23 | + # 逐条去重 |
| 24 | + assert dedup.add(data) == 1 |
| 25 | + assert dedup.get(data) == 1 |
| 26 | + |
| 27 | + # 批量去重 |
| 28 | + assert dedup.add(datas) == [1, 1] |
| 29 | + assert dedup.get(datas) == [1, 1] |
| 30 | +``` |
| 31 | + |
| 32 | + |
| 33 | +### 内存去重 |
| 34 | + |
| 35 | +> 基于内存,支持批量。去重一万条数据约0.5秒,一亿条数据占用内存约285MB |
| 36 | +
|
| 37 | +```python |
| 38 | +from feapder.dedup import Dedup |
| 39 | + |
| 40 | +data = {"xxx": 123, "xxxx": "xxxx"} |
| 41 | +datas = ["xxx", "bbb"] |
| 42 | + |
| 43 | +def test_MemoryFilter(): |
| 44 | + dedup = Dedup(Dedup.MemoryFilter) # 表名为test 历史数据3秒有效期 |
| 45 | + |
| 46 | + # 逐条去重 |
| 47 | + assert dedup.add(data) == 1 |
| 48 | + assert dedup.get(data) == 1 |
| 49 | + |
| 50 | + # 批量去重 |
| 51 | + assert dedup.add(datas) == [1, 1] |
| 52 | + assert dedup.get(datas) == [1, 1] |
| 53 | +``` |
| 54 | + |
| 55 | +### 永久去重 |
| 56 | + |
| 57 | +> 基于redis,支持批量,永久去重。 去重一万条数据约3.5秒,一亿条数据占用内存约285MB |
| 58 | +
|
| 59 | +```python |
| 60 | +from feapder.dedup import Dedup |
| 61 | + |
| 62 | + def test_BloomFilter(): |
| 63 | + dedup = Dedup(Dedup.BloomFilter, redis_url="redis://@localhost:6379/0") |
| 64 | + |
| 65 | + # 逐条去重 |
| 66 | + assert dedup.add(data) == 1 |
| 67 | + assert dedup.get(data) == 1 |
| 68 | + |
| 69 | + # 批量去重 |
| 70 | + assert dedup.add(datas) == [1, 1] |
| 71 | + assert dedup.get(datas) == [1, 1] |
| 72 | +``` |
| 73 | + |
| 74 | +## 过滤数据 |
| 75 | + |
| 76 | +Dedup可以通过如下方法,过滤掉已存在的数据 |
| 77 | + |
| 78 | + |
| 79 | +```python |
| 80 | +from feapder.dedup import Dedup |
| 81 | + |
| 82 | +def test_filter(): |
| 83 | + dedup = Dedup(Dedup.BloomFilter, redis_url="redis://@localhost:6379/0") |
| 84 | + |
| 85 | + # 制造已存在数据 |
| 86 | + datas = ["xxx", "bbb"] |
| 87 | + dedup.add(datas) |
| 88 | + |
| 89 | + # 过滤掉已存在数据 "xxx", "bbb" |
| 90 | + datas = ["xxx", "bbb", "ccc"] |
| 91 | + dedup.filter_exist_data(datas) |
| 92 | + assert datas == ["ccc"] |
| 93 | +``` |
| 94 | + |
| 95 | +## Dedup参数 |
| 96 | + |
| 97 | +- **filter_type**:去重类型,支持BloomFilter、MemoryFilter、ExpireFilter三种 |
| 98 | +- **redis_url**不是必须传递的,若项目中存在setting.py文件,且已配置redis连接方式,则可以不传递redis_url |
| 99 | + |
| 100 | +  |
| 101 | + |
| 102 | + ``` |
| 103 | + import feapder |
| 104 | + from feapder.dedup import Dedup |
| 105 | + |
| 106 | + class TestSpider(feapder.Spider): |
| 107 | + def __init__(self, *args, **kwargs): |
| 108 | + self.dedup = Dedup() # 默认是永久去重 |
| 109 | + ``` |
| 110 | +
|
| 111 | +- **name**: 过滤器名称 该名称会默认以dedup作为前缀 `dedup:expire_set:[name]`或`dedup:bloomfilter:[name]`。 默认ExpireFilter name=过期时间,BloomFilter name=`dedup:bloomfilter:bloomfilter` |
| 112 | +
|
| 113 | +  |
| 114 | + |
| 115 | + 若对不同数据源去重,可通过name参数来指定不同去重库 |
| 116 | +
|
| 117 | +- **absolute_name**:过滤器绝对名称 不会加dedup前缀 |
| 118 | +- **expire_time**:ExpireFilter的过期时间 单位为秒,其他两种过滤器不用指定 |
| 119 | +- **error_rate**:BloomFilter/MemoryFilter的误判率 默认为0.00001 |
| 120 | +- **to_md5**:去重前是否将数据转为MD5,默认是 |
0 commit comments