如何用Python批量提取PDF文本內(nèi)容芳杏?

本文為你展示爵赵,如何用Python把許多PDF文件的文本內(nèi)容批量提取出來泊脐,并且整理存儲到數(shù)據(jù)框中晨抡,以便于后續(xù)的數(shù)據(jù)分析则剃。

問題

最近棍现,讀者們在后臺的留言己肮,愈發(fā)五花八門了。

寫了幾篇關于自然語言處理的文章后娄柳,一種呼聲漸強:

老師赤拒,pdf中的文本內(nèi)容,有沒有什么方便的方法提取出來呢这敬?

我能體會到讀者的心情崔涂。

我展示的例子中冷蚂,文本數(shù)據(jù)都是直接可以讀入數(shù)據(jù)框工具做處理的觅闽。它們可能來自開放數(shù)據(jù)集合蛉拙、網(wǎng)站API,或者爬蟲吮廉。

但是宦芦,有的時候调卑,你會遇到需要處理指定格式數(shù)據(jù)的問題大咱。

例如pdf碴巾。

許多的學術論文厦瓢、研究報告,甚至是資料分享劳跃,都采用這種格式發(fā)布刨仑。

這時候贸人,已經(jīng)掌握了諸多自然語言分析工具的你,會頗有“拔劍四顧心茫然”的感覺——明明知道如何處理其中的文本信息倘要,但就是隔著一個格式轉(zhuǎn)換的問題封拧,做不來泽西。

怎么辦缰趋?

辦法自然是有的秘血,例如專用工具灰粮、在線轉(zhuǎn)換服務網(wǎng)站,甚至還可以手動復制粘貼嘛熔脂。

但是霞揉,咱們是看重效率的零聚,對不對些侍?

上述辦法岗宣,有的需要在網(wǎng)上傳輸大量內(nèi)容耗式,花費時間較多刊咳,而且可能帶來安全和隱私問題;有的需要專門花錢購買余指;有的干脆就不現(xiàn)實酵镜。

怎么辦淮韭?

好消息是贴届,Python就可以幫助你高效毫蚓、快速地批量提取pdf文本內(nèi)容绍些,而且和數(shù)據(jù)整理分析工具無縫銜接柬批,為你后續(xù)的分析處理做好基礎服務工作。

本文給你詳細展示這一過程嗅虏。

想不想試試皮服?

數(shù)據(jù)

為了更好地說明流程龄广,我為你準備好了一個壓縮包择同。

里面包括本教程的代碼敲才,以及我們要用到的數(shù)據(jù)。

請你到 這個網(wǎng)址 下載本教程配套的壓縮包剃氧。

下載后解壓她我,你會在生成的目錄(下稱“演示目錄”)里面看到以下內(nèi)容番舆。

演示目錄里面包含:

  • Pipfile: pipenv 配置文件恨狈,用來準備咱們變成需要用到的依賴包禾怠。后文會講解使用方法吗氏;
  • pdf_extractor.py: 利用pdfminer.six編寫的輔助函數(shù)弦讽。有了它你就可以直接調(diào)用pdfminer提供的pdf文本內(nèi)容抽取功能往产,而不必考慮一大堆惱人的參數(shù)某宪;
  • demo.ipynb: 已經(jīng)為你寫好的本教程 Python 源代碼 (Jupyter Notebook格式)兴喂。

另外衣迷,演示目錄中還包括了2個文件夾蘑险。

這兩個文件夾里面佃迄,都是中文pdf文件呵俏,用來給你展示pdf內(nèi)容抽取。它們都是我?guī)啄昵鞍l(fā)表的中文核心期刊論文吼肥。

這里做2點說明:

  1. 使用我自己的論文做示例缀皱,是因為我怕用別人的論文做文本抽取啤斗,會與論文作者及數(shù)據(jù)庫運營商之間有知識產(chǎn)權的糾紛钮莲;
  2. 分成2個文件夾崔拥,是為了向你展示添加新的pdf文件時链瓦,抽取工具會如何處理澡绩。

pdf文件夾內(nèi)容如下:

newpdf文件夾內(nèi)容如下:

數(shù)據(jù)準備好了肥卡,下面我們來部署代碼運行環(huán)境步鉴。

環(huán)境

要安裝Python氛琢,比較省事的辦法是裝Anaconda套裝阳似。

請到 這個網(wǎng)址 下載Anaconda的最新版本撮奏。

請選擇左側(cè)的 Python 3.6 版本下載安裝泽疆。

如果你需要具體的步驟指導玲献,或者想知道Windows平臺如何安裝并運行Anaconda命令捌年,請參考我為你準備的 視頻教程 礼预。

安裝好Anaconda之后逆瑞,打開終端获高,用cd命令進入演示目錄念秧。

如果你不了解具體使用方法摊趾,也可以參考 視頻教程 砾层。

我們需要安裝一些環(huán)境依賴包肛炮。

首先執(zhí)行:

pip install pipenv

這里安裝的侨糟,是一個優(yōu)秀的 Python 軟件包管理工具 pipenv 秕重。
安裝后,請執(zhí)行:

pipenv install --skip-lock

pipenv 工具會依照Pipfile服鹅,自動為我們安裝所需要的全部依賴軟件包菱魔。

終端里面會有進度條,提示所需安裝軟件數(shù)量和實際進度杰妓。

裝好后巷挥,根據(jù)提示我們執(zhí)行:

pipenv shell

這樣倍宾,我們就進入本教程專屬的虛擬運行環(huán)境了高职。

注意一定要執(zhí)行下面這句:

python -m ipykernel install --user --name=py36

只有這樣怔锌,當前的Python環(huán)境才會作為核心(kernel)在系統(tǒng)中注冊埃元,并且命名為py36岛杀。

此處請確認你的電腦上已經(jīng)安裝了 Google Chrome 瀏覽器楞件。

我們執(zhí)行:

jupyter notebook

默認瀏覽器(Google Chrome)會開啟土浸,并啟動 Jupyter 筆記本界面:

你可以直接點擊文件列表中的第一項ipynb文件黄伊,可以看到本教程的全部示例代碼墓阀。

你可以一邊看教程的講解斯撮,一邊依次執(zhí)行這些代碼勿锅。

但是,我建議的方法枣氧,是回到主界面下溢十,新建一個新的空白 Python 3 筆記本(顯示名稱為 py36 的那個)。

請跟著教程达吞,一個個字符輸入相應的內(nèi)容张弛。這可以幫助你更為深刻地理解代碼的含義,更高效地把技能內(nèi)化酪劫。

當你在編寫代碼中遇到困難的時候,可以返回參照 demo.ipynb 文件覆糟。

準備工作結(jié)束刻剥,下面我們開始正式輸入代碼。

代碼

首先搪桂,我們讀入一些模塊透敌,以進行文件操作。

import glob
import os

前文提到過踢械,演示目錄下酗电,有兩個文件夾,分別是pdf和newpdf内列。

我們指定 pdf 文件所在路徑為其中的pdf文件夾撵术。

pdf_path = "pdf/"

我們希望獲得所有 pdf 文件的路徑。用glob话瞧,一條命令就能完成這個功能嫩与。

pdfs = glob.glob("{}/*.pdf".format(pdf_path))

看看我們獲得的 pdf 文件路徑是否正確。

pdfs
['pdf/復雜系統(tǒng)仿真的微博客虛假信息擴散模型研究.pdf',
 'pdf/面向影子分析的社交媒體競爭情報搜集.pdf',
 'pdf/面向人機協(xié)同的移動互聯(lián)網(wǎng)政務門戶探析.pdf']

經(jīng)驗證交排。準確無誤划滋。

下面我們利用 pdfminer 來從 pdf 文件中抽取內(nèi)容。我們需要從輔助 Python 文件 pdf_extractor.py 中讀入函數(shù) extract_pdf_content埃篓。

from pdf_extractor import extract_pdf_content

用這個函數(shù)处坪,我們嘗試從 pdf 文件列表中的第一篇里,抽取內(nèi)容,并且把文本保存在 content 變量里同窘。

content = extract_pdf_content(pdfs[0])

我們看看 content 里都有什么:

content

顯然玄帕,內(nèi)容抽取并不完美,頁眉頁腳等信息都混了進來想邦。

不過裤纹,對于我們的許多文本分析用途來說,這無關緊要丧没。

你會看到 content 的內(nèi)容里面有許多的 \n鹰椒,這是什么呢?

我們用 print 函數(shù)骂铁,來顯示 content 的內(nèi)容吹零。

print(content)

可以清楚看到罩抗,那些 \n 是換行符拉庵。

通過一個 pdf 文件的抽取測試,我們建立了信心套蒂。

下面钞支,我們該建立辭典,批量抽取和存儲內(nèi)容了操刀。

mydict = {}

我們遍歷 pdfs 列表烁挟,把文件名稱(不包含目錄)作為鍵值。這樣骨坑,我們可以很容易看到撼嗓,哪些pdf文件已經(jīng)被抽取過了,哪些還沒有抽取欢唾。

為了讓這個過程更為清晰且警,我們讓Python輸出正在抽取的 pdf 文件名。

for pdf in pdfs:
    key = pdf.split('/')[-1]
    if not key in mydict:
        print("Extracting content from {} ...".format(pdf))
        mydict[key] = extract_pdf_content(pdf)

抽取過程中礁遣,你會看到這些輸出信息:

Extracting content from pdf/復雜系統(tǒng)仿真的微博客虛假信息擴散模型研究.pdf ...
Extracting content from pdf/面向影子分析的社交媒體競爭情報搜集.pdf ...
Extracting content from pdf/面向人機協(xié)同的移動互聯(lián)網(wǎng)政務門戶探析.pdf ...

看看此時字典中的鍵值都有哪些:

mydict.keys()
dict_keys(['復雜系統(tǒng)仿真的微博客虛假信息擴散模型研究.pdf', '面向影子分析的社交媒體競爭情報搜集.pdf', '面向人機協(xié)同的移動互聯(lián)網(wǎng)政務門戶探析.pdf'])

一切正常斑芜。

下面我們調(diào)用pandas,把字典變成數(shù)據(jù)框祟霍,以利于分析杏头。

import pandas as pd

下面這條語句,就可以把字典轉(zhuǎn)換成數(shù)據(jù)框了沸呐。注意后面的reset_index()把原先字典鍵值生成的索引也轉(zhuǎn)換成了普通的列醇王。

df = pd.DataFrame.from_dict(mydict, orient='index').reset_index()

然后我們重新命名列,以便于后續(xù)使用崭添。

df.columns = ["path", "content"]

此時的數(shù)據(jù)框內(nèi)容如下:

df

可以看到寓娩,我們的數(shù)據(jù)框擁有了pdf文件信息和全部文本內(nèi)容。這樣你就可以使用關鍵詞抽取、情感分析根暑、相似度計算等等諸多分析工具了力试。

篇幅所限,我們這里只用一個字符數(shù)量統(tǒng)計的例子來展示基本分析功能排嫌。

我們讓 Python 幫我們統(tǒng)計抽取內(nèi)容的長度畸裳。

df["length"] = df.content.apply(lambda x: len(x))

此時的數(shù)據(jù)框內(nèi)容發(fā)生以下變化:

df

多出的一列,就是 pdf 文本內(nèi)容的字符數(shù)量淳地。

為了在 Jupyter Notebook 里面正確展示繪圖結(jié)果怖糊,我們需要使用以下語句:

%matplotlib inline

下面,我們讓 Pandas 把字符長度一列的信息用柱狀圖標示出來颇象。為了顯示的美觀伍伤,我們設置了圖片的長寬比例,并且把對應的pdf文件名稱以傾斜45度來展示遣钳。

import matplotlib.pyplot as plt
plt.figure(figsize=(14, 6))
df.set_index('path').length.plot(kind='bar')
plt.xticks(rotation=45)

可視化分析完成扰魂。

下面我們把剛才的分析流程整理成函數(shù),以便于將來更方便地調(diào)用蕴茴。

我們先整合pdf內(nèi)容提取到字典的模塊:

def get_mydict_from_pdf_path(mydict, pdf_path):
    pdfs = glob.glob("{}/*.pdf".format(pdf_path))
    for pdf in pdfs:
        key = pdf.split('/')[-1]
        if not key in mydict:
            print("Extracting content from {} ...".format(pdf))
            mydict[key] = extract_pdf_content(pdf)
    return mydict

這里輸入是已有詞典和pdf文件夾路徑劝评。輸出為新的詞典。

你可能會納悶為何還要輸入“已有詞典”倦淀。別著急蒋畜,一會兒我用實際例子展示給你看。

下面這個函數(shù)非常直白——就是把詞典轉(zhuǎn)換成數(shù)據(jù)框撞叽。

def make_df_from_mydict(mydict):
    df = pd.DataFrame.from_dict(mydict, orient='index').reset_index()
    df.columns = ["path", "content"]
    return df

最后一個函數(shù)姻成,用于繪制統(tǒng)計出來的字符數(shù)量。

def draw_df(df):
    df["length"] = df.content.apply(lambda x: len(x))
    plt.figure(figsize=(14, 6))
    df.set_index('path').length.plot(kind='bar')
    plt.xticks(rotation=45)

函數(shù)已經(jīng)編好愿棋,下面我們來嘗試一下科展。

還記得演示目錄下有個子目錄,叫做newpdf對吧初斑?

我們把其中的2個pdf文件辛润,移動到pdf目錄下面。

這樣pdf目錄下面见秤,就有了5個文件:

我們執(zhí)行新整理出的3個函數(shù)砂竖。

首先輸入已有的詞典(注意此時里面已有3條記錄),pdf文件夾路徑?jīng)]變化鹃答。輸出是新的詞典乎澄。

mydict = get_mydict_from_pdf_path(mydict, pdf_path)
Extracting content from pdf/微博客 Twitter 的企業(yè)競爭情報搜集.pdf ...
Extracting content from pdf/移動社交媒體用戶隱私保護對策研究.pdf ...

注意這里的提示,原先的3個pdf文件沒有被再次抽取测摔,只有2個新pdf文件被抽取置济。

咱們這里一共只有5個文件解恰,所以你直觀上可能無法感受出顯著的區(qū)別。

但是浙于,假設你原先已經(jīng)用幾個小時护盈,抽取了成百上千個pdf文件信息,結(jié)果你的老板又丟給你3個新的pdf文件……

如果你必須從頭抽取信息羞酗,恐怕會很崩潰吧腐宋。

這時候,使用咱們的函數(shù)檀轨,你可以在1分鐘之內(nèi)把新的文件內(nèi)容追加進去胸竞。

這差別,不小吧参萄?

下面我們用新的詞典卫枝,構建數(shù)據(jù)框。

df = make_df_from_mydict(mydict)

我們繪制新的數(shù)據(jù)框里讹挎,pdf抽取文本字符數(shù)量校赤。結(jié)果如下:

draw_df(df)

至此,代碼展示完畢淤袜。

小結(jié)

總結(jié)一下痒谴,本文為你介紹了以下知識點:

  • 如何用glob批量讀取目錄下指定格式的文件路徑衰伯;
  • 如何用pdfminer從pdf文件中抽取文本信息铡羡;
  • 如何構建詞典,存儲與鍵值(本文中為文件名)對應的內(nèi)容意鲸,并且避免重復處理數(shù)據(jù)烦周;
  • 如何將詞典數(shù)據(jù)結(jié)構輕松轉(zhuǎn)換為Pandas數(shù)據(jù)框,以便于后續(xù)數(shù)據(jù)分析怎顾。
  • 如何用matplotlib和pandas自帶的繪圖函數(shù)輕松繪制柱狀統(tǒng)計圖形读慎。

討論

你之前做的數(shù)據(jù)分析工作中,遇到過需要從pdf文件抽取文本的任務嗎槐雾?你是如何處理的夭委?有沒有更好的工具與方法癌压?歡迎留言辅髓,把你的經(jīng)驗和思考分享給大家,我們一起交流討論拉鹃。

喜歡請點贊擎值。還可以微信關注和置頂我的公眾號“玉樹芝蘭”(nkwangshuyi)慌烧。

如果你對數(shù)據(jù)科學感興趣,不妨閱讀我的系列教程索引貼《如何高效入門數(shù)據(jù)科學鸠儿?》屹蚊,里面還有更多的有趣問題及解法厕氨。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市汹粤,隨后出現(xiàn)的幾起案子命斧,更是在濱河造成了極大的恐慌,老刑警劉巖嘱兼,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件冯丙,死亡現(xiàn)場離奇詭異,居然都是意外死亡遭京,警方通過查閱死者的電腦和手機胃惜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來哪雕,“玉大人船殉,你說我怎么就攤上這事∷购浚” “怎么了利虫?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長堡僻。 經(jīng)常有香客問我糠惫,道長,這世上最難降的妖魔是什么钉疫? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任硼讽,我火速辦了婚禮,結(jié)果婚禮上牲阁,老公的妹妹穿的比我還像新娘固阁。我一直安慰自己,他們只是感情好城菊,可當我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布备燃。 她就那樣靜靜地躺著,像睡著了一般凌唬。 火紅的嫁衣襯著肌膚如雪并齐。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天客税,我揣著相機與錄音况褪,去河邊找鬼。 笑死霎挟,一個胖子當著我的面吹牛窝剖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播酥夭,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼赐纱,長吁一口氣:“原來是場噩夢啊……” “哼脊奋!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起疙描,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤诚隙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后起胰,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體久又,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年效五,在試婚紗的時候發(fā)現(xiàn)自己被綠了地消。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡畏妖,死狀恐怖脉执,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情戒劫,我是刑警寧澤半夷,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站迅细,受9級特大地震影響巫橄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜茵典,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一湘换、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧敬尺,春花似錦枚尼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽崎溃。三九已至蜻直,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間袁串,已是汗流浹背概而。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留囱修,地道東北人赎瑰。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像破镰,于是被迫代替她去往敵國和親餐曼。 傳聞我的和親對象是個殘疾皇子压储,可洞房花燭夜當晚...
    茶點故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內(nèi)容