在文本分析的過程中,將原始數(shù)據(jù)轉(zhuǎn)換為TXT文件非常關(guān)鍵,主要出于以下幾個方面的考慮:
1.格式簡單與統(tǒng)一:
- TXT文件是一種簡單的文本格式,只包含純文本信息,不包含任何格式或樣式信息。這種簡單和統(tǒng)一的格式有助于減少在文本分析過程中可能出現(xiàn)的混淆或誤解。
- 其他格式的文檔,如PDF或word文檔,可能包含圖像、表格和其他非文本元素,還可能包含復(fù)雜的格式和樣式,這些都可能干擾文本分析的過程。
2. 便于文本預(yù)處理:
-
• 文本分析通常需要對文本數(shù)據(jù)進(jìn)行預(yù)處理,包括分詞、去停用詞、標(biāo)準(zhǔn)化等。TXT文件的簡單結(jié)構(gòu)使得這些預(yù)處理任務(wù)更容易執(zhí)行。
- • 與其他文件格式相比,TXT文件不包含任何復(fù)雜的格式或元數(shù)據(jù),這有助于簡化預(yù)處理步驟,減少可能出現(xiàn)的錯誤和問題。
3.兼容性:
-
• 大多數(shù)文本分析和自然語言處理(NLP)工具都能夠直接處理TXT文件。將原始數(shù)據(jù)轉(zhuǎn)換為TXT文件可以確保與這些工具的兼容性,從而簡化分析流程。
- • TXT文件是一種通用的文件格式,可以在不同的操作系統(tǒng)和軟件環(huán)境中輕松處理,而不需要特定的轉(zhuǎn)換或適配器。
4.節(jié)省資源:
-
• TXT文件通常比其他文件格式更小,這有助于節(jié)省存儲空間和提高處理速度。較小的文件大小也意味著需要較少的計(jì)算資源來處理文本數(shù)據(jù),從而提高分析效率。
- • 簡單的文本格式也意味著在處理時CPU和內(nèi)存的消耗較低,這對于大規(guī)模文本分析任務(wù)來說是非常重要的。
5.便于文本挖掘和模式識別:
-
• 純文本格式使得使用正則表達(dá)式和其他文本挖掘技術(shù)來識別和提取文本中的模式變得更為容易和直接。
- • 純文本數(shù)據(jù)也便于實(shí)現(xiàn)各種文本分析技術(shù),如情感分析、主題建模和實(shí)體識別等。
6.可讀性和可檢查性:
- • 人類可以直接讀取和理解TXT文件,這對于檢查、調(diào)試和理解文本分析的結(jié)果非常重要。
7.數(shù)據(jù)清洗:
-
• TXT文件的簡單性使得更容易識別和處理缺失值、錯誤和其他數(shù)據(jù)質(zhì)量問題,從而保證文本分析的準(zhǔn)確性和可靠性。
將原始數(shù)據(jù)轉(zhuǎn)換為TXT文件是實(shí)現(xiàn)有效和準(zhǔn)確文本分析的一個基本步驟,它幫助簡化和標(biāo)準(zhǔn)化文本分析流程,從而提高分析的效率和質(zhì)量。以下代碼可以用來將pdf文件轉(zhuǎn)換為txt文件。
pdf2txt.py
#!/usr/bin/env Python/ target=_blank class=infotextkey>Python # 該行命令告訴操作系統(tǒng)使用 Python 解釋器執(zhí)行此文件
import sys # 導(dǎo)入sys模塊,用于處理與Python解釋器和運(yùn)行時環(huán)境有關(guān)的操作
from pdfminer.pdfdocument import PDFDocument # 從pdfminer模塊導(dǎo)入PDFDocument類,用于表示PDF文檔
from pdfminer.pdfparser import PDFParser # 從pdfminer模塊導(dǎo)入PDFParser類,用于解析PDF文檔
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter # 從pdfminer模塊導(dǎo)入資源管理和頁面解釋類
from pdfminer.pdfdevice import PDFDevice, TagExtractor # 從pdfminer模塊導(dǎo)入PDF設(shè)備和標(biāo)簽提取器類
from pdfminer.pdfpage import PDFPage # 從pdfminer模塊導(dǎo)入PDFPage類,用于表示PDF頁面
from pdfminer.converter import XMLConverter, htmlConverter, TextConverter # 從pdfminer模塊導(dǎo)入轉(zhuǎn)換器類,用于將PDF轉(zhuǎn)換為其他格式
from pdfminer.cmapdb import CMapDB # 從pdfminer模塊導(dǎo)入字符映射數(shù)據(jù)庫類
from pdfminer.layout import LAParams # 從pdfminer模塊導(dǎo)入布局分析參數(shù)類
from pdfminer.image import ImageWriter # 從pdfminer模塊導(dǎo)入圖像寫入類
# 定義主函數(shù),argv是一個包含命令行參數(shù)的列表
def mAIn(argv):
import getopt # 導(dǎo)入getopt模塊,用于解析命令行參數(shù)
# 定義一個顯示用法的內(nèi)部函數(shù)
def usage():
print ('usage: %s [-P password] [-o output] [-t text|html|xml|tag]'
' [-O output_dir] [-c encoding] [-s scale] [-R rotation]'
' [-Y normal|loose|exact] [-p pagenos] [-m maxpages]'
' [-S] [-C] [-n] [-A] [-V] [-M char_margin] [-L line_margin]'
' [-W word_margin] [-F boxes_flow] [-d] input.pdf ...' % argv[0])
return 100 # 返回一個錯誤代碼
try:
# 使用getopt解析命令行參數(shù)
(opts, args) = getopt.getopt(argv[1:], 'dP:o:t:O:c:s:R:Y:p:m:SCnAVM:W:L:F:')
except getopt.GetoptError:
return usage() # 如果解析失敗,則顯示用法并退出
if not args: return usage() # 如果沒有提供非選項(xiàng)參數(shù)(例如輸入文件),則顯示用法并退出
# 初始化一些變量
debug = 0 # 調(diào)試級別
password = b'' # PDF密碼
pagenos = set() # 要處理的頁碼集
maxpages = 0 # 最大頁數(shù)
outfile = None # 輸出文件名
outtype = None # 輸出類型
imagewriter = None # 圖像寫入對象
rotation = 0 # 旋轉(zhuǎn)角度
stripcontrol = False # 是否剝離控制字符
layoutmode = 'normal' # 布局模式
encoding = 'utf-8' # 編碼方式
pageno = 1 # 頁面號
scale = 1 # 縮放因子
caching = True # 是否緩存
showpageno = True # 是否顯示頁面號
laparams = LAParams() # 布局分析參數(shù)對象
for (k, v) in opts: # 遍歷選項(xiàng)和值
if k == '-d': debug += 1 # 設(shè)置調(diào)試級別
elif k == '-P': password = v.encode('ascii') # 設(shè)置密碼
elif k == '-o': outfile = v # 設(shè)置輸出文件名
elif k == '-t': outtype = v # 設(shè)置輸出類型
elif k == '-O': imagewriter = ImageWriter(v) # 創(chuàng)建圖像寫入對象
elif k == '-c': encoding = v # 設(shè)置編碼方式
elif k == '-s': scale = float(v) # 設(shè)置縮放因子
elif k == '-R': rotation = int(v) # 設(shè)置旋轉(zhuǎn)角度
elif k == '-Y': layoutmode = v # 設(shè)置布局模式
elif k == '-p': pagenos.update(int(x)-1 for x in v.split(',')) # 更新頁碼集
elif k == '-m': maxpages = int(v) # 設(shè)置最大頁數(shù)
elif k == '-S': stripcontrol = True # 啟用剝離控制字符
elif k == '-C': caching = False # 禁用緩存
elif k == '-n': laparams = None # 禁用布局分析參數(shù)
elif k == '-A': laparams.all_texts = True # 啟用所有文本選項(xiàng)
elif k == '-V': laparams.detect_vertical = True # 啟用垂直檢測選項(xiàng)
elif k == '-M': laparams.char_margin = float(v) # 設(shè)置字符邊距
elif k == '-W': laparams.word_margin = float(v) # 設(shè)置單詞邊距
elif k == '-L': laparams.line_margin = float(v) # 設(shè)置行邊距
elif k == '-F': laparams.boxes_flow = float(v) # 設(shè)置框流
# 設(shè)置調(diào)試級別
PDFDocument.debug = debug
PDFParser.debug = debug
CMapDB.debug = debug
PDFPageInterpreter.debug = debug
# 創(chuàng)建PDF資源管理器對象
rsrcmgr = PDFResourceManager(caching=caching)
# 根據(jù)輸出類型和選項(xiàng)創(chuàng)建相應(yīng)的PDF設(shè)備對象
if not outtype:
outtype = 'text' # 默認(rèn)為文本輸出
if outfile:
if outfile.endswith('.htm') or outfile.endswith('.html'):
outtype = 'html' # 如果輸出文件名以.htm或.html結(jié)尾,則設(shè)置為html輸出
elif outfile.endswith('.xml'):
outtype = 'xml' # 如果輸出文件名以.xml結(jié)尾,則設(shè)置為xml輸出
elif outfile.endswith('.tag'):
outtype = 'tag' # 如果輸出文件名以.tag結(jié)尾,則設(shè)置為tag輸出
elif outtype == 'tag':
device = TagExtractor(rsrcmgr, outfp) # 如果輸出類型為'tag',則創(chuàng)建TagExtractor對象
else:
return usage() # 如果不識別的輸出類型,則顯示用法并退出
for fname in args: # 遍歷所有輸入文件名
with open(fname, 'rb') as fp: # 以二進(jìn)制讀模式打開文件
interpreter = PDFPageInterpreter(rsrcmgr, device) # 創(chuàng)建PDF頁面解釋器對象
# 遍歷PDF頁面,獲取頁面對象
for page in PDFPage.get_pages(fp, pagenos,
maxpages=maxpages, password=password,
caching=caching, check_extractable=True):
page.rotate = (page.rotate+rotation) % 360 # 設(shè)置頁面旋轉(zhuǎn)角度
interpreter.process_page(page) # 處理每個頁面
device.close() # 關(guān)閉設(shè)備對象,釋放資源
outfp.close() # 關(guān)閉輸出文件,釋放資源
return # 從主函數(shù)返回
# 檢查此模塊是否作為主模塊運(yùn)行
if __name__ == '__main__':
sys.exit(main(sys.argv)) # 如果是,則調(diào)用main函數(shù),并使用命令行參數(shù)列表作為參數(shù)
convertPDF.py
#!/usr/bin/env python3
"""
Script to convert PDFs to text files.
"""
import unicodedata, os, pdf2txt, datetime
import multiprocessing
def convertPDFToText(i, ID, newDir, fileNamePDF):
print('Trying to convert: ' + str(i) + ', ' + ID) # 輸出正在嘗試轉(zhuǎn)換的文件信息
try:
pdf2txt.main(['-o', newDir + '/' + ID + '.txt', fileNamePDF]) # 調(diào)用pdf2txt.main來轉(zhuǎn)換PDF為文本
print('Successfully converted: ' + ID) # 轉(zhuǎn)換成功時的輸出
except Exception as e:
print('Failed to convert: ' + ID + f', Error: {e}') # 轉(zhuǎn)換失敗時的輸出
def process_pdfs(pdf_list):
with multiprocessing.Pool(20) as pool: # 創(chuàng)建一個包含20個進(jìn)程的進(jìn)程池
pool.starmap(convertPDFToText, pdf_list) # 使用starmap來并行處理pdf_list中的每個元素,每個元素都是一個元組,它將被解包為convertPDFToText的參數(shù)
if __name__ == '__main__':
directory = '../../Data/PDF/work'
os.chdir(directory) # 更改當(dāng)前工作目錄至PDF文件目錄
# 指定保存轉(zhuǎn)換后文件的目錄
newDir = '../TXT/work'
# os.makedirs(newDir) # 創(chuàng)建新目錄(如果需要的話)
print('Placing converted files in: ' + newDir) # 輸出轉(zhuǎn)換后文件將被放置的目錄
pdf_list = [] # 創(chuàng)建一個空列表,用于保存將傳遞給convertPDFToText的參數(shù)元組
i = 0 # 初始化計(jì)數(shù)器
for fileNamePDF in os.listdir('./'): # 遍歷當(dāng)前目錄中的所有文件
i += 1 # 計(jì)數(shù)器遞增
if fileNamePDF.find(".pdf") == -1: # 如果文件不是PDF,跳過
continue
ID = fileNamePDF[:-4] # 從文件名中獲取ID(去掉.pdf后綴)
if os.path.isfile('../TXT/' + ID + '.txt'): # 如果已經(jīng)存在對應(yīng)的文本文件,跳過
continue
pdf_list.Append((i, ID, newDir, fileNamePDF)) # 將參數(shù)元組添加到pdf_list中
process_pdfs(pdf_list) # 調(diào)用process_pdfs函數(shù),傳遞pdf_list以并行處理PDF文件