1. 程式人生 > >另類爬蟲:從PDF檔案中爬取表格資料

另類爬蟲:從PDF檔案中爬取表格資料

簡介

  本文將展示一個稍微不一樣點的爬蟲。
  以往我們的爬蟲都是從網路上爬取資料,因為網頁一般用HTML,CSS,JavaScript程式碼寫成,因此,有大量成熟的技術來爬取網頁中的各種資料。這次,我們需要爬取的文件為PDF檔案。本文將展示如何利用Python的camelot模組從PDF檔案中爬取表格資料。
  在我們的日常生活和工作中,PDF檔案無疑是最常用的檔案格式之一,小到教材、課件,大到合同、規劃書,我們都能見到這種檔案格式。但如何從PDF檔案中提取其中的表格,這卻是一個大難題。因為PDF中沒有一個內部的表示方式來表示一個表格。這使得表格資料很難被抽取出來做分析。那麼,我們如何做到從PDF中爬取表格資料呢?
  答案是Python的camelot模組!
  camelot是Python的一個模組,它能夠讓任何人輕鬆地從PDF檔案中提取表格資料。可以使用以下命令安裝camelot模組(安裝時間較長):

pip install camelot-py

camelot模組的官方文件地址為:https://camelot-py.readthedocs.io/en/master/。
  下面將展示如何利用camelot模組從PDF檔案中爬取表格資料。

例1

  首先,讓我們看一個簡單的例子:eg.pdf,整個檔案只有一頁,這一頁中只有一個表格,如下:

eg.pdf

使用以下Python程式碼就可以提取該PDF檔案中的表格:

import camelot

# 從PDF檔案中提取表格
tables = camelot.read_pdf('E://eg.pdf', pages='1', flavor=
'stream') # 表格資訊 print(tables) print(tables[0]) # 表格資料 print(tables[0].data)

輸出結果為:

<TableList n=1>
<Table shape=(4, 4)>
[['ID', '姓名', '城市', '性別'], ['1', 'Alex', 'Shanghai', 'M'], ['2', 'Bob', 'Beijing', 'F'], ['3', 'Cook', 'New York', 'M']]

分析程式碼,camelot.read_pdf()為camelot的從表格中提取資料的函式,輸入的引數為PDF檔案的路徑,頁碼(pages)和表格解析方法(有stream和lattice兩個方法)。對於表格解析方法,預設的方法為lattice,而stream方法預設會把整個PDF頁面當做一個表格來解析,如果需要指定解析頁面中的區域,可以使用table_area這個引數。
  camelot模組的便捷之處還在於它提供了將提取後的表格資料直接轉化為pandas,csv,JSON,html的函式,如tables[0].df,tables[0].to_csv()函式等。我們以輸出csv檔案為例:

import camelot

# 從PDF檔案中提取表格
tables = camelot.read_pdf('E://eg.pdf', pages='1', flavor='stream')

# 將表格資料轉化為csv檔案
tables[0].to_csv('E://eg.csv')

得到的csv檔案如下:

輸出的csv檔案

例2

  在例2中,我們將提取PDF頁面中的某一區域的表格的資料。PDF檔案的頁面(部分)如下:

Statistics-Fundamentals-Succinctly.pdf第53頁

為了提取整個頁面中唯一的表格,我們需要定位表格所在的位置。PDF檔案的座標系統與圖片不一樣,它以左下角的頂點為原點,向右為x軸,向上為y軸,可以通過以下Python程式碼輸出整個頁面的文字的座標情況:

import camelot

# 從PDF中提取表格
tables = camelot.read_pdf('G://Statistics-Fundamentals-Succinctly.pdf', pages='53', \
                          flavor='stream')

# 繪製PDF文件的座標,定位表格所在的位置
tables[0].plot('text')

輸出結果為:

UserWarning: No tables found on page-53 [stream.py:292]

整個程式碼沒有找到表格,這是因為stream方法預設將整個PDF頁面當作表格,因此就沒有找到表格。但是繪製的頁面座標的影象如下:

PDF頁面的座標

仔細對比之前的PDF頁面,我們不難發現,表格對應的區域的左上角座標為(50,620),右下角的座標為(500,540)。我們在read_pdf()函式中加入table_area引數,完整的Python程式碼如下:

import camelot

# 識別指定區域中的表格資料
tables = camelot.read_pdf('G://Statistics-Fundamentals-Succinctly.pdf', pages='53', \
                          flavor='stream', table_area=['50,620,500,540'])

# 繪製PDF文件的座標,定位表格所在的位置
table_df = tables[0].df

print(type(table_df))
print(table_df.head(n=6))

輸出的結果為:

<class 'pandas.core.frame.DataFrame'>
         0               1                2           3
0  Student  Pre-test score  Post-test score  Difference
1        1              70               73           3
2        2              64               65           1
3        3              69               63          -6
4        …               …                …           …
5       34              82               88           6

總結

  在具體識別PDF頁面中的表格時,除了指定區域這個引數,還有上下標、單元格合併等引數,詳細地使用方法可參考camelot官方文件網址:https://camelot-py.readthedocs.io/en/master/user/advanced.html。

注意:本人現已開通微信公眾號: Python爬蟲與演算法(微訊號為:easy_web_scrape), 歡迎大家關注哦~~

參考文獻

  1. camelot模組的官方文件:https://camelot-py.readthedocs.io/en/master/
  2. Camelot:一個從pdf抽取表格資料的Python庫:https://blog.csdn.net/qq_40925239/article/details/83153599