天天看點

資料預處理之抽取文本資訊(2)

大資料技術與我們日常生活越來越緊密,要做大資料,首要解決資料問題。原始資料存在大量不完整、不一緻、有異常的資料,嚴重影響到資料模組化的執行效率,甚至可能導緻模型結果的偏差,是以要資料預處。資料預處理主要是将原始資料經過文本抽取、資料清理、資料內建、資料處理、資料變換、資料降維等處理後,不僅提高了資料品質,而且更好的提升算法模型性能。資料預處理在資料挖掘、自然語言處理、機器學習、深度學習算法中起着重要的作用。(本文原創,轉載必須注明出處.)

 Python資料預處理之抽取文本資訊(2)

白甯超  2018年12月28日10:28:48

摘要:大資料技術與我們日常生活越來越緊密,要做大資料,首要解決資料問題。原始資料存在大量不完整、不一緻、有異常的資料,嚴重影響到資料模組化的執行效率,甚至可能導緻模型結果的偏差,是以要資料預處。資料預處理主要是将原始資料經過文本抽取、資料清理、資料內建、資料處理、資料變換、資料降維等處理後,不僅提高了資料品質,而且更好的提升算法模型性能。資料預處理在資料挖掘、自然語言處理、機器學習、深度學習算法中起着重要的作用。(本文原創,轉載必須注明出處.)

1 資料類型與資料采集

通常說的資料指的的數字、圖表資訊這些。在大資料領域所謂的資料總體包括結構化資料、半結構化資料和非結構化資料。

結構化資料

結構化的資料是指可以使用關系型資料庫表示和存儲,表現為二維形式的資料。一般特點是:資料以行為機關,一行資料表示一個實體的資訊,每一行資料的屬性是相同的。比如:

id name age gender
1 張三 12
2 李花 13
3 王五 18
  • 資料特點:關系模型資料,關系資料庫表示。
  • 常見格式:比如MySQL、Oracle、SQL Server等。
  • 應用場合:資料庫、系統網站、資料備份、ERP等。
  • 資料采集:DB導出、SQL等方式。

結構化的資料的存儲和排列是很有規律的,這對查詢和修改等操作很有幫助。但是,它的擴充性不好。

半結構化資料

半結構化資料是結構化資料的一種形式,它并不符合關系型資料庫或其他資料表的形式關聯起來的資料模型結構,但包含相關标記,用來分隔語義元素以及對記錄和字段進行分層。是以,它也被稱為自描述的結構。半結構化資料,屬于同一類實體可以有不同的屬性,即使他們被組合在一起,這些屬性的順序并不重要。常見的半結構資料有XML如下:

<person>
    <name>李花</name>
    <age>13</age>
    <gender>女</gender>
</person>
           
  • 資料特點:非關系模型資料,還有一定的格式。
  • 常見格式:比如Email、HTML、XML、JSON等。
  • 應用場合:郵件系統、檔案系統、新聞網站等。
  • 資料采集:網絡爬蟲、資料解析等方式。

不同的半結構化資料的屬性的個數是不定的。有些人說半結構化資料是以樹或者圖的資料結構存儲的資料,上面的例子中,标簽是樹的根節點,和标簽是子節點。通過這樣的資料格式,可以***地表達很多有用的資訊,包括自我描述資訊(中繼資料)。是以,半結構化資料的擴充性是很好的。

非結構化資料

就是沒有固定結構的資料。各種文檔、圖檔、視訊/音頻等都屬于非結構化資料。對于這類資料,我們一般直接整體進行存儲,而且一般存儲為二進制的資料格式。如下所示:

資料預處理之抽取文本資訊(2)
  • 資料特點:沒有固定格式的資料
  • 常見格式:Word、PDF、PPT、圖檔、音視訊等。
  • 應用場合:圖檔識别、人臉識别、醫療影像、文本分析等。
  • 資料采集:網絡爬蟲、資料存檔等方式。

2 常見的文本抽取方法

針對資料不同形式,通過特定方式的資料采集方式(文檔下載下傳、資料庫導出、網絡爬蟲、語音收集、圖檔解析等等)擷取資料,無論是結構化的資料庫檔案、半結構化的網頁資料,還是非結構化的圖檔、音視訊。我們最終的目的都是将資料傳入到電腦之中,通過算法模型挖掘其潛在的價值,為最終的AI技術做支撐。不同的是,在結構化和半結構化資料資料內建過程中,我們可以提取相關文本資訊,做進一步的資料預處理;而非結構化的圖檔、音視訊我們采用一定的技術手段,擷取其對應的資料點矩陣。這一點不太容易了解,我們比如說想解析一張圖檔的資料,我們知道圖檔是有長寬高組成的,還包括紅藍綠三種基本色。那麼我們就找到對應的多元特征,采用資料點占位表示,比如:

圖檔名 長(bit) 寬(bit)
貓1 12 100 1
狗2 101 234 1 1 1
豬3 202 24 1

上面就資料表示貓1這張圖檔,長寬位點(12,100)處隻有藍色構成;狗2這張圖檔,長寬位點(101,234)處有紅綠藍3中色構成;豬3這張圖檔,長寬位點(202,24)處隻有綠構成。這就是非結構資料圖檔轉化為數值型資料的原理。完整流程資料挖掘的流程圖如下所示:

資料預處理之抽取文本資訊(2)

我根據不同的資料類型,采用對應的資料采集方式擷取目标資料。這時候的資料品質很差,存在文本格式不同,資料表示形式不同等諸多問題。這裡我們單純的考慮文本資訊的處理,就文本資訊而言,你采集的資料可能是網頁、資料庫檔案、pdf文檔、word文檔等等。我們想去處理這些資料,還需要對資料進行內建即轉化為統一的資料格式,這裡我們就需要文本資訊抽取,常見的抽取方式包括以下幾個内容:線上格式轉換工具、office内置格式轉換、自己開發文本抽取工具。詳見下圖:

資料預處理之抽取文本資訊(2)

經過實際操作會發現采用線上格式轉換工具存在幾個弊端,其限制檔案轉化的資料,要麼就是收費的;而采用本地的office自帶文檔,一個個另存為文本,肯定不現實。基于上述情況,我們對工具抽取的弊端總結如下:

  • 格式轉換後,識别亂碼較多
  • 不支援或者限制支援批量處理
  • 批量轉化收費問題
  • 格式轉換後的txt檔案存在編碼問題
  • 生成檔案名一堆數字亂碼
  • 操作不夠靈活便捷

我們針對以上問題,就去尋求解決方式,那就是自己動手豐衣足食,我們自己去打造批量文本抽取問題,我們期待效果是:

  • 支援PDF/Word等多格式文本抽取
  • 自動過濾不符合指定格式的檔案
  • 生成的目标檔案與原檔案目錄一緻
  • 生成文檔采用統一的編碼格式儲存(如:UTF-8 )
  • 支援預設儲存路徑和自定義儲存路徑

3 抽取Word文檔文本

做word文檔抽取工作,我們運作環境是在win10-64bit下,python3.5,Anaconda4.4版本下執行的,所使用的插件是win32com。下載下傳位址:https://pan.baidu.com/s/1-2BsiTs8XjMIe5Gnh_GFjw 密碼: 7j3t

預裝完win32com以後,以下代碼便完成抽取word文本資訊。

算法思路:
  • 定義檔案路徑和轉存路徑:split
  • 修改新的檔案名:fnmatch
  • 設定完整的儲存路徑:join
  • 啟動應用程式格式轉換:Dispatch
  • 儲存文本:SaveAs
算法流程:
資料預處理之抽取文本資訊(2)
代碼實作:
#coding=utf-8

"""
Description: Word檔案轉化TXT文本
Author:伏草惟存
Prompt: code in Python3 env
Install package: pip install pypiwin32
"""

import os,fnmatch
from win32com import client as wc
from win32com.client import Dispatch


\'\'\'
功能描述:word檔案轉存txt檔案,預設存儲目前路徑下;使用者可以指定存儲檔案路徑。
參數描述:1 filePath:檔案路徑   2 savePath: 指定儲存路徑
\'\'\'
def Word2Txt(filePath,savePath=\'\'):
    # 1 切分檔案上級目錄和檔案名
    dirs,filename = os.path.split(filePath)
    # print(dirs,\'\n\',filename)

    # 2 修改轉化後的檔案名
    new_name = \'\'
    if fnmatch.fnmatch(filename,\'*.doc\'):
        new_name = filename[:-4]+\'.txt\'
    elif fnmatch.fnmatch(filename,\'*.docx\'):
        new_name = filename[:-5]+\'.txt\'
    else: return
    print(\'->\',new_name)

    # 3 檔案轉化後的儲存路徑
    if savePath==\'\': savePath = dirs
    else: savePath = savePath
    word_to_txt = os.path.join(savePath,new_name)
    print(\'->\',word_to_txt)

    # 4 加載處理應用,word轉化txt
    wordapp = wc.Dispatch(\'Word.Application\')
    mytxt = wordapp.Documents.Open(filePath)
    mytxt.SaveAs(word_to_txt,4)
    mytxt.Close()



if __name__==\'__main__\':
    filepath = os.path.abspath(r\'../dataSet/filename.doc\')
    # savepath = \'\'
    Word2Txt(filepath)
           

4 抽取PDF文檔文本

算法思路:
  • 定義檔案路徑和轉存路徑:split
  • 修改新的檔案名:fnmatch
  • 設定完整的儲存路徑:join
  • 啟動應用程式格式轉換:Dispatch
  • 儲存文本:SaveAs
算法流程:
資料預處理之抽取文本資訊(2)
代碼實作:
# coding=utf-8

"""
Description: PDF檔案轉化TXT文本
Author:伏草惟存
Prompt: code in Python3 env
"""

import os,fnmatch
from win32com import client as wc
from win32com.client import Dispatch,gencache


\'\'\'
功能描述:pdf檔案轉化txt文本
參數描述:1 filePath:檔案路徑  2 savePath: 指定儲存路徑
\'\'\'
def Pdf2Txt(filePath,savePath=\'\'):
    # 1 切分檔案上級目錄和檔案名
    dirs,filename = os.path.split(filePath)
    # print(\'目錄:\',dirs,\'\n檔案名:\',filename)

    # 2 修改轉化後的檔案名
    new_name = ""
    if fnmatch.fnmatch(filename,\'*.pdf\') or fnmatch.fnmatch(filename,\'*.PDF\'):
        new_name = filename[:-4]+\'.txt\' # 截取".pdf"之前的檔案名
    else: return
    print(\'新的檔案名:\',new_name)

    # 3 檔案轉化後的儲存路徑
    if savePath=="": savePath = dirs
    else: savePath = savePath
    pdf_to_txt = os.path.join(savePath,new_name)
    print(\'儲存路徑:\',pdf_to_txt)

    # 4 加載處理應用,pdf轉化txt
    wordapp = wc.Dispatch(\'Word.Application\')
    mytxt = wordapp.Documents.Open(filePath)
    mytxt.SaveAs(pdf_to_txt,4)
    mytxt.Close()



if __name__==\'__main__\':
    # 使用絕對路徑
    filePath = os.path.abspath(r\'../dataSet/Corpus/pdftotxt/2018年世界新聞***日.pdf\')
    # savePath = r\'E:\\\'
    Pdf2Txt(filePath)
           

5 文本抽取工具與編碼

算法思路:
  • 定義檔案夾路徑和轉存夾路徑:split
  • 修改新的檔案名:TranType(filename, typename)、fnmatch
  • 設定完整的儲存路徑:join
  • 啟動應用程式格式轉換:Dispatch
  • 儲存文本:SaveAs
代碼實作
#coding=utf-8

"""
Description: 多文檔格式轉換工具
Author:伏草惟存
Prompt: code in Python3 env
"""

import os,fnmatch
from win32com import client as wc
from win32com.client import Dispatch,gencache


\'\'\'
功能描述:抽取檔案文本資訊
參數描述:1 filePath:檔案路徑  2 savePath: 指定儲存路徑
\'\'\'
def Files2Txt(filePath,savePath=\'\'):
    try:
        # 1 切分檔案上級目錄和檔案名
        dirs,filename = os.path.split(filePath)
        # print(\'目錄:\',dirs,\'\n檔案名:\',filename)

        # 2 修改轉化後的檔案名
        typename = os.path.splitext(filename)[-1].lower() # 擷取字尾
        new_name = TranType(filename,typename)
        # print(\'新的檔案名:\',new_name)

        # 3 檔案轉化後的儲存路徑
        if savePath=="": savePath = dirs
        else: savePath = savePath
        new_save_path = os.path.join(savePath,new_name)
        print(\'儲存路徑:\',new_save_path)

        # 4 加載處理應用
        wordapp = wc.Dispatch(\'Word.Application\')
        mytxt = wordapp.Documents.Open(filePath)
        mytxt.SaveAs(new_save_path,4)
        mytxt.Close()
    except Exception as e:
        pass


\'\'\'
功能描述:根據檔案字尾修改檔案名
參數描述:1 filePath:檔案路徑  2 typename 檔案字尾
傳回資料:new_name 傳回修改後的檔案名
\'\'\'
def TranType(filename,typename):
    # 新的檔案名稱
    new_name = ""
    if typename == \'.pdf\' : # pdf->txt
        if fnmatch.fnmatch(filename,\'*.pdf\') :
            new_name = filename[:-4]+\'.txt\' # 截取".pdf"之前的檔案名
        else: return
    elif typename == \'.doc\' or typename == \'.docx\' :  # word->txt
        if fnmatch.fnmatch(filename, \'*.doc\') :
            new_name = filename[:-4]+\'.txt\'
        elif fnmatch.fnmatch(filename, \'*.docx\'):
            new_name = filename[:-5]+\'.txt\'
        else: return
    else:
        print(\'警告:\n您輸入[\',typename,\']不合法,本工具支援pdf/doc/docx格式,請輸入正确格式。\')
        return
    return new_name



if __name__ == \'__main__\':
    filePath1 = os.path.abspath(r\'../dataSet/Corpus/wordtotxt/一種改進的樸素貝葉斯文本分類方法研究.doc\')
    filePath2 = os.path.abspath(r\'../dataSet/Corpus/pdftotxt/改進樸素貝葉斯文本分類方法研究.pdf\')
    filePath3 = os.path.abspath(r\'../dataSet/Corpus/wordtotxt/科技項目資料挖掘決策架構.docx\')
    Files2Txt(filePath3)
           
周遊讀取檔案
  • 周遊檔案的類TraversalFun : TraversalDir、 AllFiles
  • 周遊目錄檔案TraversalDir : AllFiles(self.rootDir)
  • 遞歸周遊檔案AllFiles: AllFiles(self,rootDir)
  • 判斷是否為檔案isfile :列印出檔案名
  • 判斷是否是目錄isdir :遞歸周遊
周遊檔案源碼實作
# coding=utf-8

"""
Description: 周遊讀取檔案名
Author:伏草惟存
Prompt: code in Python3 env
"""

import os,time


\'\'\'
功能描述:周遊目錄處理子檔案
參數描述: 1 rootDir 目标檔案的根目錄
\'\'\'
class TraversalFun():
    # 1 初始化
    def __init__(self,rootDir):
        self.rootDir = rootDir # 目錄路徑

    # 2 周遊目錄檔案
    def TraversalDir(self):
        TraversalFun.AllFiles(self,self.rootDir)

    # 3 遞歸周遊所有檔案,并提供具體檔案操作功能
    def AllFiles(self,rootDir):
        # 傳回指定目錄包含的檔案或檔案夾的名字的清單
        for lists in os.listdir(rootDir):
            # 待處理檔案夾名字集合
            path = os.path.join(rootDir, lists)
            # 核心算法,對檔案具體操作
            if os.path.isfile(path):
                print(os.path.abspath(path))
            # 遞歸周遊檔案目錄
            elif os.path.isdir(path):
                TraversalFun.AllFiles(self,path)



if __name__ == \'__main__\':
    time_start=time.time()

    # 根目錄檔案路徑
    rootDir = r"../dataSet/Corpus/EnPapers"
    tra=TraversalFun(rootDir) # 預設方法參數列印所有檔案路徑
    tra.TraversalDir()     # 周遊檔案并進行相關操作

    time_end=time.time()
    print(\'totally cost\',time_end-time_start,\'s\')
           

6 實戰案例:周遊檔案批量抽取新聞文本内容

算法思路
  • 引用外部文本抽取子產品:import ExtractTxt as ET
  • 參數方法使用:TraversalFun(rootDir,ET.Files2Txt,saveDir)
  • 建立儲存根目錄:os.path.abspath
  • 遞歸周遊檔案:func(path, save_dir)
源碼實作
# coding=utf-8

"""
Description: 批量文檔格式自動轉化txt
Author:伏草惟存
Prompt: code in Python3 env
"""

import ExtractTxt as ET
import os,time


\'\'\'
功能描述:周遊目錄,對子檔案單獨處理
參數描述:1 rootDir 根目錄  2 deffun:方法參數  3 saveDir: 儲存路徑
\'\'\'
class TraversalFun():
    # 1 初始化
    def __init__(self,rootDir,func=None,saveDir=""):
        self.rootDir = rootDir # 目錄路徑
        self.func = func   # 參數方法
        self.saveDir = saveDir # 儲存路徑

    # 2 周遊目錄檔案
    def TraversalDir(self):
        # 切分檔案上級目錄和檔案名
        dirs,latername = os.path.split(self.rootDir)
        # print(rootDir,\'\n\',dirs,\'\n\',latername)

        # 儲存目錄
        save_dir = ""
        if self.saveDir=="": # 預設檔案儲存路徑
            save_dir = os.path.abspath(os.path.join(dirs,\'new_\'+latername))
        else: save_dir = self.saveDir

        # 建立目錄檔案
        if not os.path.exists(save_dir): os.makedirs(save_dir)
        print("儲存目錄:\n"+save_dir)

        # 周遊檔案并将其轉化txt檔案
        TraversalFun.AllFiles(self,self.rootDir,save_dir)


    # 3 遞歸周遊所有檔案,并提供具體檔案操作功能
    def AllFiles(self,rootDir,save_dir=\'\'):
        # 傳回指定目錄包含的檔案或檔案夾的名字的清單
        for lists in os.listdir(rootDir):
            # 待處理檔案夾名字集合
            path = os.path.join(rootDir, lists)

            # 核心算法,對檔案具體操作
            if os.path.isfile(path):
                self.func(os.path.abspath(path),os.path.abspath(save_dir))

            # 遞歸周遊檔案目錄
            if os.path.isdir(path):
                newpath = os.path.join(save_dir, lists)
                if not os.path.exists(newpath):
                    os.mkdir(newpath)
                TraversalFun.AllFiles(self,path,newpath)




if __name__ == \'__main__\':
    time_start=time.time()

    # 根目錄檔案路徑
    rootDir = r"../dataSet/Corpus/EnPapers"
    # saveDir = r"./Corpus/TxtEnPapers"
    tra=TraversalFun(rootDir,ET.Files2Txt) # 預設方法參數列印所有檔案路徑
    tra.TraversalDir()                   # 周遊檔案并進行相關操作

    time_end=time.time()
    print(\'totally cost\',time_end-time_start,\'s\')
           

7源碼擷取

源碼請進【機器學習和自然語言QQ群:436303759】檔案下載下傳:
資料預處理之抽取文本資訊(2)
資料預處理之抽取文本資訊(2)