首先不需要關心HTML格式文件具體是什么內容(電子病歷還是其他網頁啥的),這篇主要內容是介紹如何用Python批量處理HTML格式文件、TXT格式文件,以及Python字典列表導出到EXCEL的一種解決方法。
我的原始數據是200+條HTML格式的入院記錄
如上圖所示,我關心的內容都在這些P標簽里面
首先用BeautifulSoup包來處理HTML內容,提取到TXT文件如圖所示
from bs4 import BeautifulSoup import re #創建BeautifulSoup對象 bs=BeautifulSoup(open('D:/rxa/1.html'),features='lxml') #獲取所有文字內容 #print(soup.get_text()) #獲取所有p標簽的文字內容,寫入TXT文件 for item in bs.find_all("p"): ptxt=re.sub('\s', ' ', item.get_text()) with open('d:/testvs/cutwords/test2.txt', 'a',encoding='utf-8') as f: f.write(ptxt+'\n')
觀察發現,這些屬性都是由“:”分隔的,可以作為切分的依據。我想到在C#里面,我會定義一個類,比如“病人類”,然后“年齡、入院日期、婚否......”這些都可以作為類的屬性傳入,然后每次實例化一個病人對象就把這些保存下來,通過“.”訪問,Python里面不用這么麻煩,因為Python自己就有字典這樣一個高級的數據結構,這種鍵值對的形式不恰好適合存放這種數據么。於是我想到將這些先存入字典以冒號切分,前面作為“key”,后面作為“value”。
#重要字段存入字典 dic={} k=[] f=False for item in bs.find_all("p"): ptxt=re.sub('\s', ' ', item.get_text()) if f: dic['體格檢查']=ptxt k.append('體格檢查') f=False if re.search(':',ptxt): v=ptxt.split(':') dic[v[0]] = v[1] k.append(v[0]) if re.search(':',ptxt): if re.search('體溫',ptxt): s=ptxt.split(',') v=s[0].split(':') dic[v[0]] = v[1] k.append(v[0]) v=s[1].split(':') dic[v[0]] = v[1] k.append(v[0]) v=s[2].split(':') dic[v[0]] = v[1] k.append(v[0]) v=s[3].split(':') dic[v[0]] = v[1] k.append(v[0]) f=True else: v=ptxt.split(':') dic[v[0]] = v[1] k.append(v[0])
為什么寫得這么麻煩,還有這么多判斷分支,因為我這個數據不太規范,既有中文冒號,又有英文冒號,而且正則表達式re.search是不是只能匹配第一個來着,體溫那一行就不好處理,還有其他的一些問題,要結合自己數據情況分析。至於這里有個變量f,我要解釋一下,在for循環遍歷時,我不知道怎么取當前item的下一個item,沒有指針,沒有next(怪我自己學藝不精)迭代器???反正不會寫,於是我想到了以前學C語言,有一個flag標志位,來調整程序跳轉啥的,還自以為是臭不要臉覺得自己有點點機智哈哈。
以上都是單個文件的處理,下面介紹文件夾文件批量處理
我覺得計算機批量處理才是它被發明的義意啊,對於這種重復的工作,比人工做得又快又好,還不會煩躁亂發脾氣
import os.path import re def eachFile(filepath): pathDir = os.listdir(filepath) #獲取當前路徑下的文件名,返回List temp=1 for s in pathDir: newDir=os.path.join(filepath,s) #將文件命加入到當前文件路徑后面 if os.path.isfile(newDir) : #如果是文件 if os.path.splitext(newDir)[1]==".html": #判斷是否是html bs=BeautifulSoup(open(newDir),features='lxml') #獲取所有p標簽的文字內容 for item in bs.find_all("p"): ptxt=re.sub('\s', ' ', item.get_text()) savepath = os.path.join("D:\\t",str(temp)) with open(savepath+'.txt', 'a',encoding='utf-8') as f: f.write(ptxt+'\n') temp+=1 else: eachFile(filepath) #如果不是文件,遞歸這個文件夾的路徑 rootdir = 'D:\\rxadata' eachFile(rootdir) print('提取完成')
也就是會多一層循環,這里一定要注意路徑問題,我開始就是犯了點錯,9000+條TXT文件都鋪到了D盤,差點當場去世。。。
提取的字典,存入一個列表,然后借助xlwt包來導入到excel里面,下面是完整代碼(能用,但是寫得灰常爛我自己知道)
import re import os.path import xlwt import pandas as pd def eachFile(filepath): Info=[] pathDir = os.listdir(filepath) #獲取當前路徑下的文件名,返回List for s in pathDir: newDir=os.path.join(filepath,s) #將文件命加入到當前文件路徑后面 if os.path.isfile(newDir) : if os.path.splitext(newDir)[1]==".txt": dic={} k=[] f=open(newDir,'r',encoding='utf-8') for s in f.readlines(): s=s.strip() if re.search(':',s): v=s.split(':') if v[0]!='體溫': dic[v[0]] = v[1] k.append(v[0]) else: dic['TPRBP']=s elif re.search(':',s): v=s.split(':') dic[v[0]] = v[1] k.append(v[0]) elif re.search('T',s): dic['TPRBP']=s f.close() if dic.get('出院診斷')==None: dic['出院診斷']='' if dic.get('確診日期')==None: dic['確診日期']='' if dic.get('輔 助 檢 查')==None: dic['輔 助 檢 查']='' Info.append(dic) else: break return Info def export_excel(export): #將字典列表轉換為DataFrame pf = pd.DataFrame(list(export)) #指定生成的Excel表格名稱 file_path = pd.ExcelWriter('D:\\info.xlsx') #替換空單元格 pf.fillna(' ',inplace = True) #輸出 pf.to_excel(file_path,encoding = 'utf-8',index = False) #保存表格 file_path.save() rootdir = 'D:\\t' IF=eachFile(rootdir) export_excel(IF) print('完成')
提取完成了,我還發現在我這兩百多份乳腺癌病歷里竟然有一位男患者。。。可惜沒有他的首次住院病歷,我還挺好奇男患者“月經婚育史”要怎么描述的。(PS:電子病歷是敏感的隱私數據,放截圖恐怕不妥,不過這里都故意隱藏了病人個人信息及醫院信息,只是分享知識用的,應該不違法吧)