いくつかの重複排除フィルタ実装クローラパイソン

デエンファシスフィルタの基底クラス

# 基于信摘要算法进行去重判断以及存储

# 1. 基于内存的存储
# 2. 基于redis的存储
# 3. 基于mysql的存储

import six
import hashlib


class BaseFilter(object):
    """基于信息摘要算法进行数据的去重以及判断"""
    def __init__(self, hash_func_name='md5',
                 redis_host='localhost',
                 redis_port=6379,
                 redis_db=15,
                 redis_key='filter',
                 mysql_url=None,

                 ):
        self.hash_func = getattr(hashlib, hash_func_name)
        self.redis_host = redis_host
        self.redis_port = redis_port
        self.redis_db = redis_db
        self.redis_key = redis_key
        self.mysql_url = mysql_url
        self.storage = self._get_storage()

    def _get_storage(self):
        """
        获取去重容器对象
        在具体的子类中实现
        :return:
        """
        pass

    def _safe_date(self, data):
        """
        python2 str --> python3 bytes
        python2 unicode --> python3 str
        :param data: 给定的原始数据
        :return: 二进制类型的字符串数据
        """
        if six.PY3:
            if isinstance(data, bytes):
                return data
            elif isinstance(data, str):
                return data.encode()
            else:
                raise Exception("请提供字符串数据")
        # elif six.PY2:
        #     if isinstance(data, str):
        #         return data
        #     elif isinstance(data, unicode):
        #         return data.encode()
        #     else:
        #         raise Exception("请提供字符串数据")

    def _get_hash_value(self, data):
        """
        根据给定的数据 返回对应的 hash 摘要信息
        :param data:
        :return:
        """
        # 创建一个 hash 对象
        hash_obj = self.hash_func()
        hash_obj.update(self._safe_date(data))
        hash_value = hash_obj.hexdigest()
        return hash_value

    def save(self, data):
        """
        根据 data 计算出对应的指纹进行存储
        :param data:
        :return:
        """
        hash_value = self._get_hash_value(data)
        return self._save(hash_value)

    def _save(self, hash_value):
        """
        交给对应的子类去具体实现
        :param hash_value:
        :return:
        """
    def is_exist(self, data):
        """
        判断给定的数据是否存在
        :param data:
        :return:
        """
        hash_value = self._get_hash_value(data)
        return self._is_exist(hash_value)

    def _is_exist(self, hash_value):
        """
        交给对应的子类去实现
        判断的结果是 True 或者是 False
        :param hash_value:
        :return:
        """

メモリベースのストレージの基本重量を決定します

from filter_tools.base_filter import BaseFilter


class MemoryFilter(BaseFilter):
    """
    基于 python 中的 set 结构进行去重判断依据的存储
    """

    def _get_storage(self):
        return set()

    def _save(self, hash_value):
        """
        利用 set 进行存储
        :param hash_value:
        :return:
        """
        self.storage.add(hash_value)  # 向 set 中添加数据

    def _is_exist(self, hash_value):
        if hash_value in self.storage:
            return True
        else:
            return False


if __name__ == "__main__":
    f = MemoryFilter()
    datas = ['ruiyang', 'Ruiyang', '33', 'pwd', "11", "22", "33", "ruiyang"]
    for d in datas:
        if f.is_exist(d):
            print("{} 数据已经存在".format(d))
            # print(f.storage)
        else:
            f.save(d)
            print("添加数据 {}".format(d))

永続ストアベースのRedisを達成するためのフィルタ重み

import redis

from filter_tools.base_filter import BaseFilter


class RedisFilter(BaseFilter):
    """
    基于redis的持久化存储的去重判断依据的实现
    """

    def _get_storage(self):
        """
        返回一个 redis 连接对象
        :return:
        """
        # client = redis.StrictRedis(host='localhost', port=6379, db=15)
        # return client

        # 增加 redis 连接对象的复用性
        pool = redis.ConnectionPool(host=self.redis_host,
                                    port=self.redis_port,
                                    db=self.redis_db)
        client = redis.StrictRedis(connection_pool=pool)
        return client

    def _save(self, hash_value):
        """
        利用 redis 的无序集合进行存储
        :param hash_value:
        :return:
        """
        return self.storage.sadd(self.redis_key, hash_value)

    def _is_exist(self, hash_value):
        """
        判断 redis 的无序集合中是否有对应的判断依据
        :param hash_value:
        :return:
        """
        # if self.storage.sismember(self.redis_key, hash_value):
        #     return True
        # else:
        #     return False
        return self.storage.sismember(self.redis_key, hash_value)


if __name__ == "__main__":
    f = RedisFilter()
    datas = ['ruiyang', 'Ruiyang', '33', 'pwd', "11", "22", "33", "ruiyang"]
    for d in datas:
        if f.is_exist(d):
            print("{} 数据已经存在".format(d))
            # print(f.storage)
        else:
            f.save(d)
            print("添加数据 {}".format(d))

永続ストアベースのMySQLを達成するためのフィルタ重み

from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

from filter_tools.base_filter import BaseFilter

Base = declarative_base()


class Filter(Base):
    __tablename__ = "filter"  # 对应mysql中的表名
    id = Column(Integer, primary_key=True)
    hash_value = Column(String(40), index=True, unique=True)  # 索引且唯一


class MqlFilter(BaseFilter):
    """
    基于 mysql 的去重判断依据的存储
    """

    def _get_storage(self):
        """
        返回一个 mysql 的连接对象 (在此处为 sqlalchemy 的连接对象)
        :return:
        """
        engine = create_engine(self.mysql_url)
        Base.metadata.create_all(engine)    # 创建表 如果已有就忽略
        session = sessionmaker(engine)
        return session

    def _save(self, hash_value):
        """
        利用 mysql 数据库进行存储
        :param hash_value:
        :return:
        """
        session = self.storage()
        _filter = Filter(hash_value=hash_value)
        session.add(_filter)
        session.commit()
        session.close()

    def _is_exist(self, hash_value):
        """
        判断 mysql 数据库中是否有对应的判断依据
        :param hash_value:
        :return:
        """
        session = self.storage()
        ret = session.query(Filter).filter_by(hash_value=hash_value).first()
        session.close()
        if ret is None:
            return False
        else:
            return True


if __name__ == "__main__":
    f = MqlFilter(mysql_url="mysql+pymysql://root:password@localhost:3306/db_name?charset=utf8")
    datas = ['ruiyang', 'Ruiyang', '33', 'pwd', "11", "22", "33", "ruiyang"]
    for d in datas:
        if f.is_exist(d):
            print("{} 数据已经存在".format(d))
            # print(f.storage)
        else:
            f.save(d)
            print("添加数据 {}".format(d))

ダイナミックストアのデータテーブルのMySQLデータベースを作成します。

from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

from filter_tools.base_filter import BaseFilter

Base = declarative_base()


# class Filter(Base):
#     __tablename__ = "filter"  # 对应mysql中的表名
#     id = Column(Integer, primary_key=True)
#     hash_value = Column(String(40), index=True, unique=True)  # 索引且唯一


class MqlFilter(BaseFilter):
    """
    基于 mysql 的去重判断依据的存储
    """
    def __init__(self, *args, **kwargs):

        # 因为不用项目的去重依据应该存储在不同的表中 所以我们需要为数据库动态创建

        # 动态创建类的两种办法
        # (1) 一种是直接将类写在初始化方法中
        # (2) 另外一种是使用 type 动态创建
        # class Filter(Base):
        #     # __tablename__ = "filter"  # 对应mysql中的表名
        #     __tablename__ = kwargs.get("mysql_table_name")
        #     id = Column(Integer, primary_key=True)
        #     hash_value = Column(String(40), index=True, unique=True)  # 索引且唯一
        # self.table = Filter

        self.table = type(
            kwargs.get("mysql_table_name"),
            (Base, ),
            dict(
                __tablename__=kwargs.get("mysql_table_name"),
                id=Column(Integer, primary_key=True),
                hash_value=Column(String(40), index=True, unique=True),
            )
        )
        BaseFilter.__init__(self, *args, **kwargs)

    def _get_storage(self):
        """
        返回一个 mysql 的连接对象 (在此处为 sqlalchemy 的连接对象)
        :return:
        """
        engine = create_engine(self.mysql_url)
        Base.metadata.create_all(engine)    # 创建表 如果已有就忽略
        session = sessionmaker(engine)
        return session

    def _save(self, hash_value):
        """
        利用 mysql 数据库进行存储
        :param hash_value:
        :return:
        """
        session = self.storage()
        _filter = self.table(hash_value=hash_value)
        session.add(_filter)
        session.commit()
        session.close()

    def _is_exist(self, hash_value):
        """
        判断 mysql 数据库中是否有对应的判断依据
        :param hash_value:
        :return:
        """
        session = self.storage()
        ret = session.query(self.table).filter_by(hash_value=hash_value).first()
        session.close()
        if ret is None:
            return False
        else:
            return True


if __name__ == "__main__":
    f = MqlFilter(
        # mysql_url="mysql+pymysql://root:password@localhost:3306/db_name?charset=utf8",
        mysql_table_name="test_filter"
                  )

    datas = ['ruiyang', 'Ruiyang', '33', 'pwd', "11", "22", "33", "ruiyang"]
    for d in datas:
        if f.is_exist(d):
            print("{} 数据已经存在".format(d))
            # print(f.storage)
        else:
            f.save(d)
            print("添加数据 {}".format(d))

追伸

更新:2020年2月4日

公開された291元の記事 ウォンの賞賛104 ビュー410 000 +

おすすめ

転載: blog.csdn.net/Enjolras_fuu/article/details/104166689