Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Latest commit

 

History

History
History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 

README.md

Outline

Python leveldb Utils 常用方法封装。

leveldb是Google开源的一个轻量级,高性能,KeyValue 存储数据库。作者是Google战神Jeff Dean,基于他自己的BigTable论文,使用C++ POSIX实现。

LevelDB is a light-weight, single-purpose library for persistence with bindings to many platforms.

官网 http://leveldb.org/
GitHub https://github.com/google/leveldb
官方 Javascript Binding https://github.com/Level/levelup

Python Binding

早期官方仅提供C++和Javascript。Python实现均是第三方开发。其中使用较广泛和稳定的是 https://github.com/rjpower/py-leveldb 。目前处于稳定运行,维护停滞状态。
在Python爬虫实现过程中,常常需要快速简单处理存储大量数据至本地文件,构建SQL数据库表过于复杂,变更不灵活。使用JSON文本格式,缺乏索引,过滤,随机增删数据。因此leveldb是一种轻便快捷的最佳解决方案。

这里封装了一些常用方法,均是日常爬虫数据采集存储的常用方法。

exist()

判断key是否存在于database中。返回Boolean值。

def exist(db_src, key):
    try:
        db_src.Get(_key_obj)
        return True
    except KeyError:
        return False

count()

统计database中数据总量计数,支持key过滤子字符串,value过滤子字符串,返回总数和过滤后有效总数。

def count(db_src, k_filter, v_filter):
    total, valid = 0, 0
    for _k, _v in db_src.RangeIter():
        total += 1
        if k_filter:
            if _k.find(k_filter) == -1:
                continue
        if v_filter:
            if _v.find(v_filter) == -1:
                continue
        valid += 1
    return total, valid

copy()

从源库到目标库,拷贝database,支持key过滤子字符串。返回源库总数和过滤后有效拷贝总数。

def copy(db_src, db_dst, k_filter):
    total, valid = 0, 0
    for _k, _v in db_src.RangeIter():
        total += 1
        if k_filter:
            if _k.find(k_filter) != -1:
                valid += 1
                db_dst.Put(_k, _v, sync=True)
        else:
            valid += 1
            db_dst.Put(_k, _v, sync=True)
    return total, valid

delete()

删除目标库中与源库相同key的数据项。

def delete(db_src, db_dst):
    for _k, _v in db_src.RangeIter():
        db_dst.Delete(_k)

diff()

查找源库与目标库的key值差异数据项,存储至差异库。返回差异项总数。

def diff(db_src, db_dst, db_diff):
    diff_count = 0
    for _k, _v in db_src.RangeIter():
        if not exist(db_dst, _k):
            diff_count += 1
            db_diff.Put(_k, _v)
    return diff_count

clean_copy()

拷贝源库至目标库,并删除value值为空的数据项。返回拷贝总数。

def clean_copy(db_src, db_dst):
    total = 0
    for _k, _v in db_src.RangeIter():
        if _v:
            db_dst.Put(_k, _v)
            total += 1
    return total

dump()

打印输出当前数据库中所有key value数据。
安全兼容:当参数是字符串时,当作本地路径文件名处理,临时打开数据库。

def dump(db_src):
    _db = leveldb.LevelDB(db_src, create_if_missing=False) if isinstance(db_src, str) else db_src
    for _k, _v in _db.RangeIter():
        print(_k.decode(), _v.decode())

db_to_text()

导出leveldb数据库至文本文件,以','分隔。
安全兼容:当参数是字符串时,当作本地路径文件名处理,临时打开数据库。

def db_to_text(from_db, to_text):
    _db = leveldb.LevelDB(from_db, create_if_missing=False) if isinstance(from_db, str) else from_db
    with open(to_text, 'w', encoding='utf-8') as _f:
        for _k, _v in _db.RangeIter():
            _f.write(_k.decode() + ',' + _v.decode() + '\n')

text_to_db()

从文本文件导入至leveldb数据库。参数支持自定义分隔符。
安全兼容:当参数是字符串时,当作本地路径文件名处理,临时打开数据库。

def text_to_db(from_text, to_db, split_char):
    total, invalid = 0, 0
    _split = split_char if split_char else ','
    _db = leveldb.LevelDB(to_db, create_if_missing=True) if isinstance(to_db, str) else to_db
    with open(from_text, 'r', encoding='utf-8') as _f:
        lines = _f.readlines()
        total = len(lines)
        for line in lines:
            if not line:
                invalid += 1
                continue
            # line = line.strip()
            if _split in line:
                _sub = line.split(_split, 1)
                _db.Put(_sub[0].encode('utf-8'), _sub[1].encode('utf-8'))
            else:
                _db.Put(line, '')
        return total, invalid

db_to_excel()

导出leveldb数据库至Excel文件,返回总数。
Excel文件共2列,分别对应leveldb的Key,Value。
安全兼容:当参数是字符串时,当作本地路径文件名处理,临时打开数据库。

def db_to_excel(from_db, to_excel):
    _db = leveldb.LevelDB(from_db, create_if_missing=False) if isinstance(from_db, str) else from_db
    _wb = Workbook()
    _ws = _wb.active
    total = 0
    for _k, _v in _db.RangeIter():
        _ws.append([_k.decode(), _v.decode()])
        total += 1
    _wb.save(to_excel)
    return total

excel_to_db()

从Excel文件导入至leveldb数据库。
仅读取Excel文件中的前2列数据,对应leveldb的Key,Value。
安全兼容:当参数是字符串时,当作本地路径文件名处理,临时打开数据库。

def excel_to_db(from_excel, to_db):
    _wb = load_workbook(from_excel, read_only=True)
    _ws = _wb.active
    _db = leveldb.LevelDB(to_db, create_if_missing=True) if isinstance(to_db, str) else to_db
    total = 0
    for _row in _ws.iter_rows(min_row=2, min_col=1, max_col=1):
        if _row and _row[0] and _row[1]:
            _key, _value = '', ''
            if _row[0].data_type == cell.Cell.TYPE_STRING:
                _key = _row[0].value.encode('utf-8')
                _key = ''.join(_key.split())
            if _row[1].data_type == cell.Cell.TYPE_STRING:
                _value = _row[0].value.encode('utf-8')
                _value = ''.join(_value.split())
            _db.Put(_key, _value)
            total += 1

    _wb.close()
    return total

后记

这篇文档整理完成时,leveldb官网已经推出官方Python版本。
详见 https://plyvel.readthedocs.io/en/latest/

Morty Proxy This is a proxified and sanitized view of the page, visit original site.