1. Django敏感詞檢測(cè)

        共 5245字,需瀏覽 11分鐘

         ·

        2022-08-10 01:29

        作者:vk

        鏈接:https://0vk.top/zh-hans/article/details/65

        來(lái)源:愛(ài)尚購(gòu)?

        點(diǎn)擊閱讀更多獲取極致閱讀體驗(yàn)


        c5af07a218854ee7e8c082caace72da6.webp

        為了識(shí)別和過(guò)濾用戶(hù)提交的惡意內(nèi)容,每一條人工檢查的成本又太大,需要開(kāi)發(fā)一個(gè)自動(dòng)檢測(cè)敏感詞的程序

        運(yùn)行效果如下:

        2f85c2ef73bcf6056f438c4c6c884e14.webp

        ?

        整體設(shè)計(jì)思路:

        ecf11b30165b5fe3a22f50f6832f344c.webp獲取用戶(hù)提交內(nèi)容

        通過(guò)自定義中間件的方式獲取用戶(hù)提交內(nèi)容

        要在請(qǐng)求來(lái)的時(shí)候就將惡意內(nèi)容扼殺在搖籃中,使用process_request方法。獲取到內(nèi)容中如果有敏感詞直接在中間件里返回處理內(nèi)容即可。

        新建一個(gè)py文件,自定義一個(gè)類(lèi),并且該類(lèi)必須繼承MiddlewareMixin,然后在process_request方法里寫(xiě)入自己的過(guò)濾方法。這個(gè)方法名字是不能改的

        from?django.utils.deprecation?import?MiddlewareMixin
        # 定義一個(gè)類(lèi)繼承MiddlewareMixin 并實(shí)現(xiàn)下面的方法,在這兩個(gè)方法 中定義或者攔截對(duì)應(yīng)的請(qǐng)求# 可以在中間件中添加用戶(hù)認(rèn)證和登錄設(shè)置等信息class CustomMiddle(MiddlewareMixin): def process_request(self, request): print('過(guò)濾代碼',request)

        然后在settings.py里面注冊(cè)該中間件即可使用,位置最好放在最后面,因?yàn)檎?qǐng)求經(jīng)過(guò)中間件是從上到下的,指不定自定義的中間件要依賴(lài)上面哪個(gè)中間件的結(jié)果

        判斷是否屬于敏感詞

        這里有三種方法:

        replace過(guò)濾

        import?time  old = time.time()    with open("1", encoding='utf-8') as f:????????word?=?'可愛(ài)'        for keyword in f:            if keyword == word:                print(word.replace(word, '*'))    now = time.time()????print(now?-?old,'replace方法')

        這個(gè)文件1里存放的就是敏感詞庫(kù)

        正則過(guò)濾

        import?re    old = time.time()    def check_filter(keywords, word):        return re.sub("|".join(keywords), "***", word)    with open("1", encoding='utf-8') as f:        keywords=[]        for i in f:            keywords.append(i.strip('\n'))    print(check_filter(keywords, word))    now = time.time()    print(now - old, '正則方法')

        DFA算法(推薦)

        這個(gè)算法的核心是把敏感詞庫(kù)構(gòu)造成樹(shù)結(jié)構(gòu),比如現(xiàn)在敏感詞庫(kù)有:“大家好,大人,帥氣,大部隊(duì)”

        前兩種方法就是循環(huán)詞庫(kù)每一行,然后對(duì)比,假設(shè)詞庫(kù)很大,這樣逐行對(duì)比效率很低

        DFA算法將敏感詞生成一個(gè)下圖這種結(jié)構(gòu)

        5c307ae83cbd258d6b385af6d6eb7960.webp


        組成樹(shù)形結(jié)構(gòu)的好處就是可以減少索引次數(shù),理論上只需要遍歷?遍代檢測(cè)的?本,看看是否在敏感詞庫(kù)中即可。

        ?如輸?"我感覺(jué)我?分帥?",前?個(gè)均未在詞庫(kù)中匹配,全部pass掉。直到出現(xiàn)”帥”字時(shí)在?樹(shù)中找到了,接下來(lái)繼續(xù)遍歷發(fā)現(xiàn)”?”字出現(xiàn)在?樹(shù)的?節(jié)點(diǎn) 中,就說(shuō)明帥?是敏感詞。

        在python中我們可以?字典儲(chǔ)存敏感詞詞庫(kù)樹(shù)結(jié)構(gòu),理論上字典的查詢(xún)時(shí)間復(fù)雜度為 O(1)。

        我們把第?個(gè)字符作為字典的鍵,值為另?個(gè)字典以此類(lèi)推,字典最后?項(xiàng)定義為{'\x00': 0}?來(lái)表示最后?個(gè)字符

        884b3afbabf061ba16ef092f08cf6744.webp

        定義一個(gè)類(lèi),并且初始化變量,生成樹(shù)結(jié)構(gòu):

        882ec1f18e0224b462cab95855ff1055.webp

        制作的字典如下圖763a75c60abeb37733a940774147b5c0.webp

        現(xiàn)在我們需要做的就是編寫(xiě)add?法的具體內(nèi)容:

        f29704500ae578794c8537ee052e5562.webp

        ?

        如“大家好”,循環(huán)結(jié)束后的self.key_chains應(yīng)該變?yōu)?

        ?{大:{家:{好:{}}}}?。當(dāng)“大家好”處理完成后輪到“大人”時(shí),發(fā)現(xiàn)“大”已經(jīng)為字典的鍵,所以進(jìn)入If 判斷,update level 的value。

        使level update為之前“大”對(duì)應(yīng)的值,這仍舊是一個(gè)字典。接著進(jìn)入else將“大”加到和“家”同級(jí)別的dict中

        此時(shí)的結(jié)構(gòu)如下圖:

        59eabb2bf2602c8bf93ebdd2314b25ae.webp

        ?

        樹(shù)字典構(gòu)建好了接下來(lái)需要做的就是過(guò)濾了


        dfb7a27c60dc6725f6b695fd3350d520.webp

        完整代碼
        import?jiebafrom django.conf import settingsimport time
        class DFAFilter(): ''' Filter Messages from keywords
        Use DFA to keep algorithm perform constantly
        f = DFAFilter() f.add("sexy") f.filter("hello sexy baby") hello **** baby '''
        def __init__(self): self.stopwords = ['!'] self.keyword_chains = {} self.delimit = '\x00' with open(settings.FILTER_PATH, encoding='utf-8') as f: for keyword in f: self.add(keyword.strip()) def add(self, keyword):
        if not isinstance(keyword, str): keyword = keyword.decode('utf-8') keyword = keyword.lower() chars = keyword.strip() if not chars: return level = self.keyword_chains for i in range(len(chars)): if chars[i] in level: level = level[chars[i]]
        else: if not isinstance(level, dict): break for j in range(i, len(chars)): level[chars[j]] = {} last_level, last_char = level, chars[j] level = level[chars[j]]
        last_level[last_char] = {self.delimit: 0} break if i == len(chars) - 1: level[self.delimit] = 0 def filter(self, message, repl="*"): stop_list1 = [] stop_list2 = [] stop_index = -1 if not isinstance(message, str): message = message.decode('utf-8') message = message.lower()
        wordlist = jieba.lcut(message) stop = set(self.stopwords) for i in wordlist: if i == ' ' or '': stop_index = message.index(i, stop_index + 1, len(message)) stop_list1.append(stop_index) stop_list2.append('') wordlist.remove(i) if i in stop: stop_index = message.index(i, stop_index + 1, len(message)) stop_list1.append(stop_index) stop_list2.append(i) wordlist.remove(i)
        message = ''.join(wordlist) ret = [] start = 0 danger = 0 while start < len(message): level = self.keyword_chains step_ins = 0 for char in message[start:]:
        if char in level: step_ins += 1
        if self.delimit not in level[char]: level = level[char]
        else: danger += 1 ret.append(repl * step_ins) start += step_ins - 1 break
        else: ret.append(message[start]) print(ret) break else: ret.append(message[start])
        start += 1 result = list(''.join(ret)) for i, j in zip(stop_list1, stop_list2): result.insert(i, j)
        return ''.join(result), danger

        沒(méi)有數(shù)據(jù)支持的對(duì)比都是詐騙:

        1603611cbc2bd533ea9e8a89943b133c.webp

        c52dc7679b43bd9d71e85679c1c034b9.webp

        401bc0ff603fd2d3101ee6566c001053.webp

        e769f1c5784bce758371a7f18f9b740d.webp


        可以看到:正則方法所用的時(shí)間是隨著詞庫(kù)的擴(kuò)大而增大,replace是詞庫(kù)少于2000個(gè)詞的時(shí)候表現(xiàn)良好,而DFA算法是大于2000時(shí)表現(xiàn)良好

        后臺(tái)控制敏感詞名單的增減

        DFA算法生成字典那里我們可以做出優(yōu)化,不用每次運(yùn)行都生成字典,而是把字典用pickle.dump持久話(huà)存儲(chǔ)在內(nèi)存中,用的時(shí)候再讀,這樣就快了很多。

        把敏感詞庫(kù)的詞所對(duì)應(yīng)的字段在admin中注冊(cè)就可以后臺(tái)直接控制詞庫(kù)了,我就不再操作拿IP黑名單字段演示。

        類(lèi)似下圖,這樣我們就可以在后臺(tái)管理是否啟用特定的敏感詞或者增刪特定的敏感詞了

        5a1c6c672525cab71ab8285740deb99b.webp

        持久化存儲(chǔ)文件更新

        當(dāng)我們?cè)黾踊騽h除了敏感詞的時(shí)候,對(duì)應(yīng)的持久化文件也應(yīng)該發(fā)生改變,可以在model里面重寫(xiě)save和delete方法即可。

        f3cbab2f5f0df16dced65c3ff4352dcb.webp

        不用信號(hào)的原因是無(wú)需操作別的數(shù)據(jù)庫(kù)模型和第三方app,只是重新pickle.dump update了一個(gè)新的持久化文件

        ?單詞數(shù):349字符數(shù):5138

        瀏覽 69
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
          
          

            1. 无码操逼 | 王者荣耀女角色张嘴流眼泪翻白眼图片 | 成人AV资源站 | 欧美激情一 | 欧美在线黄 |