今天就開始我們的實作,這次我取用的資料是資通安全管理法,這邊可以直接點擊網站下載。
1. 取得文件內的文字
要處理這個文件前,要先取得這個檔案的內容。
# 要先安裝套件請記得先輸入 pip install pdfplumber
# 取得文字內容
def extract_text_plumber(path):
all_text = []
with pdfplumber.open(path) as pdf:
for page in pdf.pages:
# extract_text 會抽取這一頁的文字
txt = page.extract_text() or ""
all_text.append(txt)
return "\n".join(all_text)
因為我們使用的是 PDF 所以我們這邊就使用 pdfplumber,其實我原本有使用 pypdf,只是擷取到的文字我自己檢查過可能會有些缺漏,因為 pypdf 不會考慮到排版的問題,除非你的文件比較沒有那麼複雜,否則我覺得使用 pypdf 也是可以的。
其實 pdfplumber 還有針對表格資料做處理,不過這次使用的文件沒有用到我就先略過這邊的介紹了。
這邊程式碼的邏輯是他會先從每一頁開始跑,跑完之後會抓裡面每一頁的文字這樣。
可以跑下面的程式碼檢查輸出:
text = extract_text_plumber("資通安全管理法.pdf")
print(text)
2. Chunking
我們拿到文字內容後,重點就是在 chunking 這塊了,因為其實很多都是用英文在教學 chunking 的,英文要切斷點其實很好切,因為每個空格都可以切分成一個詞句,但中文就沒有這麼好切了,可能你就只能用標點符號去切分文字,這邊其實也有專門切中文字的工具可以用,叫做 jieba,這邊先示範一下。
# 要先安裝套件請記得先輸入 pip install jieba
import jieba
# 精確模式(推薦)
words = jieba.cut(text, cut_all=False)
print("精確模式:", "/".join(words))
# 全模式(會把所有可能的詞都切出來,較冗餘)
words = jieba.cut(text, cut_all=True)
print("全模式:", "/".join(words))
# 搜索引擎模式(會多切一些詞,方便做檢索)
words = jieba.cut_for_search(text)
print("搜尋模式:", "/".join(words))
其實我自己的感覺,雖然可能精確模式會比較多人用,但針對條文這種東西,我覺得三種模式它可能都沒有切的那麼到位,畢竟我們可能自己看不懂條文為甚麼要這麼文謅謅><
這邊還有其他種方法,用正規表達式物件,我覺得也是最適用這情境的,下面是範例:
# 用 章 去分割
chapter_pattern = re.compile(r"第\s*[一二三四五六七八九十百千\d]+\s*章[^\n]*")
def split_by_chapter(text: str):
# 在整份文字裡,把符合 regex 的位置都找出來
matches = list(chapter_pattern.finditer(text))
chapters = []
for i, m in enumerate(matches):
start = m.start()
end = matches[i+1].start() if i+1 < len(matches) else len(text) # 下一章的開頭(如果沒有下一章,就到結尾)
chapter_text = text[start:end].strip() # 從「這一章的開頭」到「下一章的開頭前」這一段文字,就是完整的一章內容
chapters.append(chapter_text)
return chapters
可以跑下面的程式碼檢查輸出
chapters = split_by_chapter(text)
print("第一章內容:\n", chapters[0])
這邊我要先說,正因為這些是條文我才覺得可以論章節或一條條去切割,但如果是文章那些你是無從判斷到哪個斷點的,所以怎麼對文字做斷句,其實也要考量你的內容,正規表達式物件我就不多作介紹了。
其實我覺得後面條例的做法要去細切的話,也是跟上面的做法差不多,就交給大家去練習操作。
總結來說:Chunking 沒有一定的標準做法,但就是看你的內容去思考!
明天再接續今天的內容~大家敬請期待~