Przeglądaj źródła

Merge branch 'newbranch'

# Conflicts:
#	.gitignore
ChenYL 2 lat temu
rodzic
commit
08318a84ea
21 zmienionych plików z 7711 dodań i 0 usunięć
  1. 13 0
      .gitignore
  2. 41 0
      REMEAD.md
  3. 280 0
      agg_word.py
  4. 116 0
      cal.py
  5. 62 0
      config.py
  6. 97 0
      cut.py
  7. 1396 0
      data/stopwords/baidu_stopwords.txt
  8. 746 0
      data/stopwords/cn_stopwords.txt
  9. 767 0
      data/stopwords/hit_stopwords.txt
  10. 976 0
      data/stopwords/scu_stopwords.txt
  11. 1893 0
      data/stopwords/停用词.txt
  12. 52 0
      key.py
  13. 58 0
      key_index.py
  14. 427 0
      key_reverse.py
  15. 52 0
      key_reverse_index.py
  16. 218 0
      key_reverse_statistics.py
  17. 28 0
      logging.conf
  18. 84 0
      merge.py
  19. 156 0
      statistics.py
  20. 65 0
      stop_word.py
  21. 184 0
      tools.py

+ 13 - 0
.gitignore

@@ -1,3 +1,16 @@
+__pycache__/
+data/tmp/*.pkl
+data/tmp/*.txt
+data/tmp/*.csv
+data/pkl/*.pkl
+data/*.txt
+data/*.csv
+临时/
+data_bak/
+src_bak/
+data/analyse/
+data/analyse_bak/
+data/cache/
 # Byte-compiled / optimized / DLL files
 __pycache__/
 *.py[cod]

+ 41 - 0
REMEAD.md

@@ -0,0 +1,41 @@
+# 处理步骤
+
+1. 从5118下载泛词(csv文件)
+
+2. 对泛词进行分词处理(cut.py)
+
+    * 分词和词频统计
+    * 根据词频进行倒序排列
+
+3. 根据词频获取拓展词
+
+4. 把所有拓展词合并到一个文件中(merge.py)
+
+5. 生成关键词文件,包含三个要素:序号、关键词、分词结果(key.py)
+
+6. 对关键词文件生成索引文件(key_index.py)
+
+7. 根据关键词文件生成倒排文件(key_reverse.py)
+
+8. 根据关键词文件、索引文件、倒排文件生成最终的聚合分析文件(agg_word.py)
+
+
+# 进程相关
+1. 普通的只有一个进程
+2. 普通使用ProcessPoolExecutor只有4个进程
+3. 如果使用Manager会额外多一个进程
+
+# 文件位置相关
+1. with open 与 mmap 读取到的每行的位置是一样的
+
+# 文件读取速度比较
+1. 从单进程的角度看:仅以顺序读文件来说mmap的速度快很多,如果对内容进行编码,速度也较with open快一点
+2. 从多进程的角度看:仅以顺序读文件来说mmap的速度快很多,如果对内容进行编码,速度也较with open快一点
+3. 仅以顺序读取同一个文件,with open 与 mmap 均是 单进程读取一次的速度 比 多进程读取一次要快,而且with open的差距更明显
+4. 多进程分段读取中 mmap比with open快很多,with open非常的慢
+* 总结:
+    * mmap(单)>>mmap(单,对内容进行编码)>with open(单)
+    * mmap(多)>>mmap(多,对内容进行编码)>with open(多)
+    * (这个结论没啥用处,因为多进程一般是完成不同的任务)仅以顺序读取同一个文件,with open 与 mmap 均是 单进程读取一次的速度 比 多进程读取一次要快,而且with open的差距更明显
+    * 多进程分段读取中 mmap比with open快很多,with open非常的慢
+

+ 280 - 0
agg_word.py

@@ -0,0 +1,280 @@
+# -*- coding:utf-8 -*-
+
+from concurrent.futures import ProcessPoolExecutor, as_completed
+from functools import reduce
+from itertools import combinations
+import math
+import mmap
+import os
+from time import sleep, time
+from cal import cal_cos_sim
+
+import config
+import tools
+import stop_word
+import re
+import logging
+
+# 问题
+# 用线程处理IO高的部分
+# 主线程利用率极低
+# 优化代码,加快速度(目前速度:约1分钟100个关键词)
+
+# 已解决
+# 输出的格式不正确
+# 分析结果内容没有写入结果中
+# 移除祠根数等于1的词,不做分析
+# 减少重复加载 -> 解决:加入仅在子进程时才加载的判断
+
+tools.init_log()    
+
+def intesect(x, y):
+    """
+    计算集合的交集
+    """
+    return x & y
+
+if __name__ != "__main__":
+    # 停用词
+    stop_word_index = stop_word.load_stop_word()
+
+    # KEY表索引
+    key_index = tools.load_obj(config.KEY_INDEX_CACHE)
+
+    # 倒排表索引
+    reverse_index = tools.load_obj(config.KEY_REVERSE_INDEX_CACHE)
+
+    # 聚合阈值
+    agg_threshold = 0.8
+
+    # 正则提取
+    # 倒排表 索引
+    index_re = r"'(\d+)'"
+    index_pattern = re.compile(index_re, re.I)
+    # 关键词    
+    key_re = r"[^,]*,(.*),\["
+    key_pattern = re.compile(key_re, re.I)
+    # KEY表 词根
+    stem_re = r"'([^,]*)'"
+    stem_pattern = re.compile(stem_re, re.I)
+
+def sub_process(start_pos, end_pos):
+    """
+    子进程
+    """
+    pid = os.getpid()
+
+    logging.info("子进程-%d 开始执行任务,开始位置:%d,结束位置:%d" % (pid,start_pos, end_pos))
+
+    # 聚合结果
+    agg_result = []
+    
+    # 开始时间
+    start_time = time()
+
+    with open(config.KEY_FILE, "r", encoding=config.ENCODING_CHARSET) as f_key, \
+        mmap.mmap(f_key.fileno(), 0, access=mmap.ACCESS_READ) as f_key_mmap, \
+        open(config.KEY_REVERSE_FILE, "r", encoding=config.ENCODING_CHARSET) as f_reverse, \
+        mmap.mmap(f_reverse.fileno(), 0, access=mmap.ACCESS_READ) as f_reverse_mmap :
+        
+        # 把关键词索引转换成对应的位置
+        lower_pos = key_index[start_pos]
+        upper_pos = key_index[end_pos]
+
+        # 移动到开始位置
+        f_key_mmap.seek(lower_pos)
+
+        # 读取主关键词信息
+        a_keys = {}
+        while True:
+            # 校验当前位置是否越界
+            cur_pos = f_key_mmap.tell()
+            if cur_pos >= upper_pos:
+                break
+            
+            line = f_key_mmap.readline().decode("UTF-8")
+            # 提取 关键词、词根
+            key_m = key_pattern.match(line)
+            a_key = key_m.group(1)
+            a_stem = []
+            # 过滤停用词
+            tmp_stem = stem_pattern.findall(line)
+            for stem in tmp_stem:
+                if stem in stop_word_index:
+                    continue
+                a_stem.append(stem)
+            # 保存到容器,如果祠根数等于1则没有比较的价值
+            if len(a_stem) > 1:
+                a_keys[a_key]=a_stem
+
+        # 合并词根
+        all_stem = set()
+        for a_stem in a_keys.values():
+            for stem in a_stem:
+                all_stem.add(stem)
+
+        # 获取倒排信息
+        reverse_dict = {}
+        for stem in all_stem:
+            # 读取倒排表
+            f_reverse_mmap.seek(reverse_index[stem])
+            reverse_line = f_reverse_mmap.readline().decode("UTF-8")
+            # 提取 位置信息
+            b_indexs = index_pattern.findall(reverse_line)
+            reverse_dict[stem]=set(b_indexs)
+        
+        # 计算相关性
+        for a_key, a_stem in a_keys.items():
+            # 计算词根组合
+            logging.debug("子进程-%d 主关键词:%s 开始计算词根组合" % (pid, a_key))
+            tmp_stem = []
+            for stem in a_stem:
+                tmp_stem.append(stem)
+            num = math.ceil(len(tmp_stem) * 0.7)
+            stem_combs = list (combinations(tmp_stem, num))
+            logging.debug("子进程-%d 主关键词:%s 计算词根组合结束" % (pid, a_key))
+
+            logging.debug("子进程-%d 主关键词:%s 开始获取词根涉及的关键词信息" % (pid, a_key))
+            # 计算词根涉及的关键词的交集
+            b_indexs = set()
+            for stem_comb in stem_combs:
+                indexs = [reverse_dict[a_stem] for a_stem in stem_comb]
+                for b_index in  reduce(intesect, indexs):
+                    b_indexs.add(b_index)
+            logging.debug("子进程-%d 主关键词:%s 总祠根数:%d" % (pid, a_key, len(b_indexs)))
+            # 获取关键词信息
+            b_keys = []
+            for b_index in b_indexs:
+                # 读取关键词数据
+                f_key_mmap.seek(key_index[int(b_index)])
+                line = f_key_mmap.readline().decode("UTF-8")
+                # 提取 关键词、词根
+                key_m = key_pattern.match(line)
+                b_key = key_m.group(1)
+                b_stem = stem_pattern.findall(line)
+                b_keys.append((b_key, b_stem))
+            logging.debug("子进程-%d 主关键词:%s 获取词根涉及的关键词信息结束,涉及计算关键词数量:%d" % (pid, a_key, len(b_keys)))
+
+            logging.debug("子进程-%d 主关键词:%s 开始计算相关性" % (pid, a_key))
+            # 结果容器
+            correlation_key = []
+            correlation_key.append(a_key)
+            # 计算相关性
+            if b_keys:
+                for b_key, b_stem in b_keys:
+                    try:
+                        val = cal_cos_sim(a_key, a_stem, b_key, b_stem)
+                        if val >= agg_threshold:
+                            correlation_key.append(b_key)
+                    except Exception as e:
+                        logging.error("主关键词:%s 发生异常,涉及的副关键词信息-关键词:%s,分词:%s" % (a_key, b_key, b_stem), e)
+
+                # 有内容则进行保存
+                if len(correlation_key) > 1:
+                    agg_result.append(correlation_key)
+            logging.debug("子进程-%d 主关键词:%s 计算相关性结束,相关的关键词数据量:%d" % (pid, a_key, (len(correlation_key)-1)))
+
+            
+    logging.info("子进程-%d 执行任务结束,耗时:%f" % (pid, (time() - start_time)))
+
+    return {
+        "agg_result": agg_result,
+        "start_pos": start_pos
+    }
+            
+def main_process():
+    """
+    主进程
+    """
+
+    # 进程数
+    process_num = 4
+
+    # KEY 表总长度
+    total_task = 14500028
+
+    # 任务数量
+    per_task_num = 100
+
+    # 划分子任务:任务进度记录、任务列表
+    process_record, tasks = avg_split_task(total_task, per_task_num)
+
+    with ProcessPoolExecutor(max_workers=process_num) as process_pool, \
+        open(config.AGG_FILE, "a", encoding=config.ENCODING_CHARSET) as f:
+
+        logging.info("主进程:提交任务到子进程")
+        process_futures = [process_pool.submit(sub_process, task[0], task[1]) for task in tasks]
+        
+        for p_future in as_completed(process_futures):
+            logging.debug("主进程:子进程返回部分数据")
+            result = p_future.result()
+
+            # 记录处理进度
+            cur_pos = result["start_pos"]
+            process_record[cur_pos//per_task_num]=1
+
+            # 保存分析结果
+            if result:
+                logging.debug("主进程:存在有效数据开始处理")
+                for correlation_key in result["agg_result"]:
+                    f.write("\n######开始######\n")
+                    for key in correlation_key:
+                        f.write("%s\n" % key)
+            
+            # 保存处理进度
+            tools.save_obj(config.ANALYSE_PROCESS_CACHE, process_record)
+
+            tools.tip(total_task, cur_pos)
+            
+
+                
+
+def avg_split_task(total:int, split_internal:int):
+    """
+    平分任务
+    """
+    # 任务列表
+    tasks = None
+    # 任务进度记录
+    process_record = None
+
+    # 分割的任务份数
+    split_num = math.ceil(total / split_internal)
+
+    # 平分
+    tmp_lists = []
+    for i in range(split_num):
+        # 计算平分点在列表中的位置
+        start_pos = i * split_internal
+        end_pos = i * split_internal + split_internal
+        # 如果超过列表大小需要额外处理
+        if end_pos >= total:
+            end_pos = None
+        tmp_lists.append([start_pos,end_pos])
+    
+    # 加载进度缓存
+    if os.path.exists(config.ANALYSE_PROCESS_CACHE):
+        logging.debug("存在分析进度缓存")
+        process_record = tools.load_obj(config.ANALYSE_PROCESS_CACHE)
+    
+    # 更新任务列表
+    if process_record:
+        tasks = []
+        for task in tmp_lists:
+            pos = task[0] // split_internal
+            if not process_record[pos]:
+                tasks.append(task)
+    else:
+        tasks = tmp_lists
+        process_record = [0 for i in range(len(tmp_lists))]
+
+    return process_record, tasks
+
+if __name__ == "__main__":
+
+    TITLE = "(多进程版 fast_14.py)聚合文件"
+    tools.log_start_msg(TITLE)
+
+    main_process()
+
+    tools.log_end_msg(TITLE)

+ 116 - 0
cal.py

@@ -0,0 +1,116 @@
+# -*- coding:utf-8 -*-
+
+import config
+import re
+import numpy as np
+
+def merge_stem(a_stem:list, b_stem:list):
+    """
+    合并词根
+    """
+    return list(set(a_stem).union(set(b_stem)))
+
+def gen_word_vec(a_word:str, b_word:str, stem:list):
+    """
+    生成词向量
+    """
+    a_vec, b_vec = [], []
+    for word in stem:
+        # if re.findall(word, config.RE_SPECIAL_SIMBOL):
+        if word in config.RE_SPECIAL_SIMBOL:
+            word = "\\" + word
+        if word == "c++":
+            word = "c\\+\\+"
+        a_vec.append(len(re.findall(word, a_word)))
+        b_vec.append(len(re.findall(word, b_word)))
+    return a_vec, b_vec
+
+def col_sim(vec1, vec2):
+    """
+    计算余弦相似性
+    """
+    return vec1.dot(vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))
+
+
+def cal_cos_sim(a_word:str, a_stem:list, b_word:str, b_stem:list):
+    """
+    计算余弦相似性
+    """
+    union_stem = merge_stem(a_stem, b_stem)
+    a_vec, b_vec = gen_word_vec(a_word, b_word, union_stem)
+    val = col_sim(np.array(a_vec), np.array(b_vec))
+    return val
+
+
+if __name__ == "__main__":
+
+    # a_word= "QQ邮箱格式怎么写"
+    # b_word= "QQ邮箱格式如何写"
+    # a_word_root = ['QQ', '邮箱', '格式', '怎么', '写']
+    # b_word_root = ['QQ', '邮箱', '格式', '如何', '写']
+    # print(cal_cos_sim(a_word, a_word_root, b_word, b_word_root))
+
+     # 合并词根,用于生成词向量
+    # union_word_root = merge_stem(a_word_root, b_word_root)
+    # print(union_word_root)
+
+    # # 生成词向量
+    # a_vec, b_vec = gen_word_vec(a_word, b_word, union_word_root)
+    # print(a_vec)
+    # print(b_vec)
+    # # a_vec = [1,1,1,1,0,1]
+    # # b_vec = [1,1,1,0,1,1]
+    # print(col_sim(np.array(a_vec), np.array(b_vec)))
+
+    # s = "0,腋下长了一个小疙瘩是什么东西,['腋下', '长', '了', '一个', '小', '疙瘩', '是', '什么', '东西']"
+    # s_r = r"'([^,]*)'"
+    # pattern = re.compile(s_r, re.I)
+    # for i in pattern.findall(s):
+    #     print(i)
+    
+    # s_r = r"([\d]*),(.*),\["
+    # pattern = re.compile(s_r, re.I)
+    # m = pattern.match(s)
+    # for i in m.groups():
+    #     print(i)
+
+    # import mmap
+    # with open(config.KEY_FILE, "r", encoding=config.ENCODING_CHARSET) as f_key, \
+    #     mmap.mmap(f_key.fileno(), 0, access=mmap.ACCESS_READ) as f_key_mmap:
+
+    #     key_info_re = r"([\d]*),(.*),\["
+    #     key_info_pattern = re.compile(key_info_re, re.I)
+
+    #     s_r = r"'([^,]*)'"
+    #     s_pattern = re.compile(s_r, re.I)
+
+    #     a_line = f_key_mmap.readline().decode("UTF-8")
+    #     b_line = f_key_mmap.readline().decode("UTF-8")
+
+    #     a_m = key_info_pattern.match(a_line)
+    #     a_key = a_m.group(2)
+    #     a_stem = s_pattern.findall(a_line)
+    #     print(a_stem)
+
+    #     b_m = key_info_pattern.match(b_line)
+    #     b_key = b_m.group(2)
+    #     b_stem = s_pattern.findall(b_line)
+    #     print(b_stem)
+
+    #     print(cal_cos_sim(a_key, a_stem, b_key, b_stem))
+
+    # a_key = "吃什么东西减肥最快"
+    # a_stem = ['吃', '什么', '东西', '减肥', '最快']
+
+    # b_key="vc++读写什么文件最快"
+    # b_stem =['v', 'c++', '读写', '什么', '文件', '最快']
+    # print(cal_cos_sim(a_key, a_stem, b_key, b_stem))
+
+    # print(re.findall("c\\+\\+", "vc++读写什么文件最快"))
+    
+    
+    print("".join([".", "?", "^", "$", "*", "+", "\\", "[", "]", "|", "{", "}", "(", ")"]))
+    # s = r"([.?^$*+\[]|{}()])"
+    s=r"([\\])"
+    re.findall(s, "vc++读写什么文件最快")
+    print(re.findall(s, "vc++读写什么文件\最快"))

+ 62 - 0
config.py

@@ -0,0 +1,62 @@
+# -*- coding:utf-8 -*-
+
+# 文件编码格式
+ENCODING_CHARSET = "UTF-8"
+
+# 分词与词频统计
+CUT_FILE = "./data/tmp/cut.csv"
+
+# 拓展词合并文件
+MERGE_FILE = "./data/tmp/merge.csv"
+
+# 排除合并的文件
+MERGE_EXCLUDE_FILES = ['打开乱码如何处理?.txt']
+
+# 关键词文件(包含三要素:序号、关键词、词根)
+KEY_FILE = "./data/tmp/key.csv"
+
+# 关键词索引文件(包含两个要素:关键词序号、在文件中的位置)(暂时弃用)
+KEY_INDEX_FILE = "./data/tmp/key_index.csv"
+
+# 关键词索引模型 缓存 (包含两个要素:关键词序号、在文件中的位置)
+KEY_INDEX_CACHE = "./data/cache/key_index.pkl"
+
+# 关键词倒排文件(包含两个要素:词根、关键词序号)
+KEY_REVERSE_FILE = "./data/tmp/key_reverse.csv"
+
+# 关键词倒排索引模型 缓存 (包含两个要素:词根、位置)
+KEY_REVERSE_INDEX_CACHE = "./data/cache/key_reverse_index.pkl"
+
+# 关键词倒排文件 数据统计 (包含两个要素:词根,涉及的关键词数量)
+KEY_REVERSE_STATISTICS_FILE = "./data/tmp/key_reverse_statistics.csv"
+
+# 关键词倒排索引热点 缓存 (包含两个要素:词根、位置)
+KEY_REVERSE_INDEX_HOT_CACHE = "./data/cache/key_reverse_index_hot.pkl"
+
+# 最终的聚合分析结果存放文件
+AGG_ANALYSE_FILE = "./data/analyse/%s.csv"
+
+# 聚合结果
+AGG_FILE = "./data/agg_analyse.csv"
+
+# 停用词存放文件夹
+STOP_WORD_DIR = "./data/stopwords"
+
+# 停用词模型 缓存
+STOP_WORD_CACHE = "./data/cache/stop_word.pkl"
+
+# 分析BITMAP模型 缓存
+ANALYSE_BITMAP_CACHE = "./data/cache/analyse_bitmap.pkl"
+
+# 分析进度模型 缓存
+ANALYSE_PROCESS_CACHE = "./data/cache/analyse_process.pkl"
+
+# 正则表达式中需要额外处理的特殊符号
+# RE_SPECIAL_SIMBOL = "'.', '?', '^', '$', '*', '+', '\\', '[', ']', '|', '{', '}', '(', ')"
+RE_SPECIAL_SIMBOL = [".", "?", "^", "$", "*", "+", "\\", "[", "]", "|", "{", "}", "(", ")"]
+
+# 百分比进度提示
+PRECENT_TIPS = 0.01
+
+# 正则提取关键词表中的信息
+KEY_RE_PATTERAN = r"(\d+),([^,]*),(.*)"

+ 97 - 0
cut.py

@@ -0,0 +1,97 @@
+# -*- coding:utf-8 -*-
+
+import config
+import os
+import tools
+import jieba
+import logging
+import logging.config
+
+from stop_word import load_stop_word
+
+TITLE = "分词处理"
+
+# 待处理的数据文件
+DATA_FILE = "E:\Download\怎么长尾词_1655561719.csv"
+
+def cut_word_and_statistics(data):
+
+    """
+    分词并统计词频
+    """
+
+    logging.info("开始执行分词操作并进行词频统计")
+
+    # 分词结果容器
+    key_dict = {}
+    # 停用词
+    stop_word = load_stop_word()
+    # 待处理数据总数量
+    total_num = len(data)
+
+    logging.info("共需处理 %d 条数据" % total_num)
+
+    for i, item in enumerate(data):
+        # 只需要第一列的数据
+        longTailKey = item.split(",")[0]
+        # 移除换行符
+        longTailKey = longTailKey.replace("\n", "")
+        # 分词
+        cutWord = jieba.cut_for_search(longTailKey)
+
+        # 统计
+        for word in cutWord:
+
+            # 过滤停用词
+            if word in stop_word:
+                continue
+
+            if word in key_dict:
+                key_dict[word] = key_dict[word] + 1
+            else:
+                key_dict[word] = 1
+        
+        # 进度提示
+        tools.tip(total_num, i)
+        
+
+    # 根据词频倒序排列
+    logging.info("根据词频进行倒序排列")
+    sorted_key_list = sorted(key_dict.items(), key=lambda x: x[1], reverse=True)
+
+    logging.info("分词操作并进行词频统计 结束")
+
+    return sorted_key_list
+
+def main():
+
+    # 日志初始化
+    tools.init_log()
+
+    tools.log_start_msg(TITLE)
+
+    if not os.path.exists(DATA_FILE):
+        logging.warning("待处理的数据文件不存在:%s" % DATA_FILE)
+        return
+
+    # 读取数据
+    logging.info("正在读取待处理的数据文件:%s" % DATA_FILE)
+    lines = None
+    with open(DATA_FILE, "r", encoding=config.ENCODING_CHARSET) as f:
+        lines = f.readlines()
+    
+    # 执行分词和词频统计(跳过前两行)
+    word_root_list = cut_word_and_statistics(lines[2:])
+
+    # 导出数据
+    logging.info("正在导出分词数据,位置:%s" % config.CUT_FILE)
+    with open(config.CUT_FILE, "w", encoding=config.ENCODING_CHARSET) as f:
+        for key, count in word_root_list:
+            f.write("%s,%d\n" % (key, count))
+
+    tools.log_end_msg(TITLE)
+
+
+if __name__ == '__main__':
+    main()
+

+ 1396 - 0
data/stopwords/baidu_stopwords.txt

@@ -0,0 +1,1396 @@
+--
+?
+“
+”
+》
+--
+able
+about
+above
+according
+accordingly
+across
+actually
+after
+afterwards
+again
+against
+ain't
+all
+allow
+allows
+almost
+alone
+along
+already
+also
+although
+always
+am
+among
+amongst
+an
+and
+another
+any
+anybody
+anyhow
+anyone
+anything
+anyway
+anyways
+anywhere
+apart
+appear
+appreciate
+appropriate
+are
+aren't
+around
+as
+a's
+aside
+ask
+asking
+associated
+at
+available
+away
+awfully
+be
+became
+because
+become
+becomes
+becoming
+been
+before
+beforehand
+behind
+being
+believe
+below
+beside
+besides
+best
+better
+between
+beyond
+both
+brief
+but
+by
+came
+can
+cannot
+cant
+can't
+cause
+causes
+certain
+certainly
+changes
+clearly
+c'mon
+co
+com
+come
+comes
+concerning
+consequently
+consider
+considering
+contain
+containing
+contains
+corresponding
+could
+couldn't
+course
+c's
+currently
+definitely
+described
+despite
+did
+didn't
+different
+do
+does
+doesn't
+doing
+done
+don't
+down
+downwards
+during
+each
+edu
+eg
+eight
+either
+else
+elsewhere
+enough
+entirely
+especially
+et
+etc
+even
+ever
+every
+everybody
+everyone
+everything
+everywhere
+ex
+exactly
+example
+except
+far
+few
+fifth
+first
+five
+followed
+following
+follows
+for
+former
+formerly
+forth
+four
+from
+further
+furthermore
+get
+gets
+getting
+given
+gives
+go
+goes
+going
+gone
+got
+gotten
+greetings
+had
+hadn't
+happens
+hardly
+has
+hasn't
+have
+haven't
+having
+he
+hello
+help
+hence
+her
+here
+hereafter
+hereby
+herein
+here's
+hereupon
+hers
+herself
+he's
+hi
+him
+himself
+his
+hither
+hopefully
+how
+howbeit
+however
+i'd
+ie
+if
+ignored
+i'll
+i'm
+immediate
+in
+inasmuch
+inc
+indeed
+indicate
+indicated
+indicates
+inner
+insofar
+instead
+into
+inward
+is
+isn't
+it
+it'd
+it'll
+its
+it's
+itself
+i've
+just
+keep
+keeps
+kept
+know
+known
+knows
+last
+lately
+later
+latter
+latterly
+least
+less
+lest
+let
+let's
+like
+liked
+likely
+little
+look
+looking
+looks
+ltd
+mainly
+many
+may
+maybe
+me
+mean
+meanwhile
+merely
+might
+more
+moreover
+most
+mostly
+much
+must
+my
+myself
+name
+namely
+nd
+near
+nearly
+necessary
+need
+needs
+neither
+never
+nevertheless
+new
+next
+nine
+no
+nobody
+non
+none
+noone
+nor
+normally
+not
+nothing
+novel
+now
+nowhere
+obviously
+of
+off
+often
+oh
+ok
+okay
+old
+on
+once
+one
+ones
+only
+onto
+or
+other
+others
+otherwise
+ought
+our
+ours
+ourselves
+out
+outside
+over
+overall
+own
+particular
+particularly
+per
+perhaps
+placed
+please
+plus
+possible
+presumably
+probably
+provides
+que
+quite
+qv
+rather
+rd
+re
+really
+reasonably
+regarding
+regardless
+regards
+relatively
+respectively
+right
+said
+same
+saw
+say
+saying
+says
+second
+secondly
+see
+seeing
+seem
+seemed
+seeming
+seems
+seen
+self
+selves
+sensible
+sent
+serious
+seriously
+seven
+several
+shall
+she
+should
+shouldn't
+since
+six
+so
+some
+somebody
+somehow
+someone
+something
+sometime
+sometimes
+somewhat
+somewhere
+soon
+sorry
+specified
+specify
+specifying
+still
+sub
+such
+sup
+sure
+take
+taken
+tell
+tends
+th
+than
+thank
+thanks
+thanx
+that
+thats
+that's
+the
+their
+theirs
+them
+themselves
+then
+thence
+there
+thereafter
+thereby
+therefore
+therein
+theres
+there's
+thereupon
+these
+they
+they'd
+they'll
+they're
+they've
+think
+third
+this
+thorough
+thoroughly
+those
+though
+three
+through
+throughout
+thru
+thus
+to
+together
+too
+took
+toward
+towards
+tried
+tries
+truly
+try
+trying
+t's
+twice
+two
+un
+under
+unfortunately
+unless
+unlikely
+until
+unto
+up
+upon
+us
+use
+used
+useful
+uses
+using
+usually
+value
+various
+very
+via
+viz
+vs
+want
+wants
+was
+wasn't
+way
+we
+we'd
+welcome
+well
+we'll
+went
+were
+we're
+weren't
+we've
+what
+whatever
+what's
+when
+whence
+whenever
+where
+whereafter
+whereas
+whereby
+wherein
+where's
+whereupon
+wherever
+whether
+which
+while
+whither
+who
+whoever
+whole
+whom
+who's
+whose
+why
+will
+willing
+wish
+with
+within
+without
+wonder
+won't
+would
+wouldn't
+yes
+yet
+you
+you'd
+you'll
+your
+you're
+yours
+yourself
+yourselves
+you've
+zero
+zt
+ZT
+zz
+ZZ
+一
+一下
+一些
+一切
+一则
+一天
+一定
+一方面
+一旦
+一时
+一来
+一样
+一次
+一片
+一直
+一致
+一般
+一起
+一边
+一面
+万一
+上下
+上升
+上去
+上来
+上述
+上面
+下列
+下去
+下来
+下面
+不一
+不久
+不仅
+不会
+不但
+不光
+不单
+不变
+不只
+不可
+不同
+不够
+不如
+不得
+不怕
+不惟
+不成
+不拘
+不敢
+不断
+不是
+不比
+不然
+不特
+不独
+不管
+不能
+不要
+不论
+不足
+不过
+不问
+与
+与其
+与否
+与此同时
+专门
+且
+两者
+严格
+严重
+个
+个人
+个别
+中小
+中间
+丰富
+临
+为
+为主
+为了
+为什么
+为什麽
+为何
+为着
+主张
+主要
+举行
+乃
+乃至
+么
+之
+之一
+之前
+之后
+之後
+之所以
+之类
+乌乎
+乎
+乘
+也
+也好
+也是
+也罢
+了
+了解
+争取
+于
+于是
+于是乎
+云云
+互相
+产生
+人们
+人家
+什么
+什么样
+什麽
+今后
+今天
+今年
+今後
+仍然
+从
+从事
+从而
+他
+他人
+他们
+他的
+代替
+以
+以上
+以下
+以为
+以便
+以免
+以前
+以及
+以后
+以外
+以後
+以来
+以至
+以至于
+以致
+们
+任
+任何
+任凭
+任务
+企图
+伟大
+似乎
+似的
+但
+但是
+何
+何况
+何处
+何时
+作为
+你
+你们
+你的
+使得
+使用
+例如
+依
+依照
+依靠
+促进
+保持
+俺
+俺们
+倘
+倘使
+倘或
+倘然
+倘若
+假使
+假如
+假若
+做到
+像
+允许
+充分
+先后
+先後
+先生
+全部
+全面
+兮
+共同
+关于
+其
+其一
+其中
+其二
+其他
+其余
+其它
+其实
+其次
+具体
+具体地说
+具体说来
+具有
+再者
+再说
+冒
+冲
+决定
+况且
+准备
+几
+几乎
+几时
+凭
+凭借
+出去
+出来
+出现
+分别
+则
+别
+别的
+别说
+到
+前后
+前者
+前进
+前面
+加之
+加以
+加入
+加强
+十分
+即
+即令
+即使
+即便
+即或
+即若
+却不
+原来
+又
+及
+及其
+及时
+及至
+双方
+反之
+反应
+反映
+反过来
+反过来说
+取得
+受到
+变成
+另
+另一方面
+另外
+只是
+只有
+只要
+只限
+叫
+叫做
+召开
+叮咚
+可
+可以
+可是
+可能
+可见
+各
+各个
+各人
+各位
+各地
+各种
+各级
+各自
+合理
+同
+同一
+同时
+同样
+后来
+后面
+向
+向着
+吓
+吗
+否则
+吧
+吧哒
+吱
+呀
+呃
+呕
+呗
+呜
+呜呼
+呢
+周围
+呵
+呸
+呼哧
+咋
+和
+咚
+咦
+咱
+咱们
+咳
+哇
+哈
+哈哈
+哉
+哎
+哎呀
+哎哟
+哗
+哟
+哦
+哩
+哪
+哪个
+哪些
+哪儿
+哪天
+哪年
+哪怕
+哪样
+哪边
+哪里
+哼
+哼唷
+唉
+啊
+啐
+啥
+啦
+啪达
+喂
+喏
+喔唷
+嗡嗡
+嗬
+嗯
+嗳
+嘎
+嘎登
+嘘
+嘛
+嘻
+嘿
+因
+因为
+因此
+因而
+固然
+在
+在下
+地
+坚决
+坚持
+基本
+处理
+复杂
+多
+多少
+多数
+多次
+大力
+大多数
+大大
+大家
+大批
+大约
+大量
+失去
+她
+她们
+她的
+好的
+好象
+如
+如上所述
+如下
+如何
+如其
+如果
+如此
+如若
+存在
+宁
+宁可
+宁愿
+宁肯
+它
+它们
+它们的
+它的
+安全
+完全
+完成
+实现
+实际
+宣布
+容易
+密切
+对
+对于
+对应
+将
+少数
+尔后
+尚且
+尤其
+就
+就是
+就是说
+尽
+尽管
+属于
+岂但
+左右
+巨大
+巩固
+己
+已经
+帮助
+常常
+并
+并不
+并不是
+并且
+并没有
+广大
+广泛
+应当
+应用
+应该
+开外
+开始
+开展
+引起
+强烈
+强调
+归
+当
+当前
+当时
+当然
+当着
+形成
+彻底
+彼
+彼此
+往
+往往
+待
+後来
+後面
+得
+得出
+得到
+心里
+必然
+必要
+必须
+怎
+怎么
+怎么办
+怎么样
+怎样
+怎麽
+总之
+总是
+总的来看
+总的来说
+总的说来
+总结
+总而言之
+恰恰相反
+您
+意思
+愿意
+慢说
+成为
+我
+我们
+我的
+或
+或是
+或者
+战斗
+所
+所以
+所有
+所谓
+打
+扩大
+把
+抑或
+拿
+按
+按照
+换句话说
+换言之
+据
+掌握
+接着
+接著
+故
+故此
+整个
+方便
+方面
+旁人
+无宁
+无法
+无论
+既
+既是
+既然
+时候
+明显
+明确
+是
+是否
+是的
+显然
+显著
+普通
+普遍
+更加
+曾经
+替
+最后
+最大
+最好
+最後
+最近
+最高
+有
+有些
+有关
+有利
+有力
+有所
+有效
+有时
+有点
+有的
+有着
+有著
+望
+朝
+朝着
+本
+本着
+来
+来着
+极了
+构成
+果然
+果真
+某
+某个
+某些
+根据
+根本
+欢迎
+正在
+正如
+正常
+此
+此外
+此时
+此间
+毋宁
+每
+每个
+每天
+每年
+每当
+比
+比如
+比方
+比较
+毫不
+没有
+沿
+沿着
+注意
+深入
+清楚
+满足
+漫说
+焉
+然则
+然后
+然後
+然而
+照
+照着
+特别是
+特殊
+特点
+现代
+现在
+甚么
+甚而
+甚至
+用
+由
+由于
+由此可见
+的
+的话
+目前
+直到
+直接
+相似
+相信
+相反
+相同
+相对
+相对而言
+相应
+相当
+相等
+省得
+看出
+看到
+看来
+看看
+看见
+真是
+真正
+着
+着呢
+矣
+知道
+确定
+离
+积极
+移动
+突出
+突然
+立即
+第
+等
+等等
+管
+紧接着
+纵
+纵令
+纵使
+纵然
+练习
+组成
+经
+经常
+经过
+结合
+结果
+给
+绝对
+继续
+继而
+维持
+综上所述
+罢了
+考虑
+者
+而
+而且
+而况
+而外
+而已
+而是
+而言
+联系
+能
+能否
+能够
+腾
+自
+自个儿
+自从
+自各儿
+自家
+自己
+自身
+至
+至于
+良好
+若
+若是
+若非
+范围
+莫若
+获得
+虽
+虽则
+虽然
+虽说
+行为
+行动
+表明
+表示
+被
+要
+要不
+要不是
+要不然
+要么
+要是
+要求
+规定
+觉得
+认为
+认真
+认识
+让
+许多
+论
+设使
+设若
+该
+说明
+诸位
+谁
+谁知
+赶
+起
+起来
+起见
+趁
+趁着
+越是
+跟
+转动
+转变
+转贴
+较
+较之
+边
+达到
+迅速
+过
+过去
+过来
+运用
+还是
+还有
+这
+这个
+这么
+这么些
+这么样
+这么点儿
+这些
+这会儿
+这儿
+这就是说
+这时
+这样
+这点
+这种
+这边
+这里
+这麽
+进入
+进步
+进而
+进行
+连
+连同
+适应
+适当
+适用
+逐步
+逐渐
+通常
+通过
+造成
+遇到
+遭到
+避免
+那
+那个
+那么
+那么些
+那么样
+那些
+那会儿
+那儿
+那时
+那样
+那边
+那里
+那麽
+部分
+鄙人
+采取
+里面
+重大
+重新
+重要
+鉴于
+问题
+防止
+阿
+附近
+限制
+除
+除了
+除此之外
+除非
+随
+随着
+随著
+集中
+需要
+非但
+非常
+非徒
+靠
+顺
+顺着
+首先
+高兴
+是不是
+说说
+ 

+ 746 - 0
data/stopwords/cn_stopwords.txt

@@ -0,0 +1,746 @@
+$
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+?
+_
+“
+”
+、
+。
+《
+》
+一
+一些
+一何
+一切
+一则
+一方面
+一旦
+一来
+一样
+一般
+一转眼
+万一
+上
+上下
+下
+不
+不仅
+不但
+不光
+不单
+不只
+不外乎
+不如
+不妨
+不尽
+不尽然
+不得
+不怕
+不惟
+不成
+不拘
+不料
+不是
+不比
+不然
+不特
+不独
+不管
+不至于
+不若
+不论
+不过
+不问
+与
+与其
+与其说
+与否
+与此同时
+且
+且不说
+且说
+两者
+个
+个别
+临
+为
+为了
+为什么
+为何
+为止
+为此
+为着
+乃
+乃至
+乃至于
+么
+之
+之一
+之所以
+之类
+乌乎
+乎
+乘
+也
+也好
+也罢
+了
+二来
+于
+于是
+于是乎
+云云
+云尔
+些
+亦
+人
+人们
+人家
+什么
+什么样
+今
+介于
+仍
+仍旧
+从
+从此
+从而
+他
+他人
+他们
+以
+以上
+以为
+以便
+以免
+以及
+以故
+以期
+以来
+以至
+以至于
+以致
+们
+任
+任何
+任凭
+似的
+但
+但凡
+但是
+何
+何以
+何况
+何处
+何时
+余外
+作为
+你
+你们
+使
+使得
+例如
+依
+依据
+依照
+便于
+俺
+俺们
+倘
+倘使
+倘或
+倘然
+倘若
+借
+假使
+假如
+假若
+傥然
+像
+儿
+先不先
+光是
+全体
+全部
+兮
+关于
+其
+其一
+其中
+其二
+其他
+其余
+其它
+其次
+具体地说
+具体说来
+兼之
+内
+再
+再其次
+再则
+再有
+再者
+再者说
+再说
+冒
+冲
+况且
+几
+几时
+凡
+凡是
+凭
+凭借
+出于
+出来
+分别
+则
+则甚
+别
+别人
+别处
+别是
+别的
+别管
+别说
+到
+前后
+前此
+前者
+加之
+加以
+即
+即令
+即使
+即便
+即如
+即或
+即若
+却
+去
+又
+又及
+及
+及其
+及至
+反之
+反而
+反过来
+反过来说
+受到
+另
+另一方面
+另外
+另悉
+只
+只当
+只怕
+只是
+只有
+只消
+只要
+只限
+叫
+叮咚
+可
+可以
+可是
+可见
+各
+各个
+各位
+各种
+各自
+同
+同时
+后
+后者
+向
+向使
+向着
+吓
+吗
+否则
+吧
+吧哒
+吱
+呀
+呃
+呕
+呗
+呜
+呜呼
+呢
+呵
+呵呵
+呸
+呼哧
+咋
+和
+咚
+咦
+咧
+咱
+咱们
+咳
+哇
+哈
+哈哈
+哉
+哎
+哎呀
+哎哟
+哗
+哟
+哦
+哩
+哪
+哪个
+哪些
+哪儿
+哪天
+哪年
+哪怕
+哪样
+哪边
+哪里
+哼
+哼唷
+唉
+唯有
+啊
+啐
+啥
+啦
+啪达
+啷当
+喂
+喏
+喔唷
+喽
+嗡
+嗡嗡
+嗬
+嗯
+嗳
+嘎
+嘎登
+嘘
+嘛
+嘻
+嘿
+嘿嘿
+因
+因为
+因了
+因此
+因着
+因而
+固然
+在
+在下
+在于
+地
+基于
+处在
+多
+多么
+多少
+大
+大家
+她
+她们
+好
+如
+如上
+如上所述
+如下
+如何
+如其
+如同
+如是
+如果
+如此
+如若
+始而
+孰料
+孰知
+宁
+宁可
+宁愿
+宁肯
+它
+它们
+对
+对于
+对待
+对方
+对比
+将
+小
+尔
+尔后
+尔尔
+尚且
+就
+就是
+就是了
+就是说
+就算
+就要
+尽
+尽管
+尽管如此
+岂但
+己
+已
+已矣
+巴
+巴巴
+并
+并且
+并非
+庶乎
+庶几
+开外
+开始
+归
+归齐
+当
+当地
+当然
+当着
+彼
+彼时
+彼此
+往
+待
+很
+得
+得了
+怎
+怎么
+怎么办
+怎么样
+怎奈
+怎样
+总之
+总的来看
+总的来说
+总的说来
+总而言之
+恰恰相反
+您
+惟其
+慢说
+我
+我们
+或
+或则
+或是
+或曰
+或者
+截至
+所
+所以
+所在
+所幸
+所有
+才
+才能
+打
+打从
+把
+抑或
+拿
+按
+按照
+换句话说
+换言之
+据
+据此
+接着
+故
+故此
+故而
+旁人
+无
+无宁
+无论
+既
+既往
+既是
+既然
+时候
+是
+是以
+是的
+曾
+替
+替代
+最
+有
+有些
+有关
+有及
+有时
+有的
+望
+朝
+朝着
+本
+本人
+本地
+本着
+本身
+来
+来着
+来自
+来说
+极了
+果然
+果真
+某
+某个
+某些
+某某
+根据
+欤
+正值
+正如
+正巧
+正是
+此
+此地
+此处
+此外
+此时
+此次
+此间
+毋宁
+每
+每当
+比
+比及
+比如
+比方
+没奈何
+沿
+沿着
+漫说
+焉
+然则
+然后
+然而
+照
+照着
+犹且
+犹自
+甚且
+甚么
+甚或
+甚而
+甚至
+甚至于
+用
+用来
+由
+由于
+由是
+由此
+由此可见
+的
+的确
+的话
+直到
+相对而言
+省得
+看
+眨眼
+着
+着呢
+矣
+矣乎
+矣哉
+离
+竟而
+第
+等
+等到
+等等
+简言之
+管
+类如
+紧接着
+纵
+纵令
+纵使
+纵然
+经
+经过
+结果
+给
+继之
+继后
+继而
+综上所述
+罢了
+者
+而
+而且
+而况
+而后
+而外
+而已
+而是
+而言
+能
+能否
+腾
+自
+自个儿
+自从
+自各儿
+自后
+自家
+自己
+自打
+自身
+至
+至于
+至今
+至若
+致
+般的
+若
+若夫
+若是
+若果 
+若非
+莫不然
+莫如
+莫若
+虽
+虽则
+虽然
+虽说
+被
+要
+要不
+要不是
+要不然
+要么
+要是
+譬喻
+譬如
+让
+许多
+论
+设使
+设或
+设若
+诚如
+诚然
+该
+说来
+诸
+诸位
+诸如
+谁
+谁人
+谁料
+谁知
+贼死
+赖以
+赶
+起
+起见
+趁
+趁着
+越是
+距
+跟
+较
+较之
+边
+过
+还
+还是
+还有
+还要
+这
+这一来
+这个
+这么
+这么些
+这么样
+这么点儿
+这些
+这会儿
+这儿
+这就是说
+这时
+这样
+这次
+这般
+这边
+这里
+进而
+连
+连同
+逐步
+通过
+遵循
+遵照
+那
+那个
+那么
+那么些
+那么样
+那些
+那会儿
+那儿
+那时
+那样
+那般
+那边
+那里
+都
+鄙人
+鉴于
+针对
+阿
+除
+除了
+除外
+除开
+除此之外
+除非
+随
+随后
+随时
+随着
+难道说
+非但
+非徒
+非特
+非独
+靠
+顺
+顺着
+首先
+!
+,
+:
+;
+?

+ 767 - 0
data/stopwords/hit_stopwords.txt

@@ -0,0 +1,767 @@
+———
+》),
+)÷(1-
+”,
+)、
+=(
+:
+→
+℃ 
+&
+*
+一一
+~~~~
+’
+. 
+『
+.一
+./
+-- 
+』
+=″
+【
+[*]
+}>
+[⑤]]
+[①D]
+c]
+ng昉
+*
+//
+[
+]
+[②e]
+[②g]
+={
+}
+,也 
+‘
+A
+[①⑥]
+[②B] 
+[①a]
+[④a]
+[①③]
+[③h]
+③]
+1. 
+-- 
+[②b]
+’‘ 
+××× 
+[①⑧]
+0:2 
+=[
+[⑤b]
+[②c] 
+[④b]
+[②③]
+[③a]
+[④c]
+[①⑤]
+[①⑦]
+[①g]
+∈[ 
+[①⑨]
+[①④]
+[①c]
+[②f]
+[②⑧]
+[②①]
+[①C]
+[③c]
+[③g]
+[②⑤]
+[②②]
+一.
+[①h]
+.数
+[]
+[①B]
+数/
+[①i]
+[③e]
+[①①]
+[④d]
+[④e]
+[③b]
+[⑤a]
+[①A]
+[②⑧]
+[②⑦]
+[①d]
+[②j]
+〕〔
+][
+://
+′∈
+[②④
+[⑤e]
+12%
+b]
+...
+...................
+…………………………………………………③
+ZXFITL
+[③F]
+」
+[①o]
+]∧′=[ 
+∪φ∈
+′|
+{-
+②c
+}
+[③①]
+R.L.
+[①E]
+-[*]-
+↑
+.日 
+[②d]
+[②
+[②⑦]
+[②②]
+[③e]
+[①i]
+[①B]
+[①h]
+[①d]
+[①g]
+[①②]
+[②a]
+f]
+[⑩]
+a]
+[①e]
+[②h]
+[②⑥]
+[③d]
+[②⑩]
+e]
+〉
+】
+元/吨
+[②⑩]
+2.3%
+5:0  
+[①]
+::
+[②]
+[③]
+[④]
+[⑤]
+[⑥]
+[⑦]
+[⑧]
+[⑨] 
+……
+——
+?
+、
+。
+“
+”
+《
+》
+!
+,
+:
+;
+?
+.
+,
+.
+'
+? 
+———
+──
+? 
+—
+<
+>
+(
+)
+〔
+〕
+[
+]
+(
+)
+-
++
+~
+/
+/
+①
+②
+③
+④
+⑤
+⑥
+⑦
+⑧
+⑨
+⑩
+Ⅲ
+"
+;
+#
+@
+φ.
+■
+▲
+sub
+exp 
+sup
+sub
+Lex 
+#
+%
+&
+'
++
++ξ
+++
+-
+-β
+<
+<±
+<Δ
+<λ
+<φ
+<<
+=
+=
+=☆
+=-
+>
+>λ
+_
+~±
+~+
+[⑤f]
+[⑤d]
+[②i]
+≈ 
+[②G]
+[①f]
+LI
+㈧ 
+[-
+......
+〉
+[③⑩]
+第二
+一番
+一直
+一个
+一些
+许多
+种
+有的是
+也就是说
+末##末
+啊
+阿
+哎
+哎呀
+哎哟
+唉
+俺
+俺们
+按
+按照
+吧
+吧哒
+把
+罢了
+被
+本
+本着
+比
+比方
+比如
+鄙人
+彼
+彼此
+边
+别
+别的
+别说
+并
+并且
+不比
+不成
+不单
+不但
+不独
+不管
+不光
+不过
+不仅
+不拘
+不论
+不怕
+不然
+不如
+不特
+不惟
+不问
+不只
+朝
+朝着
+趁
+趁着
+乘
+冲
+除
+除此之外
+除非
+除了
+此
+此间
+此外
+从
+从而
+打
+待
+但
+但是
+当
+当着
+到
+得
+的
+的话
+等
+等等
+地
+第
+叮咚
+对
+对于
+多
+多少
+而
+而况
+而且
+而是
+而外
+而言
+而已
+尔后
+反过来
+反过来说
+反之
+非但
+非徒
+否则
+嘎
+嘎登
+该
+赶
+个
+各
+各个
+各位
+各种
+各自
+给
+根据
+跟
+故
+故此
+固然
+关于
+管
+归
+果然
+果真
+过
+哈
+哈哈
+呵
+和
+何
+何处
+何况
+何时
+嘿
+哼
+哼唷
+呼哧
+乎
+哗
+还是
+还有
+换句话说
+换言之
+或
+或是
+或者
+极了
+及
+及其
+及至
+即
+即便
+即或
+即令
+即若
+即使
+几
+几时
+己
+既
+既然
+既是
+继而
+加之
+假如
+假若
+假使
+鉴于
+将
+较
+较之
+叫
+接着
+结果
+借
+紧接着
+进而
+尽
+尽管
+经
+经过
+就
+就是
+就是说
+据
+具体地说
+具体说来
+开始
+开外
+靠
+咳
+可
+可见
+可是
+可以
+况且
+啦
+来
+来着
+离
+例如
+哩
+连
+连同
+两者
+了
+临
+另
+另外
+另一方面
+论
+嘛
+吗
+慢说
+漫说
+冒
+么
+每
+每当
+们
+莫若
+某
+某个
+某些
+拿
+哪
+哪边
+哪儿
+哪个
+哪里
+哪年
+哪怕
+哪天
+哪些
+哪样
+那
+那边
+那儿
+那个
+那会儿
+那里
+那么
+那么些
+那么样
+那时
+那些
+那样
+乃
+乃至
+呢
+能
+你
+你们
+您
+宁
+宁可
+宁肯
+宁愿
+哦
+呕
+啪达
+旁人
+呸
+凭
+凭借
+其
+其次
+其二
+其他
+其它
+其一
+其余
+其中
+起
+起见
+起见
+岂但
+恰恰相反
+前后
+前者
+且
+然而
+然后
+然则
+让
+人家
+任
+任何
+任凭
+如
+如此
+如果
+如何
+如其
+如若
+如上所述
+若
+若非
+若是
+啥
+上下
+尚且
+设若
+设使
+甚而
+甚么
+甚至
+省得
+时候
+什么
+什么样
+使得
+是
+是的
+首先
+谁
+谁知
+顺
+顺着
+似的
+虽
+虽然
+虽说
+虽则
+随
+随着
+所
+所以
+他
+他们
+他人
+它
+它们
+她
+她们
+倘
+倘或
+倘然
+倘若
+倘使
+腾
+替
+通过
+同
+同时
+哇
+万一
+往
+望
+为
+为何
+为了
+为什么
+为着
+喂
+嗡嗡
+我
+我们
+呜
+呜呼
+乌乎
+无论
+无宁
+毋宁
+嘻
+吓
+相对而言
+像
+向
+向着
+嘘
+呀
+焉
+沿
+沿着
+要
+要不
+要不然
+要不是
+要么
+要是
+也
+也罢
+也好
+一
+一般
+一旦
+一方面
+一来
+一切
+一样
+一则
+依
+依照
+矣
+以
+以便
+以及
+以免
+以至
+以至于
+以致
+抑或
+因
+因此
+因而
+因为
+哟
+用
+由
+由此可见
+由于
+有
+有的
+有关
+有些
+又
+于
+于是
+于是乎
+与
+与此同时
+与否
+与其
+越是
+云云
+哉
+再说
+再者
+在
+在下
+咱
+咱们
+则
+怎
+怎么
+怎么办
+怎么样
+怎样
+咋
+照
+照着
+者
+这
+这边
+这儿
+这个
+这会儿
+这就是说
+这里
+这么
+这么点儿
+这么些
+这么样
+这时
+这些
+这样
+正如
+吱
+之
+之类
+之所以
+之一
+只是
+只限
+只要
+只有
+至
+至于
+诸位
+着
+着呢
+自
+自从
+自个儿
+自各儿
+自己
+自家
+自身
+综上所述
+总的来看
+总的来说
+总的说来
+总而言之
+总之
+纵
+纵令
+纵然
+纵使
+遵照
+作为
+兮
+呃
+呗
+咚
+咦
+喏
+啐
+喔唷
+嗬
+嗯
+嗳

+ 976 - 0
data/stopwords/scu_stopwords.txt

@@ -0,0 +1,976 @@
+打开天窗说亮话
+到目前为止
+赶早不赶晚
+常言说得好
+何乐而不为
+毫无保留地
+由此可见
+这就是说
+这么点儿
+综上所述
+总的来看
+总的来说
+总的说来
+总而言之
+相对而言
+除此之外
+反过来说
+恰恰相反
+如上所述
+换句话说
+具体地说
+具体说来
+另一方面
+与此同时
+一则通过
+毫无例外
+不然的话
+从此以后
+从古到今
+从古至今
+从今以后
+大张旗鼓
+从无到有
+从早到晚
+弹指之间
+不亦乐乎
+不知不觉
+不止一次
+不择手段
+不可开交
+不可抗拒
+不仅仅是
+不管怎样
+挨家挨户
+长此下去
+长话短说
+除此而外
+除此以外
+除此之外
+得天独厚
+川流不息
+长期以来
+挨门挨户
+挨门逐户
+多多少少
+多多益善
+二话不说
+更进一步
+二话没说
+分期分批
+风雨无阻
+归根到底
+归根结底
+反之亦然
+大面儿上
+倒不如说
+成年累月
+换句话说
+或多或少
+简而言之
+接连不断
+尽如人意
+尽心竭力
+尽心尽力
+尽管如此
+据我所知
+具体地说
+具体来说
+具体说来
+近几年来
+每时每刻
+屡次三番
+三番两次
+三番五次
+三天两头
+另一方面
+老老实实
+年复一年
+恰恰相反
+顷刻之间
+穷年累月
+千万千万
+日复一日
+如此等等
+如前所述
+如上所述
+一方面
+切不可
+顷刻间
+全身心
+另方面
+另一个
+猛然间
+默默地
+就是说
+近年来
+尽可能
+接下来
+简言之
+急匆匆
+即是说
+基本上
+换言之
+充其极
+充其量
+暗地里
+反之则
+比如说
+背地里
+背靠背
+并没有
+不得不
+不得了
+不得已
+不仅仅
+不经意
+不能不
+不外乎
+不由得
+不怎么
+不至于
+策略地
+差不多
+常言道
+常言说
+多年来
+多年前
+差一点
+敞开儿
+抽冷子
+大不了
+反倒是
+反过来
+大体上
+当口儿
+倒不如
+怪不得
+动不动
+看起来
+看上去
+看样子
+够瞧的
+到了儿
+呆呆地
+来不及
+来得及
+到头来
+连日来
+于是乎
+为什么
+这会儿
+换言之
+那会儿
+那么些
+那么样
+什么样
+反过来
+紧接着
+就是说
+要不然
+要不是
+一方面
+以至于
+自个儿
+自各儿
+之所以
+这么些
+这么样
+怎么办
+怎么样
+谁知
+顺着
+似的
+虽然
+虽说
+虽则
+随着
+所以
+他们
+他人
+它们
+她们
+倘或
+倘然
+倘若
+倘使
+要么
+要是
+也罢
+也好
+以便
+依照
+以及
+以免
+以至
+以致
+抑或
+因此
+因而
+因为
+由于
+有的
+有关
+有些
+于是
+与否
+与其
+越是
+云云
+一般
+一旦
+一来
+一切
+一样
+同时
+万一
+为何
+为了
+为着
+嗡嗡
+我们
+呜呼
+乌乎
+无论
+无宁
+沿着
+毋宁
+向着
+照着
+怎么
+咱们
+在下
+再说
+再者
+怎样
+这边
+这儿
+这个
+这里
+这么
+这时
+这些
+这样
+正如
+之类
+之一
+只是
+只限
+只要
+只有
+至于
+诸位
+着呢
+纵令
+纵然
+纵使
+遵照
+作为
+喔唷
+自从
+自己
+自家
+自身
+总之
+要不
+哎呀
+哎哟
+俺们
+按照
+吧哒
+罢了
+本着
+比方
+比如
+鄙人
+彼此
+别的
+别说
+并且
+不比
+不成
+不单
+不但
+不独
+不管
+不光
+不过
+不仅
+不拘
+不论
+不怕
+不然
+不如
+不特
+不惟
+不问
+不只
+朝着
+趁着
+除非
+除了
+此间
+此外
+从而
+但是
+当着
+的话
+等等
+叮咚
+对于
+多少
+而况
+而且
+而是
+而外
+而言
+而已
+尔后
+反之
+非但
+非徒
+否则
+嘎登
+各个
+各位
+各种
+各自
+根据
+故此
+固然
+关于
+果然
+果真
+哈哈
+何处
+何况
+何时
+哼唷
+呼哧
+还是
+还有
+或是
+或者
+极了
+及其
+及至
+即便
+即或
+即令
+即若
+即使
+既然
+既是
+继而
+加之
+假如
+假若
+假使
+鉴于
+几时
+较之
+接着
+结果
+进而
+尽管
+经过
+就是
+可见
+可是
+可以
+况且
+开始
+开外
+来着
+例如
+连同
+两者
+另外
+慢说
+漫说
+每当
+莫若
+某个
+某些
+哪边
+哪儿
+哪个
+哪里
+哪年
+哪怕
+哪天
+哪些
+哪样
+那边
+那儿
+那个
+那里
+那么
+那时
+那些
+那样
+乃至
+宁可
+宁肯
+宁愿
+你们
+啪达
+旁人
+凭借
+其次
+其二
+其他
+其它
+其一
+其余
+其中
+起见
+起见
+岂但
+前后
+前者
+然而
+然后
+然则
+人家
+任何
+任凭
+如此
+如果
+如何
+如其
+如若
+若非
+若是
+上下
+尚且
+设若
+设使
+甚而
+甚么
+甚至
+省得
+时候
+什么
+使得
+是的
+首先
+首先
+其次
+再次
+最后
+您们
+它们
+她们
+他们
+我们
+你是
+您是
+我是
+他是
+她是
+它是
+不是
+你们
+啊哈
+啊呀
+啊哟
+挨次
+挨个
+挨着
+哎呀
+哎哟
+俺们
+按理
+按期
+默然
+按时
+按说
+按照
+暗中
+暗自
+昂然
+八成
+倍感
+倍加
+本人
+本身
+本着
+并非
+别人
+必定
+比起
+比如
+比照
+鄙人
+毕竟
+必将
+必须
+并肩
+并没
+并排
+并且
+并无
+勃然
+不必
+不常
+不大
+不单
+不但
+而且
+不得
+不迭
+不定
+不独
+不对
+不妨
+不管
+不光
+不过
+不会
+不仅
+不拘
+不力
+不了
+不料
+不论
+不满
+不免
+不起
+不巧
+不然
+不日
+不少
+不胜
+不时
+不是
+不同
+不能
+不要
+不外
+不下
+不限
+不消
+不已
+不再
+不曾
+不止
+不只
+才能
+彻夜
+趁便
+趁机
+趁热
+趁势
+趁早
+趁着
+成心
+乘机
+乘势
+乘隙
+乘虚
+诚然
+迟早
+充分
+出来
+出去
+除此
+除非
+除开
+除了
+除去
+除却
+除外
+处处
+传说
+传闻
+纯粹
+此后
+此间
+此外
+此中
+次第
+匆匆
+从不
+从此
+从而
+从宽
+从来
+从轻
+从速
+从头
+从未
+从小
+从新
+从严
+从优
+从中
+从重
+凑巧
+存心
+达旦
+打从
+大大
+大抵
+大都
+大多
+大凡
+大概
+大家
+大举
+大略
+大约
+大致
+待到
+单纯
+单单
+但是
+但愿
+当场
+当儿
+当即
+当然
+当庭
+当头
+当下
+当真
+当中
+当着
+倒是
+到处
+到底
+到头
+得起
+的话
+的确
+等到
+等等
+顶多
+动辄
+陡然
+独自
+断然
+对于
+顿时
+多次
+多多
+多亏
+而后
+而论
+而且
+而是
+而外
+而言
+而已
+而又
+尔等
+反倒
+反而
+反手
+反之
+方才
+方能
+非常
+非但
+非得
+分头
+奋勇
+愤然
+更为
+更加
+根据
+个人
+各式
+刚才
+敢情
+该当
+嘎嘎
+否则
+赶快
+敢于
+刚好
+刚巧
+高低
+格外
+隔日
+隔夜
+公然
+过于
+果然
+果真
+光是
+关于
+共总
+姑且
+故此
+故而
+故意
+固然
+惯常
+毫不
+毫无
+很多
+何须
+好在
+何必
+何尝
+何妨
+何苦
+何况
+何止
+很少
+轰然
+后来
+呼啦
+哗啦
+互相
+忽地
+忽然
+话说
+或是
+伙同
+豁然
+恍然
+还是
+或许
+或者
+基本
+基于
+极大
+极度
+极端
+极力
+极其
+极为
+即便
+即将
+及其
+及至
+即刻
+即令
+即使
+几度
+几番
+几乎
+几经
+既然
+继而
+继之
+加上
+加以
+加之
+假如
+假若
+假使
+间或
+将才
+简直
+鉴于
+将近
+将要
+交口
+较比
+较为
+较之
+皆可
+截然
+截至
+藉以
+借此
+借以
+届时
+尽快
+近来
+进而
+进来
+进去
+尽管
+尽量
+尽然
+就算
+居然
+就此
+就地
+竟然
+究竟
+经常
+尽早
+精光
+经过
+就是
+局外
+举凡
+据称
+据此
+据实
+据说
+可好
+看来
+开外
+绝不
+决不
+据悉
+决非
+绝顶
+绝对
+绝非
+可见
+可能
+可是
+可以
+恐怕
+来讲
+来看
+快要
+况且
+拦腰
+牢牢
+老是
+累次
+累年
+理当
+理该
+理应
+例如
+立地
+立刻
+立马
+立时
+联袂
+连连
+连日
+路经
+临到
+连声
+连同
+连袂
+另外
+另行
+屡次
+屡屡
+缕缕
+率尔
+率然
+略加
+略微
+略为
+论说
+马上
+猛然
+没有
+每当
+每逢
+每每
+莫不
+莫非
+莫如
+莫若
+哪怕
+那么
+那末
+那些
+乃至
+难道
+难得
+难怪
+难说
+你们
+凝神
+宁可
+宁肯
+宁愿
+偶而
+偶尔
+碰巧
+譬如
+偏偏
+平素
+迫于
+扑通
+其次
+其后
+其实
+其它
+起初
+起来
+起首
+起头
+起先
+岂但
+岂非
+岂止
+恰逢
+恰好
+恰恰
+恰巧
+恰如
+恰似
+前后
+前者
+切莫
+切切
+切勿
+亲口
+亲身
+亲手
+亲眼
+亲自
+顷刻
+请勿
+取道
+权时
+全都
+全力
+全年
+全然
+然而
+然后
+人家
+人人
+仍旧
+仍然
+日见
+日渐
+日益
+日臻
+如常
+如次
+如果
+如今
+如期
+如若
+如上
+如下
+上来
+上去
+瑟瑟
+沙沙
+啊
+哎
+唉
+俺
+按
+吧
+把
+甭
+别
+嘿
+很
+乎
+会
+或
+既
+及
+啦
+了
+们
+你
+您
+哦
+砰
+啊
+你
+我
+他
+她
+它

+ 1893 - 0
data/stopwords/停用词.txt

@@ -0,0 +1,1893 @@
+!
+"
+#
+$
+%
+&
+'
+(
+)
+*
++
+,
+-
+--
+.
+..
+...
+......
+...................
+./
+.一
+.数
+.日
+/
+//
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+:
+://
+::
+;
+<
+=
+>
+>>
+?
+@
+A
+Lex
+[
+\
+]
+^
+_
+`
+exp
+sub
+sup
+|
+}
+~
+~~~~
+×××
+φ.
+—
+——
+———
+‘
+’
+’‘
+“
+”
+”,
+…
+……
+…………………………………………………③
+′∈
+′|
+℃
+Ⅲ
+↑
+→
+∈[
+∪φ∈
+≈
+①
+②
+②c
+③
+③]
+④
+⑤
+⑥
+⑦
+⑧
+⑨
+⑩
+──
+■
+▲
+ 
+、
+。
+〈
+〉
+《
+》
+》),
+」
+『
+』
+【
+】
+〔
+〕
+〕〔
+㈧
+一
+一.
+一一
+一下
+一个
+一些
+一何
+一切
+一则
+一则通过
+一天
+一定
+一方面
+一旦
+一时
+一来
+一样
+一次
+一片
+一番
+一直
+一致
+一般
+一起
+一转眼
+一边
+一面
+七
+万一
+三
+三天两头
+三番两次
+三番五次
+上
+上下
+上升
+上去
+上来
+上述
+上面
+下
+下列
+下去
+下来
+下面
+不
+不一
+不下
+不久
+不了
+不亦乐乎
+不仅
+不仅...而且
+不仅仅
+不仅仅是
+不会
+不但
+不但...而且
+不光
+不免
+不再
+不力
+不单
+不变
+不只
+不可
+不可开交
+不可抗拒
+不同
+不外
+不外乎
+不够
+不大
+不如
+不妨
+不定
+不对
+不少
+不尽
+不尽然
+不巧
+不已
+不常
+不得
+不得不
+不得了
+不得已
+不必
+不怎么
+不怕
+不惟
+不成
+不拘
+不择手段
+不敢
+不料
+不断
+不日
+不时
+不是
+不曾
+不止
+不止一次
+不比
+不消
+不满
+不然
+不然的话
+不特
+不独
+不由得
+不知不觉
+不管
+不管怎样
+不经意
+不胜
+不能
+不能不
+不至于
+不若
+不要
+不论
+不起
+不足
+不过
+不迭
+不问
+不限
+与
+与其
+与其说
+与否
+与此同时
+专门
+且
+且不说
+且说
+两者
+严格
+严重
+个
+个人
+个别
+中小
+中间
+丰富
+串行
+临
+临到
+为
+为主
+为了
+为什么
+为什麽
+为何
+为止
+为此
+为着
+主张
+主要
+举凡
+举行
+乃
+乃至
+乃至于
+么
+之
+之一
+之前
+之后
+之後
+之所以
+之类
+乌乎
+乎
+乒
+乘
+乘势
+乘机
+乘胜
+乘虚
+乘隙
+九
+也
+也好
+也就是说
+也是
+也罢
+了
+了解
+争取
+二
+二来
+二话不说
+二话没说
+于
+于是
+于是乎
+云云
+云尔
+互
+互相
+五
+些
+交口
+亦
+产生
+亲口
+亲手
+亲眼
+亲自
+亲身
+人
+人人
+人们
+人家
+人民
+什么
+什么样
+什麽
+仅
+仅仅
+今
+今后
+今天
+今年
+今後
+介于
+仍
+仍旧
+仍然
+从
+从不
+从严
+从中
+从事
+从今以后
+从优
+从古到今
+从古至今
+从头
+从宽
+从小
+从新
+从无到有
+从早到晚
+从未
+从来
+从此
+从此以后
+从而
+从轻
+从速
+从重
+他
+他人
+他们
+他是
+他的
+代替
+以
+以上
+以下
+以为
+以便
+以免
+以前
+以及
+以后
+以外
+以後
+以故
+以期
+以来
+以至
+以至于
+以致
+们
+任
+任何
+任凭
+任务
+企图
+伙同
+会
+伟大
+传
+传说
+传闻
+似乎
+似的
+但
+但凡
+但愿
+但是
+何
+何乐而不为
+何以
+何况
+何处
+何妨
+何尝
+何必
+何时
+何止
+何苦
+何须
+余外
+作为
+你
+你们
+你是
+你的
+使
+使得
+使用
+例如
+依
+依据
+依照
+依靠
+便
+便于
+促进
+保持
+保管
+保险
+俺
+俺们
+倍加
+倍感
+倒不如
+倒不如说
+倒是
+倘
+倘使
+倘或
+倘然
+倘若
+借
+借以
+借此
+假使
+假如
+假若
+偏偏
+做到
+偶尔
+偶而
+傥然
+像
+儿
+允许
+元/吨
+充其极
+充其量
+充分
+先不先
+先后
+先後
+先生
+光
+光是
+全体
+全力
+全年
+全然
+全身心
+全部
+全都
+全面
+八
+八成
+公然
+六
+兮
+共
+共同
+共总
+关于
+其
+其一
+其中
+其二
+其他
+其余
+其后
+其它
+其实
+其次
+具体
+具体地说
+具体来说
+具体说来
+具有
+兼之
+内
+再
+再其次
+再则
+再有
+再次
+再者
+再者说
+再说
+冒
+冲
+决不
+决定
+决非
+况且
+准备
+凑巧
+凝神
+几
+几乎
+几度
+几时
+几番
+几经
+凡
+凡是
+凭
+凭借
+出
+出于
+出去
+出来
+出现
+分别
+分头
+分期
+分期分批
+切
+切不可
+切切
+切勿
+切莫
+则
+则甚
+刚
+刚好
+刚巧
+刚才
+初
+别
+别人
+别处
+别是
+别的
+别管
+别说
+到
+到了儿
+到处
+到头
+到头来
+到底
+到目前为止
+前后
+前此
+前者
+前进
+前面
+加上
+加之
+加以
+加入
+加强
+动不动
+动辄
+勃然
+匆匆
+十分
+千
+千万
+千万千万
+半
+单
+单单
+单纯
+即
+即令
+即使
+即便
+即刻
+即如
+即将
+即或
+即是说
+即若
+却
+却不
+历
+原来
+去
+又
+又及
+及
+及其
+及时
+及至
+双方
+反之
+反之亦然
+反之则
+反倒
+反倒是
+反应
+反手
+反映
+反而
+反过来
+反过来说
+取得
+取道
+受到
+变成
+古来
+另
+另一个
+另一方面
+另外
+另悉
+另方面
+另行
+只
+只当
+只怕
+只是
+只有
+只消
+只要
+只限
+叫
+叫做
+召开
+叮咚
+叮当
+可
+可以
+可好
+可是
+可能
+可见
+各
+各个
+各人
+各位
+各地
+各式
+各种
+各级
+各自
+合理
+同
+同一
+同时
+同样
+后
+后来
+后者
+后面
+向
+向使
+向着
+吓
+吗
+否则
+吧
+吧哒
+吱
+呀
+呃
+呆呆地
+呐
+呕
+呗
+呜
+呜呼
+呢
+周围
+呵
+呵呵
+呸
+呼哧
+呼啦
+咋
+和
+咚
+咦
+咧
+咱
+咱们
+咳
+哇
+哈
+哈哈
+哉
+哎
+哎呀
+哎哟
+哗
+哗啦
+哟
+哦
+哩
+哪
+哪个
+哪些
+哪儿
+哪天
+哪年
+哪怕
+哪样
+哪边
+哪里
+哼
+哼唷
+唉
+唯有
+啊
+啊呀
+啊哈
+啊哟
+啐
+啥
+啦
+啪达
+啷当
+喀
+喂
+喏
+喔唷
+喽
+嗡
+嗡嗡
+嗬
+嗯
+嗳
+嘎
+嘎嘎
+嘎登
+嘘
+嘛
+嘻
+嘿
+嘿嘿
+四
+因
+因为
+因了
+因此
+因着
+因而
+固
+固然
+在
+在下
+在于
+地
+均
+坚决
+坚持
+基于
+基本
+基本上
+处在
+处处
+处理
+复杂
+多
+多么
+多亏
+多多
+多多少少
+多多益善
+多少
+多年前
+多年来
+多数
+多次
+够瞧的
+大
+大不了
+大举
+大事
+大体
+大体上
+大凡
+大力
+大多
+大多数
+大大
+大家
+大张旗鼓
+大批
+大抵
+大概
+大略
+大约
+大致
+大都
+大量
+大面儿上
+失去
+奇
+奈
+奋勇
+她
+她们
+她是
+她的
+好
+好在
+好的
+好象
+如
+如上
+如上所述
+如下
+如今
+如何
+如其
+如前所述
+如同
+如常
+如是
+如期
+如果
+如次
+如此
+如此等等
+如若
+始而
+姑且
+存在
+存心
+孰料
+孰知
+宁
+宁可
+宁愿
+宁肯
+它
+它们
+它们的
+它是
+它的
+安全
+完全
+完成
+定
+实现
+实际
+宣布
+容易
+密切
+对
+对于
+对应
+对待
+对方
+对比
+将
+将才
+将要
+将近
+小
+少数
+尔
+尔后
+尔尔
+尔等
+尚且
+尤其
+就
+就地
+就是
+就是了
+就是说
+就此
+就算
+就要
+尽
+尽可能
+尽如人意
+尽心尽力
+尽心竭力
+尽快
+尽早
+尽然
+尽管
+尽管如此
+尽量
+局外
+居然
+届时
+属于
+屡
+屡屡
+屡次
+屡次三番
+岂
+岂但
+岂止
+岂非
+川流不息
+左右
+巨大
+巩固
+差一点
+差不多
+己
+已
+已矣
+已经
+巴
+巴巴
+带
+帮助
+常
+常常
+常言说
+常言说得好
+常言道
+平素
+年复一年
+并
+并不
+并不是
+并且
+并排
+并无
+并没
+并没有
+并肩
+并非
+广大
+广泛
+应当
+应用
+应该
+庶乎
+庶几
+开外
+开始
+开展
+引起
+弗
+弹指之间
+强烈
+强调
+归
+归根到底
+归根结底
+归齐
+当
+当下
+当中
+当儿
+当前
+当即
+当口儿
+当地
+当场
+当头
+当庭
+当时
+当然
+当真
+当着
+形成
+彻夜
+彻底
+彼
+彼时
+彼此
+往
+往往
+待
+待到
+很
+很多
+很少
+後来
+後面
+得
+得了
+得出
+得到
+得天独厚
+得起
+心里
+必
+必定
+必将
+必然
+必要
+必须
+快
+快要
+忽地
+忽然
+怎
+怎么
+怎么办
+怎么样
+怎奈
+怎样
+怎麽
+怕
+急匆匆
+怪
+怪不得
+总之
+总是
+总的来看
+总的来说
+总的说来
+总结
+总而言之
+恍然
+恐怕
+恰似
+恰好
+恰如
+恰巧
+恰恰
+恰恰相反
+恰逢
+您
+您们
+您是
+惟其
+惯常
+意思
+愤然
+愿意
+慢说
+成为
+成年
+成年累月
+成心
+我
+我们
+我是
+我的
+或
+或则
+或多或少
+或是
+或曰
+或者
+或许
+战斗
+截然
+截至
+所
+所以
+所在
+所幸
+所有
+所谓
+才
+才能
+扑通
+打
+打从
+打开天窗说亮话
+扩大
+把
+抑或
+抽冷子
+拦腰
+拿
+按
+按时
+按期
+按照
+按理
+按说
+挨个
+挨家挨户
+挨次
+挨着
+挨门挨户
+挨门逐户
+换句话说
+换言之
+据
+据实
+据悉
+据我所知
+据此
+据称
+据说
+掌握
+接下来
+接着
+接著
+接连不断
+放量
+故
+故意
+故此
+故而
+敞开儿
+敢
+敢于
+敢情
+数/
+整个
+断然
+方
+方便
+方才
+方能
+方面
+旁人
+无
+无宁
+无法
+无论
+既
+既...又
+既往
+既是
+既然
+日复一日
+日渐
+日益
+日臻
+日见
+时候
+昂然
+明显
+明确
+是
+是不是
+是以
+是否
+是的
+显然
+显著
+普通
+普遍
+暗中
+暗地里
+暗自
+更
+更为
+更加
+更进一步
+曾
+曾经
+替
+替代
+最
+最后
+最大
+最好
+最後
+最近
+最高
+有
+有些
+有关
+有利
+有力
+有及
+有所
+有效
+有时
+有点
+有的
+有的是
+有着
+有著
+望
+朝
+朝着
+末##末
+本
+本人
+本地
+本着
+本身
+权时
+来
+来不及
+来得及
+来看
+来着
+来自
+来讲
+来说
+极
+极为
+极了
+极其
+极力
+极大
+极度
+极端
+构成
+果然
+果真
+某
+某个
+某些
+某某
+根据
+根本
+格外
+梆
+概
+次第
+欢迎
+欤
+正值
+正在
+正如
+正巧
+正常
+正是
+此
+此中
+此后
+此地
+此处
+此外
+此时
+此次
+此间
+殆
+毋宁
+每
+每个
+每天
+每年
+每当
+每时每刻
+每每
+每逢
+比
+比及
+比如
+比如说
+比方
+比照
+比起
+比较
+毕竟
+毫不
+毫无
+毫无例外
+毫无保留地
+汝
+沙沙
+没
+没奈何
+没有
+沿
+沿着
+注意
+活
+深入
+清楚
+满
+满足
+漫说
+焉
+然
+然则
+然后
+然後
+然而
+照
+照着
+牢牢
+特别是
+特殊
+特点
+犹且
+犹自
+独
+独自
+猛然
+猛然间
+率尔
+率然
+现代
+现在
+理应
+理当
+理该
+瑟瑟
+甚且
+甚么
+甚或
+甚而
+甚至
+甚至于
+用
+用来
+甫
+甭
+由
+由于
+由是
+由此
+由此可见
+略
+略为
+略加
+略微
+白
+白白
+的
+的确
+的话
+皆可
+目前
+直到
+直接
+相似
+相信
+相反
+相同
+相对
+相对而言
+相应
+相当
+相等
+省得
+看
+看上去
+看出
+看到
+看来
+看样子
+看看
+看见
+看起来
+真是
+真正
+眨眼
+着
+着呢
+矣
+矣乎
+矣哉
+知道
+砰
+确定
+碰巧
+社会主义
+离
+种
+积极
+移动
+究竟
+穷年累月
+突出
+突然
+窃
+立
+立刻
+立即
+立地
+立时
+立马
+竟
+竟然
+竟而
+第
+第二
+等
+等到
+等等
+策略地
+简直
+简而言之
+简言之
+管
+类如
+粗
+精光
+紧接着
+累年
+累次
+纯
+纯粹
+纵
+纵令
+纵使
+纵然
+练习
+组成
+经
+经常
+经过
+结合
+结果
+给
+绝
+绝不
+绝对
+绝非
+绝顶
+继之
+继后
+继续
+继而
+维持
+综上所述
+缕缕
+罢了
+老
+老大
+老是
+老老实实
+考虑
+者
+而
+而且
+而况
+而又
+而后
+而外
+而已
+而是
+而言
+而论
+联系
+联袂
+背地里
+背靠背
+能
+能否
+能够
+腾
+自
+自个儿
+自从
+自各儿
+自后
+自家
+自己
+自打
+自身
+臭
+至
+至于
+至今
+至若
+致
+般的
+良好
+若
+若夫
+若是
+若果
+若非
+范围
+莫
+莫不
+莫不然
+莫如
+莫若
+莫非
+获得
+藉以
+虽
+虽则
+虽然
+虽说
+蛮
+行为
+行动
+表明
+表示
+被
+要
+要不
+要不是
+要不然
+要么
+要是
+要求
+见
+规定
+觉得
+譬喻
+譬如
+认为
+认真
+认识
+让
+许多
+论
+论说
+设使
+设或
+设若
+诚如
+诚然
+话说
+该
+该当
+说明
+说来
+说说
+请勿
+诸
+诸位
+诸如
+谁
+谁人
+谁料
+谁知
+谨
+豁然
+贼死
+赖以
+赶
+赶快
+赶早不赶晚
+起
+起先
+起初
+起头
+起来
+起见
+起首
+趁
+趁便
+趁势
+趁早
+趁机
+趁热
+趁着
+越是
+距
+跟
+路经
+转动
+转变
+转贴
+轰然
+较
+较为
+较之
+较比
+边
+达到
+达旦
+迄
+迅速
+过
+过于
+过去
+过来
+运用
+近
+近几年来
+近年来
+近来
+还
+还是
+还有
+还要
+这
+这一来
+这个
+这么
+这么些
+这么样
+这么点儿
+这些
+这会儿
+这儿
+这就是说
+这时
+这样
+这次
+这点
+这种
+这般
+这边
+这里
+这麽
+进入
+进去
+进来
+进步
+进而
+进行
+连
+连同
+连声
+连日
+连日来
+连袂
+连连
+迟早
+迫于
+适应
+适当
+适用
+逐步
+逐渐
+通常
+通过
+造成
+逢
+遇到
+遭到
+遵循
+遵照
+避免
+那
+那个
+那么
+那么些
+那么样
+那些
+那会儿
+那儿
+那时
+那末
+那样
+那般
+那边
+那里
+那麽
+部分
+都
+鄙人
+采取
+里面
+重大
+重新
+重要
+鉴于
+针对
+长期以来
+长此下去
+长线
+长话短说
+问题
+间或
+防止
+阿
+附近
+陈年
+限制
+陡然
+除
+除了
+除却
+除去
+除外
+除开
+除此
+除此之外
+除此以外
+除此而外
+除非
+随
+随后
+随时
+随着
+随著
+隔夜
+隔日
+难得
+难怪
+难说
+难道
+难道说
+集中
+零
+需要
+非但
+非常
+非徒
+非得
+非特
+非独
+靠
+顶多
+顷
+顷刻
+顷刻之间
+顷刻间
+顺
+顺着
+顿时
+颇
+风雨无阻
+饱
+首先
+马上
+高低
+高兴
+默然
+默默地
+齐
+︿
+!
+#
+$
+%
+&
+'
+(
+)
+)÷(1-
+)、
+*
++
++ξ
+++
+,
+,也
+-
+-β
+--
+-[*]-
+.
+/
+0
+0:2
+1
+1.
+12%
+2
+2.3%
+3
+4
+5
+5:0
+6
+7
+8
+9
+:
+;
+<
+<±
+<Δ
+<λ
+<φ
+<<
+=
+=″
+=☆
+=(
+=-
+=[
+={
+>
+>λ
+?
+@
+A
+LI
+R.L.
+ZXFITL
+[
+[①①]
+[①②]
+[①③]
+[①④]
+[①⑤]
+[①⑥]
+[①⑦]
+[①⑧]
+[①⑨]
+[①A]
+[①B]
+[①C]
+[①D]
+[①E]
+[①]
+[①a]
+[①c]
+[①d]
+[①e]
+[①f]
+[①g]
+[①h]
+[①i]
+[①o]
+[②
+[②①]
+[②②]
+[②③]
+[②④
+[②⑤]
+[②⑥]
+[②⑦]
+[②⑧]
+[②⑩]
+[②B]
+[②G]
+[②]
+[②a]
+[②b]
+[②c]
+[②d]
+[②e]
+[②f]
+[②g]
+[②h]
+[②i]
+[②j]
+[③①]
+[③⑩]
+[③F]
+[③]
+[③a]
+[③b]
+[③c]
+[③d]
+[③e]
+[③g]
+[③h]
+[④]
+[④a]
+[④b]
+[④c]
+[④d]
+[④e]
+[⑤]
+[⑤]]
+[⑤a]
+[⑤b]
+[⑤d]
+[⑤e]
+[⑤f]
+[⑥]
+[⑦]
+[⑧]
+[⑨]
+[⑩]
+[*]
+[-
+[]
+]
+]∧′=[
+][
+_
+a]
+b]
+c]
+e]
+f]
+ng昉
+{
+{-
+|
+}
+}>
+~
+~±
+~+
+¥

+ 52 - 0
key.py

@@ -0,0 +1,52 @@
+# -*- coding:utf-8 -*-
+
+import logging
+import config
+import tools
+import jieba
+import datetime
+import mmap
+
+TITLE = "关键词表 生成"
+
+
+def main():
+    
+    # 日志配置初始化
+    tools.init_log()
+    tools.log_start_msg(TITLE)
+
+    with open(config.MERGE_FILE, "r", encoding=config.ENCODING_CHARSET) as fmerge, \
+        open(config.KEY_FILE, "w", encoding=config.ENCODING_CHARSET) as fw, \
+        mmap.mmap(fmerge.fileno(), 0, access=mmap.ACCESS_READ) as fmmap:
+
+        # TODO 
+        # 这里可能有IO优化的余地
+        # 这里可以不用mmap,改用一条一条readline()进行读取
+        # 进度提示也不完整
+
+            count = -1
+            total_num = fmmap.size()
+
+            while True:
+                count = count + 1
+                # 读取关键词
+                word = fmmap.readline().decode("UTF-8").replace("\r","").replace("\n","")
+
+                # 读取不到任何内容结束执行
+                if not word :
+                    break
+                
+                # 分词
+                word_root = list(jieba.cut_for_search(word))
+
+                # 写入文件中
+                fw.write("%d,%s,%s\n"%(count,word,word_root))
+
+                # 进度提示
+                tools.tip(total_num, fmmap.tell(), False)
+
+    tools.log_end_msg(TITLE)
+
+if __name__ == '__main__':
+    main()

+ 58 - 0
key_index.py

@@ -0,0 +1,58 @@
+# -*- coding:utf-8 -*-
+
+import config
+import tools
+import mmap
+import logging
+
+TITLE = "关键词索引"
+
+def main():
+    # 日志配置初始化
+    tools.init_log()
+    tools.log_start_msg(TITLE)
+
+    # 关键词索引容器
+    key_index_cache = {}
+
+    with open(config.KEY_FILE, "r", encoding=config.ENCODING_CHARSET) as fkey, \
+        mmap.mmap(fkey.fileno(), 0, access=mmap.ACCESS_READ) as fmmap:
+        
+        # 总大小
+        total_num = fmmap.size()
+
+        while True:
+            # 读取光标位置
+            cur_pos = fmmap.tell()
+            # 把光标移动到下一行
+            line = fmmap.readline().decode(config.ENCODING_CHARSET)
+            # 如果没有数据则结束
+            if not line :
+                break
+            
+            # 获取关键词序号
+            index = line.index(",")
+
+            # 建立关键词序号和位置的关系
+            key_index_cache[line[:index]]=cur_pos
+            
+            # 进度显示
+            tools.tip_in_size(total_num, cur_pos)
+        
+        # 保存索引
+        tools.save_obj(config.KEY_INDEX_CACHE, key_index_cache)
+
+    tools.log_end_msg(TITLE)
+    
+
+if __name__ == '__main__':
+    main()
+
+    # key_index_cache = tools.load_obj(config.KEY_INDEX_CACHE)
+
+    # with open(config.KEY_FILE, "r", encoding=config.ENCODING_CHARSET) as fkey, \
+    #     mmap.mmap(fkey.fileno(), 0, access=mmap.ACCESS_READ) as fmmap:
+    #         for key,value in key_index_cache.items():
+    #             fmmap.seek(value)
+    #             line = fmmap.readline().decode(config.ENCODING_CHARSET)
+    #             logging.debug("key: %s, value: %d, 内容:%s" % (key, value, line))

+ 427 - 0
key_reverse.py

@@ -0,0 +1,427 @@
+# -*- coding:utf-8 -*-
+
+from asyncio import FIRST_COMPLETED
+from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor, as_completed, wait
+from multiprocessing import Manager
+import multiprocessing
+from queue import Queue
+import sys
+from time import time
+import os
+from unittest import result
+import config
+import tools
+import ast
+import re
+import math
+import stop_word
+import logging
+import mmap
+import threading
+
+TITLE = "生成关键词倒排和统计信息"
+
+def thread_handle(path, start_pos, end_pos):
+    pattern = re.compile(config.KEY_RE_PATTERAN, re.I)
+    t = threading.current_thread()
+    print("线城-%d 开始任务,开始位置:%d,结束位置:%d" % (t.ident, start_pos, end_pos))
+    # 临时容器
+    key_reverse = []
+    with open(path, "r", encoding=config.ENCODING_CHARSET) as fkey, \
+        mmap.mmap(fkey.fileno(), 0, access=mmap.ACCESS_READ) as fmmap:
+        # 移动到开始位置
+        fmmap.seek(start_pos)
+
+        while True:
+            # 获取当前处理位置
+            cur_pos = fmmap.tell()
+
+            # 越界检查
+            if cur_pos > end_pos:
+                break
+
+            line = fmmap.readline()
+            key_reverse.append(line)
+            # 暂留
+            # # 读取关键词数据
+            # line = fmmap.readline().decode("UTF-8")
+
+            # # 如果到行尾则结束
+            # if not line:
+            #     break
+
+            # # 提取数据
+            # m = pattern.match(line)
+            # # 获取关键词序号、词根
+            # index = m.group(1)
+            # key_root = m.group(3)
+
+            # # 转换成真正的list对象
+            # key_root = ast.literal_eval(key_root)
+
+            # key_reverse.append((index, key_root))
+    # print("线城-%d 结束任务" % t.ident)
+    # return key_reverse
+    return {
+        "tid": t.ident,
+        "key_reverse": key_reverse
+    }
+
+
+
+def process_handle(stop_word_cache, lines):
+    pid = os.getpid()
+    print("进程-%d 接收到数据,开始计算")
+    pattern = re.compile(config.KEY_RE_PATTERAN, re.I)
+
+    key_reverse_dict={}
+
+    for line in lines:
+        line = line.decode("UTF-8")
+        # 提取数据
+        m = pattern.match(line)
+        # 获取关键词序号、词根
+        index = m.group(1)
+        key_root = m.group(3)
+
+        # 转换成真正的list对象
+        for item in ast.literal_eval(key_root):
+            # 排除停用词
+            if item in stop_word_cache:
+                continue
+            # 构建倒排表和统计数据量
+            val = key_reverse_dict.get(item)
+            if val:
+                key_reverse_dict[item]["count"] = key_reverse_dict[item]["count"] + 1
+                key_reverse_dict[item]["indexs"].append(index) 
+            else:
+                key_reverse_dict[item]= {
+                    "count":1,
+                    "indexs":[]
+                }
+    return {
+        "pid": pid,
+        "key_reverse_dict":key_reverse_dict
+    }
+
+def multi_thread():
+    """
+    构建待排表(多线程)
+    """
+
+    key_reverse_dict = {}
+
+    def process_handle_result(future):
+        print("进程-%d 执行结束,返回部分数据 合并数据" % result["pid"])
+        result = future.result()
+        for key,value in result["key_reverse_dict"].items():
+            val = key_reverse_dict.get(key)
+            if val:
+                key_reverse_dict[key]["count"] = key_reverse_dict[key]["count"] + value["count"]
+                key_reverse_dict[key]["indexs"].append(value["indexs"]) 
+            else:
+                key_reverse_dict[key]= value
+        print("进程-%d 合并数据结束" % result["pid"])
+        
+
+    def thread_handle_result(future):
+        result = future.result()
+        logging.info("线程-%d 执行结束,返回部分数据,提交至计算进程" % result["tid"])
+        process_future = process_pool.submit(process_handle, stop_word_cache, result["key_reverse"])
+        process_future.add_done_callback(process_handle_result)
+
+    tools.init_log()
+    tools.log_start_msg(TITLE)
+
+    logging.info("目前执行的是多线程版")
+
+    logging.info("开始执行初始化")
+    # 提取规则
+    pattern = re.compile(config.KEY_RE_PATTERAN, re.I)
+    # 停用表
+    stop_word_cache = stop_word.load_stop_word()
+    # 进程处理数
+    thread_num = 1
+    process_num = 2
+    worker_num = 100
+    # 关键表索引
+    key_index_cache = tools.load_obj(config.KEY_INDEX_CACHE)
+
+    logging.info("开始对数据进行分段计算")
+
+    # 对索引文件中的元素进行平分
+    # 转成列表,计算总长 和 平分后的处理区间
+    key_index_list = [key for key in key_index_cache.keys()]
+    total_len = len(key_index_list)
+    internal = math.ceil(total_len / worker_num )
+
+    # 利用 缓存索引文件 生成处理区间的位置信息
+    # 位置信息容器
+    pos_list = []
+    for i in range(worker_num + 1):
+        # 计算平分点在列表中的位置
+        l_pos = i * internal
+        # 如果大于等于列表大小需要额外处理
+        if l_pos >= total_len:
+            l_pos = total_len -1
+        # 获取列表中的词根
+        key_index = key_index_list[l_pos:l_pos+1]
+        # 根据词根获取位置信息
+        pos = key_index_cache[key_index[0]]
+        # 记录位置信息
+        pos_list.append(pos)
+   
+    logging.info("把分段结果提交至多线程执行")
+    # 生成任务
+    with ThreadPoolExecutor(thread_num) as thread_pool, \
+        ProcessPoolExecutor(process_num) as process_pool:
+
+        # thread_futures = []
+
+        for i in range(0, len(pos_list)-1):
+            pos = pos_list[i: i+2]
+            # thread_futures.append()
+            thread_future = thread_pool.submit(thread_handle, config.KEY_FILE, pos[0], pos[1])
+            thread_future.add_done_callback(thread_handle_result)
+
+        # 等待数据返回
+        logging.info("等待多线程执行结束")
+        thread_pool.shutdown(wait=True)
+        process_pool.shutdown(wait=True)
+        
+
+
+            
+                
+    
+    logging.info("已获取全部子进程返回部分结果,总数据量:%d" % len(key_reverse_dict))
+    return 
+    # 根据关键词数量进行排序,这里通过items()方法转成元组列表,才能进行排序
+    logging.info("根据关键词数量进行倒序排列")
+    sorted_reverse_list = sorted(key_reverse_dict.items(), key=lambda x: x[1]["count"], reverse=True)
+
+    # 保存到本地文件
+    logging.info("保存到本地")
+    with open(config.KEY_REVERSE_FILE, "w", encoding=config.ENCODING_CHARSET) as f:
+        for key, value in sorted_reverse_list:
+            f.write("%s,%d,%s\n" % (key, value["count"], value["indexs"]))
+
+    tools.log_end_msg(TITLE)
+
+def handle(path, start_pos, end_pos, share_pattern, stop_word_cache):
+    pid = os.getpid()
+    print("进程-%d 开始任务,开始位置:%d,结束位置:%d" % (pid, start_pos, end_pos))
+    # 临时容器
+    key_reverse = {}
+    # 提取数据用的正则
+    pattern = share_pattern.value
+    with open(path, "r", encoding=config.ENCODING_CHARSET) as fkey, \
+        mmap.mmap(fkey.fileno(), 0, access=mmap.ACCESS_READ) as fmmap:
+        # 移动到开始位置
+        fmmap.seek(start_pos)
+
+        while True:
+            # 获取当前处理位置
+            cur_pos = fmmap.tell()
+
+            # 越界检查
+            if cur_pos > end_pos:
+                break
+
+            # 读取关键词数据
+            line = fmmap.readline().decode("UTF-8")
+
+            # 如果到行尾则结束
+            if not line:
+                break
+
+            # 提取数据
+            m = pattern.match(line)
+            # 获取关键词序号、词根
+            index = m.group(1)
+            key_root = m.group(3)
+
+            # 转换成真正的list对象
+            for item in ast.literal_eval(key_root):
+                # 排除停用词
+                if item in stop_word_cache:
+                    continue
+                # 构建倒排表和统计数据量
+                val = key_reverse.get(item)
+                if val:
+                    count = key_reverse[item]["count"]
+                    key_reverse[item]["count"] = count + 1
+                    key_reverse[item]["indexs"].append(index) 
+                else:
+                    key_reverse[item]= {
+                        "count":1,
+                        "indexs":[]
+                    }
+    
+    print("进程-%d 任务执行结束" % pid)
+
+    return key_reverse
+
+def multi_process():
+    """
+    构建待排表(多进程)
+    """
+
+    tools.init_log()
+    tools.log_start_msg(TITLE)
+
+    logging.info("目前执行的是多进程版")
+
+    logging.info("开始执行初始化")
+    manager = Manager()
+    # 提取规则
+    share_pattern = manager.Value("pattern", re.compile(config.KEY_RE_PATTERAN, re.I))
+    # 停用表
+    stop_word_cache = manager.dict(stop_word.load_stop_word())
+    # 进程处理数
+    process_num = os.cpu_count() - 1
+    worker_num = process_num
+    pool = ProcessPoolExecutor(max_workers=process_num)
+    # 关键表索引
+    key_index_cache = tools.load_obj(config.KEY_INDEX_CACHE)
+
+    logging.info("开始对数据进行分段计算")
+
+    # 对索引文件中的元素进行平分
+    # 转成列表,计算总长 和 平分后的处理区间
+    key_index_list = [key for key in key_index_cache.keys()]
+    total_len = len(key_index_list)
+    internal = math.ceil(total_len / worker_num )
+
+    # 利用 缓存索引文件 生成处理区间的位置信息
+    # 位置信息容器
+    pos_list = []
+    for i in range(worker_num + 1):
+        # 计算平分点在列表中的位置
+        l_pos = i * internal
+        # 如果大于等于列表大小需要额外处理
+        if l_pos >= total_len:
+            l_pos = total_len -1
+        # 获取列表中的词根
+        key_index = key_index_list[l_pos:l_pos+1]
+        # 根据词根获取位置信息
+        pos = key_index_cache[key_index[0]]
+        # 记录位置信息
+        pos_list.append(pos)
+   
+    logging.info("把分段结果提交至多进程执行")
+    # 生成任务
+    process_futures = []
+    for i in range(0, len(pos_list)-1):
+        pos = pos_list[i: i+2]
+        process_futures.append(pool.submit(handle, config.KEY_FILE, pos[0], pos[1], share_pattern, stop_word_cache))
+
+    # 等待数据返回
+    logging.info("等待多进程执行结束")
+    wait(process_futures,return_when=FIRST_COMPLETED)
+    key_reverse_dict = {}
+    for future in as_completed(process_futures):
+        logging.info("有子进程执行结束,返回部分结果")
+        result = future.result()
+        for key, value in result.items():
+            # 进行数据合并
+            val_dict = key_reverse_dict.get(key)
+            if val_dict:
+                count = val_dict["count"]
+                key_reverse_dict[key]["count"] = count + value["count"]
+                key_reverse_dict[key]["indexs"].extend(value["indexs"])
+            else:
+                key_reverse_dict[key] = value
+
+    logging.info("已获取全部子进程返回部分结果")
+    
+    # 根据关键词数量进行排序,这里通过items()方法转成元组列表,才能进行排序
+    logging.info("根据关键词数量进行倒序排列")
+    sorted_reverse_list = sorted(key_reverse_dict.items(), key=lambda x: x[1]["count"], reverse=True)
+
+    # 保存到本地文件
+    logging.info("保存到本地")
+    with open(config.KEY_REVERSE_FILE, "w", encoding=config.ENCODING_CHARSET) as f:
+        for key, value in sorted_reverse_list:
+            f.write("%s,%d,%s\n" % (key, value["count"], value["indexs"]))
+
+    tools.log_end_msg(TITLE)
+
+def one_process():
+    """
+    构建倒排表(单进程版)
+    """
+
+    tools.init_log()
+    tools.log_start_msg(TITLE)
+
+    logging.info("目前执行的是单进程版")
+
+    # 提取规则
+    pattern = re.compile(config.KEY_RE_PATTERAN, re.I)
+
+    # 倒排表 容器
+    key_reverse = {}
+
+    # 停用表
+    stop_word_cache = stop_word.load_stop_word()
+
+    with open(config.KEY_FILE, "r", encoding=config.ENCODING_CHARSET) as fkey:
+        
+        # 获取文件总大小,获取后需要复原光标位置
+        fkey.seek(0, os.SEEK_END)
+        total_num = fkey.tell()
+        fkey.seek(0)
+
+        while True:
+            # 获取当前处理位置
+            cur_pos = fkey.tell()
+            
+            # 进度提示
+            tools.tip_in_size(total_num, cur_pos)
+
+            # 读取关键词数据
+            line = fkey.readline()
+
+            # 如果到行尾则结束
+            if not line:
+                break
+
+            # 提取数据
+            m = pattern.match(line)
+            # 获取关键词序号
+            index = m.group(1)
+            # 获取词根
+            key_root = m.group(3)
+            # 转换成真正的list对象
+            for item in ast.literal_eval(key_root):
+                
+                # 排除停用词
+                if item in stop_word_cache:
+                    continue
+
+                # 构建倒排表
+                val = key_reverse.get(item)
+                if val:
+                    count = key_reverse[item]["count"]
+                    key_reverse[item]["count"] = count + 1
+                    key_reverse[item]["indexs"].append(index) 
+                else:
+                    key_reverse[item]= {
+                        "count":1,
+                        "indexs":[]
+                    }
+
+    logging.info("根据关键词数量进行倒序排列")
+    sorted_reverse_list = sorted(key_reverse.items(), key=lambda x: x[1]["count"], reverse=True)
+
+    # 保存到本地文件
+    logging.info("保存到本地")
+    with open(config.KEY_REVERSE_FILE, "w", encoding=config.ENCODING_CHARSET) as f:
+        for key, value in sorted_reverse_list:
+            f.write("%s,%d,%s\n" % (key, value["count"], value["indexs"]))
+
+    tools.log_end_msg(TITLE)
+
+if __name__ == "__main__":
+    multi_thread()

+ 52 - 0
key_reverse_index.py

@@ -0,0 +1,52 @@
+# -*- coding:utf-8 -*-
+
+import sys
+from time import time
+import os
+import config
+import tools
+import ast
+import re
+import stop_word
+import mmap
+
+TITLE = "关键词倒排索引"
+
+def main():
+    # 日志配置初始化
+    tools.init_log()
+    tools.log_start_msg(TITLE)
+
+    # 关键词倒排索引容器
+    key_reverse_index_cache = {}
+
+    with open(config.KEY_REVERSE_FILE, "r", encoding=config.ENCODING_CHARSET) as freverse, \
+        mmap.mmap(freverse.fileno(), 0, access=mmap.ACCESS_READ) as fmmap:
+        
+        # 总大小
+        total_num = fmmap.size()
+
+        while True:
+            # 读取光标位置
+            cur_pos = fmmap.tell()
+            # 把光标移动到下一行
+            line = fmmap.readline().decode(config.ENCODING_CHARSET)
+
+            # 如果没有数据则结束
+            if not line :
+                break
+            
+            # 获取词根位置,建立词根和位置的关系
+            index = line.index(",")
+            key_reverse_index_cache[line[:index]]=cur_pos
+            
+            # 进度显示
+            tools.tip_in_size(total_num, cur_pos)
+        
+        # 保存索引
+        tools.save_obj(config.KEY_REVERSE_INDEX_CACHE, key_reverse_index_cache)
+
+    tools.log_end_msg(TITLE)
+
+if __name__ == "__main__":
+    main()

+ 218 - 0
key_reverse_statistics.py

@@ -0,0 +1,218 @@
+# -*- coding:utf-8 -*-
+
+from concurrent.futures import ProcessPoolExecutor, as_completed
+import mmap
+from multiprocessing.connection import wait
+import random
+import sys
+from time import sleep, time
+import os
+import config
+import tools
+import ast
+import re
+import stop_word
+import logging
+import math
+from multiprocessing import Process, Pool
+
+TITLE = "关键词倒排文件 统计"
+
+# def reverse_statistics(start_pos, end_pos):
+
+def handle(start_pos, end_pos):
+
+    print("进程:%d, 统计开始,开始位置:%d,结束位置:%d" % (os.getpid(), start_pos, end_pos))
+
+    # 统计信息容器
+    reverse_statistics = {}
+    
+    with open(config.KEY_REVERSE_FILE, "r", encoding=config.ENCODING_CHARSET) as fr, \
+        mmap.mmap(fr.fileno(), 0 , access=mmap.ACCESS_READ) as fmmap:
+        # 调整开始位置
+        fmmap.seek(start_pos)
+
+        while True:
+            cur_pos = fmmap.tell()
+            # 越界检测
+            if cur_pos >= end_pos:
+                break
+            
+            line = fmmap.readline().decode(config.ENCODING_CHARSET)
+            index=line.index(",")
+            key = line[:index]
+            word_root = line[index+1:]
+            word_root = ast.literal_eval(word_root)
+            l = len(word_root)
+            
+            reverse_statistics[key]=l
+            
+    logging.info("进程:%d, 统计结束" % os.getpid())
+
+    return {
+        "pid":os.getpid(),
+        "statistics":reverse_statistics
+    }
+    
+
+def main2():
+    # 日志信息配置
+    tools.init_log()
+    tools.log_start_msg(TITLE)
+
+    # 进程数
+    process_num = os.cpu_count()
+
+    # 加载缓存索引文件
+    key_reverse_index = tools.load_obj(config.KEY_REVERSE_INDEX_CACHE)
+
+    # 对索引文件中的元素进行平分
+
+    # 转成列表,计算总长 和 平分后的处理区间
+    key_list = [key for key in key_reverse_index.keys()]
+    key_list_len = len(key_list)
+    internal = math.ceil(key_list_len / process_num )
+
+    # 利用 缓存索引文件 生成处理区间的位置信息
+    # 位置信息容器
+    pos_list = []
+    for i in range(process_num + 1):
+        # 计算平分点在列表中的位置
+        l_pos = i * internal
+        # 如果超过列表大小需要额外处理
+        if l_pos > key_list_len:
+            l_pos = key_list_len -1
+        # 获取列表中的词根
+        key = key_list[l_pos:l_pos+1]
+        # 根据词根获取位置信息
+        pos = key_reverse_index[key[0]]
+        # 记录位置信息
+        pos_list.append(pos)
+
+     
+    # 使用用进程池
+    pool = ProcessPoolExecutor(process_num)
+    # 生成任务
+    process_futures = []
+    for i in range(0, len(pos_list)-1):
+        pos = pos_list[i: i+2]
+        process_futures.append(pool.submit(handle, pos[0], pos[1]))
+    
+    # with open(config.KEY_REVERSE_STATISTICS_FILE, "w", encoding=config.ENCODING_CHARSET) as fw:
+    #     for future in as_completed(process_futures):
+    #         logging.info("部分子任务统计结束,保存至本地 - 开始")
+    #         for key, value in future.result().items():
+    #             fw.write("%s,%s\n"%(key,value))
+    #         logging.info("部分子任务统计结束,保存至本地 - 结束")
+
+    
+    results = []
+    for future in as_completed(process_futures):
+        result = future.result()
+        logging.info("进程:%d, 统计结束" % result["pid"])
+        results.append(result)
+
+    logging.info("统计结束,保存至本地 - 开始")
+    with open(config.KEY_REVERSE_STATISTICS_FILE, "w", encoding=config.ENCODING_CHARSET) as fw:
+        for r in results:
+            for key, value in r["statistics"].items():
+                fw.write("%s,%s\n"%(key,value))
+    logging.info("部分子任务统计结束,保存至本地 - 结束")
+
+    pool.shutdown(wait=True)
+
+    tools.log_end_msg(TITLE)
+
+    # 测试代码3
+    # pool = ProcessPoolExecutor(3)
+    # for i in range(1,5):
+    #     pool.submit(handle, "测试进程-%d"%i, i, i*10)
+
+    # pool.shutdown(wait=True)
+
+    # 测试代码2
+    # pool = Pool(3)
+    # for i in range(1,5):
+    #     pool.apply_async(handle, ("测试进程-%d"%i, i, i*10))
+    # pool.close()
+    # pool.join()
+    # print("结束")
+
+    # 测试代码1
+    # p = Process(target=handle, args=('测试进程', 1, 10))
+    # p.start()
+    # p.join()
+    
+    # tools.init_log()
+    # tools.log_start_msg(TITLE)
+
+    # key_reverse_index = tools.load_obj(config.KEY_REVERSE_INDEX_CACHE)
+
+    # tmp = [key for key in key_reverse_index.keys()]
+    
+    # l = len(tmp)
+    # print("总长:", l)
+    # internal = math.ceil(l / 4)
+    # print("间隔:", internal)
+    # pos = []
+    # for i in range(5):
+    #     t = i*internal
+    #     if t > l:
+    #         t = l-1
+    #     pos.append(t)
+    # print(pos)
+
+    # for item in pos:
+    #     key = tmp[item:item+1]
+    #     print(key)
+    #     pos = key_reverse_index[key[0]]
+    #     print(key, pos)
+
+    
+    # reverse_statistics = {}
+    # logging.info("统计开始")
+    # with open(config.KEY_REVERSE_FILE, "r", encoding=config.ENCODING_CHARSET) as fr, \
+    #     mmap.mmap(fr.fileno(), 0 , access=mmap.ACCESS_READ) as fmmap:
+    #     for line in fr:
+    #         index=line.index(",")
+    #         key = line[:index]
+    #         word_root = line[index+1:]
+    #         word_root = ast.literal_eval(word_root)
+    #         l = len(word_root)
+            
+    #         reverse_statistics[key]=l
+
+    # logging.info("统计结束,保存至本地")
+    # with open(config.KEY_REVERSE_STATISTICS_FILE, "w", encoding=config.ENCODING_CHARSET) as fw:
+    #     for key, value in reverse_statistics:
+    #         fw.write("%s,%s\n"%(key,value))
+
+    # tools.log_end_msg(TITLE)
+
+
+def main():
+    tools.init_log()
+    tools.log_start_msg(TITLE)
+    
+    reverse_statistics = {}
+    logging.info("统计开始")
+    with open(config.KEY_REVERSE_FILE, "r", encoding=config.ENCODING_CHARSET) as fr, \
+        mmap.mmap(fr.fileno(), 0 , access=mmap.ACCESS_READ) as fmmap:
+        for line in fr:
+            index=line.index(",")
+            key = line[:index]
+            word_root = line[index+1:]
+            word_root = ast.literal_eval(word_root)
+            l = len(word_root)
+            
+            reverse_statistics[key]=l
+
+    logging.info("统计结束,保存至本地")
+    with open(config.KEY_REVERSE_STATISTICS_FILE, "w", encoding=config.ENCODING_CHARSET) as fw:
+        for key, value in reverse_statistics:
+            fw.write("%s,%s\n"%(key,value))
+
+    tools.log_end_msg(TITLE)
+
+if __name__ == "__main__":
+    main2()

+ 28 - 0
logging.conf

@@ -0,0 +1,28 @@
+[loggers]
+keys=root
+
+[handlers]
+keys=fileHandler,consoleHandler
+
+[formatters]
+keys=simpleFormatter
+
+[logger_root]
+level=INFO
+handlers=fileHandler,consoleHandler
+
+[handler_consoleHandler]
+class=StreamHandler
+args=(sys.stdout,)
+level=DEBUG
+formatter=simpleFormatter
+
+[handler_fileHandler]
+class=FileHandler
+args=('../all.log', 'a', "UTF-8")
+level=DEBUG
+formatter=simpleFormatter
+
+[formatter_simpleFormatter]
+format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
+datefmt=

+ 84 - 0
merge.py

@@ -0,0 +1,84 @@
+# -*- coding: utf-8 -*-
+
+import config
+import os
+import tools
+import logging
+import zipfile
+
+TITLE= "拓展词合并"
+
+# 带合并的文件目录
+DATA_DIR = "E:\Download\长尾关键词\普通-p"
+
+def get_files(path):
+    '''
+    读取文件夹下的文件列表
+    '''
+    file_list = []
+    for file in os.listdir(path):
+        file_list.append(os.path.join(path,file))
+    return file_list
+
+def merge_file_content():
+    """
+    合并文件下的所有文件中的内容(仅限关键词)
+
+    Parameters
+    ----------
+    dir_path : string
+        待读取的文件夹
+
+    dest_file : string 
+        合并后输出的文件
+
+    exclude_file : list
+        跳过压缩文件中的文件
+    ----------
+    """
+
+    # 日志初始化
+    tools.init_log()
+
+    tools.log_start_msg(TITLE)
+
+    # 获取文件列表
+    files = get_files(DATA_DIR)
+
+    # 总文件数
+    total_num = len(files)
+    logging.info("待处理文件数:%d" % total_num)
+
+    with open(config.MERGE_FILE, "w", encoding="utf-8") as f:
+
+        for i, file in enumerate(files):
+            zfile = zipfile.ZipFile(file)
+            filenames = zfile.namelist()
+            for filename in filenames:
+
+                # 重新编码文件名为正确形式
+                realname = filename.encode('cp437').decode('gbk')
+                
+                # 排除无效文件
+                if realname in config.MERGE_EXCLUDE_FILES:
+                    continue
+
+                logging.info("正在处理文件: %s" % realname)
+
+                # 读取压缩文件中的文件
+                with zfile.open(filename) as file_content:
+                    lines = file_content.readlines()
+                    # 跳过开头两行
+                    for line in lines[2:]:
+                        split = line.decode("gbk").split(",")
+                        # 只需要第一列的数据
+                        f.write(split[0])
+                        f.write("\n")
+                
+            tools.tip(total_num, i)
+
+    tools.log_end_msg(TITLE)
+
+if __name__ == '__main__':
+    merge_file_content()
+        

+ 156 - 0
statistics.py

@@ -0,0 +1,156 @@
+# -*- coding:utf-8 -*-
+
+from collections import namedtuple
+from dataclasses import make_dataclass
+import os
+import tools
+import config
+import logging
+import random
+import time
+import ast
+import mmap
+
+TASK_TITLE = "数据统计分析"
+
+def transfer_str(num):
+    msg = None
+    if num >= 10000:
+        msg = "%d万%d" % (num//10000, num%10000)
+    else:
+        msg = str(num)
+    return msg
+
+def cal(list):
+    list_len = len(list)
+    list_count = sum(list)
+    sum_msg = transfer_str(list_len)
+    count_msg = transfer_str(list_count)
+    avg_msg = transfer_str(int(list_count/list_len))
+    return sum_msg, count_msg, avg_msg
+
+def tip(condition, list):
+    logging.info("条件:%s - 涉及:%s个词根,涉及词数:%s,平均约:%s 词数/词根" % ((condition,)+ cal(list)))
+
+def test_tip(list, ele_num):
+    start =time.time()
+    tmp = ast.literal_eval(str(random.sample(list, ele_num)))
+    end =time.time()
+    logging.info("%s个元素的字符列表转换成对象耗时%s" % (transfer_str(ele_num), end-start))
+
+def cost_statistics():
+    with open(config.KEY_REVERSE_STATISTICS_FILE, "r", encoding=config.ENCODING_CHARSET) as f:
+        count_list= []
+        total_count=0
+        for line in f:
+            first_index = line.index(",")
+            count = int(line[first_index+1:])
+            count_list.append(count)
+            total_count = total_count + count
+        
+        logging.info("总祠根数:%d, 涉及的总分词查找数:%d" % (len(count_list), total_count))
+        
+        tip("等于1", [val for val in count_list if val == 1])
+
+        tip("大于1小于100", [val for val in count_list if val > 1 and val < 100])
+
+        tip("大于等于100小于200", [val for val in count_list if val >= 100 and val < 200])
+
+        tip("大于等于200小于300", [val for val in count_list if val >= 200 and val < 300])
+
+        tip("大于等于300小于400", [val for val in count_list if val >= 300 and val < 400])
+
+        tip("大于等于400小于500", [val for val in count_list if val >= 400 and val < 500])
+        
+        tip("大于等于500小于1000", [val for val in count_list if val >= 500 and val < 1000])
+
+        tip("大于等于1000小于5000", [val for val in count_list if val >= 1000 and val < 5000])
+
+        tip("大于等于5000小于1万", [val for val in count_list if val >= 5000 and val < 10000])
+
+        tip("大于等于1万小于5万", [val for val in count_list if val >= 10000 and val < 50000])
+
+        tip("大于等于5万小于10万", [val for val in count_list if val >= 50000 and val < 100000])
+
+        tip("大于等于10万", [val for val in count_list if val >= 100000])
+
+        sample_list = [i for i in range(14500029)]
+        test_tip(sample_list, 1)
+        test_tip(sample_list, 10)
+        test_tip(sample_list, 50)
+        test_tip(sample_list, 100)
+        test_tip(sample_list, 200)
+        test_tip(sample_list, 300)
+        test_tip(sample_list, 400)
+        test_tip(sample_list, 500)
+        test_tip(sample_list, 1000)
+        test_tip(sample_list, 5000)
+        test_tip(sample_list, 10000)
+        test_tip(sample_list, 50000)
+        test_tip(sample_list, 100000)
+        test_tip(sample_list, 595528)
+        test_tip(sample_list, 689520)
+        test_tip(sample_list, 776035)
+        test_tip(sample_list, 822266)
+        test_tip(sample_list, 951491)
+
+def memory_statistics():
+    key_reverse_index_cache = tools.load_obj(config.KEY_REVERSE_INDEX_CACHE)
+    end_pos = key_reverse_index_cache["导不出"]
+    logging.info("查找结束位置")
+    with open(config.KEY_REVERSE_FILE, "r", encoding=config.ENCODING_CHARSET) as freverse, \
+        mmap.mmap(freverse.fileno(), 0, access=mmap.ACCESS_READ) as fmmap:
+        
+        logging.info("开始构建缓存")
+        cache = {}
+        start = time.time()
+        while True:
+            cur_pos = fmmap.tell()
+            
+            if cur_pos > end_pos:
+                break
+
+            line = fmmap.readline().decode("UTF-8")
+            first_index = line.index(",")
+            key = line[:first_index]
+
+            # 转换
+            word_root = line[first_index+1:]
+            cache[key]=ast.literal_eval(word_root)
+
+        end = time.time()
+        logging.info('构建热点缓存完成,耗时:%s,缓存数量:%d' % ((end-start), len(cache)))
+
+        logging.info('把缓存保存到本地')
+        tools.save_obj(config.KEY_REVERSE_INDEX_HOT_CACHE, cache)
+        logging.info('保存结束')
+
+        time.sleep(20)
+        logging.info('留20s进行内存观察')
+        
+
+def main():
+
+    # num = 459789
+    # print(num%10000)
+    # print(num//10000)
+    # return
+
+    tools.init_log()
+    tools.log_start_msg(TASK_TITLE)
+
+    memory_statistics()
+        
+
+    tools.log_end_msg(TASK_TITLE)
+
+
+if __name__ == "__main__":
+    # print("加载开始")
+    # cache = tools.load_obj(config.KEY_REVERSE_INDEX_HOT_CACHE+".bak")
+    # print("加载结束")
+    # time.sleep(20)
+
+    Shape = namedtuple('Shape', ['x', 'y', 'z'])
+    exm = Shape(1, 2, 3)
+    print(exm.index(2))

+ 65 - 0
stop_word.py

@@ -0,0 +1,65 @@
+# -*- coding:utf-8 -*-
+
+from datetime import datetime
+import os
+import time
+import tools
+import config
+import pickle
+import logging
+
+TITLE = "停用词"
+
+def load_stop_word():
+    """
+    加载停用词
+    """
+
+    # 判断是否存在缓存
+    if os.path.exists(config.STOP_WORD_CACHE):
+        logging.debug("存在停用词缓存")
+        return tools.load_obj(config.STOP_WORD_CACHE)
+
+    logging.debug("正在构建停用词缓存")
+
+    # 停用词容器
+    stop_word = []
+
+    # 构建停用词列表
+    stop_word_files = os.listdir(config.STOP_WORD_DIR)
+    for file in stop_word_files:
+        stop_word_file = os.path.join(config.STOP_WORD_DIR, file)
+        with open(stop_word_file, encoding=config.ENCODING_CHARSET) as f:
+            for item in f:
+                # 移除换行符
+                stop_word.append(item.replace("\n",""))
+    # 去重
+    stop_word = list(set(stop_word))
+
+    # 把list改成dict提升检索速度
+    stop_word_dict = {}
+    for item in stop_word:
+        stop_word_dict[item]=None
+    
+    logging.debug("把停用词缓存保存到本地")
+
+    # 保存本地作为缓存
+    tools.save_obj(config.STOP_WORD_CACHE, stop_word_dict)
+    
+    return stop_word_dict
+
+if __name__ == '__main__':
+
+    tools.init_log()
+    tools.log_start_msg(TITLE)
+
+    stop_word = load_stop_word()
+
+    start = time.time()
+    for i in range(1400*10000):
+        for item in ["总之", "风雨无阻","千"]:
+            item in stop_word
+    end = time.time()
+    print("耗时:", end - start)
+
+    tools.log_end_msg(TITLE)

+ 184 - 0
tools.py

@@ -0,0 +1,184 @@
+# -*- coding:utf-8 -*-
+
+import math
+import logging
+import os
+import config
+import logging.config
+import pickle
+import mmap
+
+TITLE = "工具类"
+
+tip_internal_cache = {}
+
+def init_log():
+    """
+    日志初始化工具
+    """
+    # 读取日志配置文件内容
+    logging.config.fileConfig('./logging.conf')
+
+    # 用一个没有在配置文件中定义的logger名称来创建一个日志器logger
+    return logging.getLogger()
+
+def log_start_msg(msg):
+    """
+    执行开始时的简易日志输出
+    """
+    logging.info("-----------------%s 开始-----------------" % msg)
+
+def log_end_msg(msg):
+    """
+    执行结束时的简易日志输出
+    """
+    logging.info("-----------------%s 结束-----------------" % msg)
+
+def get_tip_internal(total_num):
+    """
+    计算进度提示间隔
+    """
+    # 尝试从缓存中获取
+    internal = tip_internal_cache.get(total_num)
+    # 不存在则进行计算并放入缓存中
+    if not internal:
+        internal = math.ceil(total_num * config.PRECENT_TIPS)
+        tip_internal_cache[total_num] = internal
+    return internal
+    
+
+def tip(total_num, cur_num, is_zero_base=True):
+    """
+    简易进度提示
+
+    total_num 总数量
+
+    cur_num 当前进度(0基)
+
+    internal 提示间隔
+    """
+
+    # TODO
+    # 修改成百分比提示
+
+    internal = get_tip_internal(total_num)
+
+    # cur_num + 1 是0基修正
+    if is_zero_base:
+        cur_num = cur_num + 1
+
+    # 进度提示
+    if cur_num == total_num:
+        logging.info("当前进度 %d / %d" % (total_num, total_num))
+    elif cur_num % internal == 0:
+        logging.info("当前进度 %d / %d" % (cur_num, total_num))
+
+def tip_in_size(total_size, cur_pos):
+    """
+    简易进度提示(用于不知道总行数的情形)
+
+    total_size 总数量
+
+    cur_num 当前进度
+    """
+
+    # 尝试从缓存中获取
+    tip_internal = tip_internal_cache.get(total_size)
+    if not tip_internal:
+        # 不存在缓存,构建 提示检查点 和 提示间隔 信息
+        internal = math.ceil(total_size * config.PRECENT_TIPS)
+        tip_internal= {
+            "check_point": cur_pos,
+            "internal": internal
+        }
+        # 放入缓存
+        tip_internal_cache[total_size] = tip_internal
+    
+    # 当前位置超过提示检查点则显示进度
+    if cur_pos >= tip_internal["check_point"]:
+
+        logging.info("当前进度 %d / %d" % (cur_pos, total_size))
+
+        # 修改 提示检查点
+        check_point = tip_internal["check_point"]
+        internal = tip_internal["internal"]
+
+        while cur_pos >= check_point:
+
+            check_point = check_point + internal
+
+            # 如果 提示检查点大于总值,则置为总值
+            if check_point > total_size:
+                check_point = total_size
+                # 如果不手动中断会陷入循环
+                break
+        
+        # 更新 提示检查点
+        tip_internal["check_point"] = check_point
+
+
+    
+
+def save_obj(path, obj):
+    """
+    保存对象至本地
+    """
+    with open(path, "wb") as f:
+        pickle.dump(obj, f)
+
+def load_obj(path):
+    """
+    加载对象
+    """
+    with open(path, "rb") as f:
+        return pickle.load(f)
+
+if __name__ == "__main__":
+
+    init_log()
+
+    log_start_msg(TITLE)
+
+    # 测试普通提示
+    # total = 3
+    # for i in range(total):
+    #     tip(total, i)
+
+    # 测试mmap的提示
+    # with open(config.KEY_FILE, "r", encoding=config.ENCODING_CHARSET) as fkey, \
+    #     mmap.mmap(fkey.fileno(), 0, access=mmap.ACCESS_READ) as fmmap:
+        
+    #     # 总大小
+    #     total_num = fmmap.size()
+
+    #     while True:
+    #         # 读取光标位置
+    #         cur_pos = fmmap.tell()
+    #         # 把光标移动到下一行
+    #         line = fmmap.readline()
+
+    #         # 进度显示
+    #         tip_in_size(total_num, cur_pos)
+
+    #         if not line:
+    #             break
+
+    # 测试逐行读取的进度提示
+    with open(config.KEY_FILE, "r", encoding=config.ENCODING_CHARSET) as fkey:
+
+        fkey.seek(0, os.SEEK_END)
+        total_num = fkey.tell()
+        fkey.seek(0)
+
+        while True:
+
+            cur_pos = fkey.tell()
+
+            line = fkey.readline()
+
+            tip_in_size(total_num, cur_pos)
+
+            if not line:
+                break;
+    
+    log_end_msg(TITLE)