GitHub連結
一、PSP表格
PSP2.1 | Personal Software Process Stages | 預估耗時(分鐘) | 實際耗時(分鐘) |
---|---|---|---|
Planning | 計劃 | ||
· Estimate | · 估計這個任務需要多少時間 | 10 | 20 |
Development | 開發 | ||
· Analysis | · 需求分析 (包括學習新技術) | 120 | |
· Design Spec | · 生成設計文檔 | 30 | |
· Design Review | · 設計複審 | 5 | |
· Coding Standard | · 代碼規範 (為目前的開發制定合适的規範) | ||
· Design | · 具體設計 | 180 | 300 |
· Coding | · 具體編碼 | 900 | 1200 |
· Code Review | · 代碼複審 | 600 | |
· Test | · 測試(自我測試,修改代碼,送出修改) | ||
Reporting | 報告 | ||
· Test Repor | · 測試報告 | ||
· Size Measurement | · 計算工作量 | ||
· Postmortem & Process Improvement Plan | · 事後總結, 并提出過程改進計劃 | ||
· 合計 | 1585 | 2475 |
二、計算子產品接口
2.1 計算子產品接口的設計與實作過程
2.1.1 程式設計思路
- 在剛開始看到這個題時我隻能想到循環查找字元串、利用樹存儲來加快時間等模糊的想法,但并沒有實際的能力去實作。在我參考了不少同學的思路後,我發現總共大多是使用DFA或AC自動機的方法。在思考哪個更适合我之後,我選擇了用python來實作DFA算法。 如圖将關鍵詞“你真帥”“我真好”“你真牛”用該樹存儲起來。從根節點開始,在比較待查文本的字元時,若遇到“你”則進入“你”節點,并判斷此時狀态:顯然并不是終點,“帥”或“牛”才是。而如果整個比較過程都沒有出錯,順利到了終點,那麼便成功找到了一個關鍵詞,若出錯則重來。
- 在python中,用字典dict來實作DFA算法較友善。如下,可見使用字典實作可以避免不少麻煩。
state_event_dict = {
'你':{
'真':{
'帥':{
'is_end':True
},'is_end':False
'牛':{
'is_end':True
},'is_end':False
},
},
'我':{
'真':{
'好':{
'is_end':True
},'is_end':False
},'is_end':False
}
},
2.1.2代碼實作
-
類
-
内含class DFA
函數,自動生成keyword_list(關鍵詞查找樹),以及_generate_state_event_dict
函數,根據輸入的關鍵詞在(keyword_list)樹上查找并輸出。但隻提供了基礎的輸入輸出功能,對關鍵詞輸入的優化(增添删改)以及擷取資料的輸出格式還需外部函數進行優化。match
-
-
主要函數
- 将敏感詞從檔案輸入并轉為清單友善操作
-
将待查文本從檔案輸入轉為字元串友善操作def read_keywords(file_path): with open(file_path, encoding='utf-8') as keyword_list: return keyword_list.read().splitlines()
-
将資料按格式輸出到ans.txtdef read_article(file_path): with open(file_path, encoding='utf-8') as article: return article.read()
-
處理敏感字清單,加入拼音、拼音首字母、漢字、偏旁部首等各種變形的敏感字plusdef write_ans(file_path, ans_list): with open(file_path, 'w', encoding='utf-8') as ans: ans.write('total: '+str(ans_list[0])+'\n') for word in ans_list: if isinstance(word, int): continue ans.write('line'+str(word['line'])+': '+'<'+real_keyword[word['keyword']]+'> ' + word['match'] + '\n')
def word_handle(keyword_list): after_list = [] # 小寫 for keyword in keyword_list: after_list.append(keyword.lower()) # 轉拼音 for keyword in keyword_list: # 注意使用lazy_pinyin(一維清單)而不是pinyin(二維清單) # after_list.append("".join(lazy_pinyin(keyword))) pinyin_list = lazy_pinyin(keyword) # 首字母 first_letter_list = lazy_pinyin(keyword, 4) # 判斷是否中文避免數組越界( if ord(keyword[0]) > 255: dfs(after_list, pinyin_list, first_letter_list, "", 0, len(keyword)) return after_list
- 關鍵的遞歸,讓敏感字變形更迅速,擴充敏感字清單也就更友善
def dfs(after_list, pinyin_list, first_letter_list, cur_chars, w, length): if w == length: after_list.append(cur_chars) return dfs(after_list, pinyin_list, first_letter_list, cur_chars + first_letter_list[w], w + 1, length) dfs(after_list, pinyin_list, first_letter_list, cur_chars + pinyin_list[w], w + 1, length)
2.2 計算子產品接口部分的性能改進
- 由于pycharm是社群版沒有profiler,于是隻好用了自帶的cprofile,由圖可見第三方庫的引用占了不少的時間
2.3 計算子產品部分單元測試展示
敏感詞1
待查文本1
答案1
2.4 計算子產品部分異常處理說明
三、心得
- 在寫代碼前一定要預留出足夠的時間去思考需要完成什麼、需要學什麼、怎麼調試,并且題目一定一定一定要看清楚,不然可能會出現急頭白臉看了一堆資料、寫了一堆東西結果沒用的情況。
- 而本次實驗對我來說比較難,參考了好多教程、代碼,用了好多不同的方式才勉強出來一部分。但是即便花了不少精力,還是沒能來得及,反思了下,原因應該是沒有客觀合理地預料這一周需要完成的各種事務,以至于沒能預留出足夠的時間在這個項目上,導緻哪怕快通宵了還是沒能完成。不過這才是第一次,希望吸取了經驗教訓後将來能有所進步。