任務:將一個一千多頁的pdf中的表格數據提取出來,拼接成html表格,以便在富文本中更好查看
pdf中的表格如圖所示
步驟
1.其中有些表格是跨頁的(即同一張表格不在同一個頁面),像上面的第一個表格就是屬於跨列,如果不做判斷,獲取到的原屬於同一個表格的就會分開了,所以要把屬於同一個表格的拼接起來。
2.所有表頭都是相同的,所以處理時候遇到表頭就把上個表格內容存進數據庫。
3.因為我們想要的表格是從30頁開始,最后一頁結束,所以這兩頁要特殊處理。
4.還有個需求,把表格第二列"搜素打開菜單"中的內容提取出來存進數據庫的另一個字段,如:搜索打開菜單:【有價卡換卡】中的有價卡換卡。
代碼
代碼如下:
因為我有django項目,為了方便點,所以我直接就在項目里寫一個路由(部分代碼省略)用orm操作數據庫,也可以自己修改成用原生操作數據庫的方法存進數據庫。
#將pdf中的測試步驟表格數據提取出來存進數據庫 import pdfplumber, time from .models import ScenarioInfo #這里是引入模型中的ScenarioInfo表 with pdfplumber.open(r'C:\Users\hisoft\Desktop\(2019-09-25)_21460.pdf') as pdf: m = 0 # 測試步驟表格的數量(按表頭數算) s = '<table><tbody>' mjcd = '' # 末級菜單 for i in range(29, len(pdf.pages)): # 從第30頁開始獲取表格數據 page = pdf.pages[i] # 設置操作頁面 n = 1 # 當前頁的第n個表格 for table in page.extract_tables(): k = True for row in range(len(table)): if str(table[ row]) == r"['Step', '案例步驟', '預期結果', '測試信息', '耗時(秒\n)', '結果']": # 這是根據表格行內容判斷是否是一個新的表格開頭,因為表頭內容都是固定的 if i == 29 and n == 1: # 判斷是否是第30頁的第一個表格 pass else: s += '</tbody></table>' print('i=', i) # print('s=', s) # print('mjcd=', mjcd) m += 1 ScenarioInfo.objects.create(test_steps=s, lrry='哈哈哈', mjcd=mjcd) #存進數據庫,s是拼接好的表格字符串,富文本會識別表格標簽顯示 time.sleep(0.6) mjcd = '' s = '<table><tbody>' for j in range(len(table[row])): if j == 0: # 判斷是否是當前行的第一列 s += '<tr><td>' s += table[row][j] if j == 1: # 判斷是否是當前行的第二列,將末級菜單取出來,若碰到有多個末級菜單的只取第一個 if k: if len(table[row][j].split('搜索打開菜單:【')) > 1: mjcd = table[row][j].split('搜索打開菜單:【')[1].split('】')[0] k = False if j == len(table[row]) - 1: # 判斷是否是當前行的最后一列 s += '</td></tr>' else: s += '</td><td>' if i == len(pdf.pages) - 1: # 判斷是否是最后一頁 if n == len(page.extract_tables()): # 判斷是否是最后一個表格 for row in range(len(table)): if row == len(table) - 1: # 判斷是否是當前表格的最后一行 for j in range(len(table[row])): if j == len(table[row]) - 1: # 判斷是否是當前行的最后一列 s += '</tbody></table>' print('i=', i) print('end_s=:', s) m += 1 print('m=', m) print('mjcd=', mjcd) ScenarioInfo.objects.create(test_steps=s, lrry='哈哈哈', mjcd=mjcd) #存進數據庫 n += 1