當前位置:編程學習大全網 - 編程語言 - 如何用 Python 和正則表達式抽取文本結構化信息?

如何用 Python 和正則表達式抽取文本結構化信息?

痛點

很多人的日常工作,都是要和大量的文本打交道的。

例如學者需要閱讀大量的文獻材料,從中找到靈感、數據與論據。

學生需要閱讀很多教科書和論文,然後寫自己的報告或者做幻燈。

財經分析師,需要從大量的新聞報道中,找到行業的發展趨勢和目標企業動態的蛛絲馬跡。

不是所有的文本處理,都那麽新鮮而有趣。

有壹項重要但繁瑣的工作,就是從大量的文本當中抽取結構化的信息。

許多數據分析的場景,都要求輸入結構化的信息。

例如在咱們之前介紹過的《貸還是不貸:如何用 Python 和機器學習幫妳決策?》和《如何用 Python 和深度神經網絡鎖定即將流失的客戶?》中,妳都看到了,機器模型更喜歡被結構化的表格信息來餵養。

然而,結構化的信息,不壹定就在那裏,靜候妳來使用。很多時候,它蘊藏在以往生成的非結構化文本中。

妳可能早已習慣,人工閱讀文本信息,把關鍵點摘取出來,然後把它們拷貝粘貼放到壹個表格中。從原理上講,這樣做無可厚非。但是實際操作裏面,效率太低,而且太麻煩。

大部分人,是不願意從事這種簡單重復的枯燥工作的。

壹遍遍機械重復鼠標劃定文本範圍,“Ctrl+C”、切換到表格文檔、找準輸入位置,再 “Ctrl+V”……

這種事兒做得太多,對妳的肩肘關節,甚至是身心健康,都有可能造成不利影響。

想不想嘗試用壹種更簡單的自動化方式,替妳快速完成這些煩人的操作步驟呢??

讀過本文後,希望妳能找到答案。

樣例

這裏,我們舉壹個極端簡化的中文文本抽取信息例子。

之所以這樣做,是為了避免妳在解讀數據上花費太多時間。

我更希望,妳能夠聚焦於方法,從而掌握新知。

假設壹個高中班主任,高考後讓班長統計壹下學生們的畢業去向。班長很認真地進行了調查,然後做了如下匯報:

張華考上了北京大學

李萍進了中等技術學校

韓梅梅進了百貨公司

……

為了讓妳對樣例足夠熟悉,甚至有***鳴,這裏我從 1998 年版的新華字典中,“借鑒” 了部分內容。

夠貼心吧?

現實生活中,壹個班大概不會只有 3 個人,因此妳可以想象這是壹個長長的句子列表。

但其實班主任有個隱含的意思沒有表達出來,即:

我想要壹張表格!

所以,看到這壹長串的句子,妳可以想象他的表情。

班長估計也很難堪:

想要表格妳早說啊!

這時候,假設妳是班長,怎麽辦?

信息都在文本裏面。但如果需要轉換成表格,就得壹個個信息點去尋找和處理。

其實,對於四五十人的班級來說,手動操作也不是什麽太難的事情。

但是設想壹下,如果妳需要處理的數據量,是這個例子的十倍、百倍甚至千萬倍呢?

繼續堅持手動處理?

這不僅麻煩,而且不現實。

我們需要找到壹種簡單的方法,幫助我們自動抽取相應的信息。

此處我們使用的方法,是正則表達式

正則

“正則表達式” 這個名字,初聽起來好像很玄妙。實際上,它是從英文 “regular expression” 翻譯過來的。

如果譯成白話,那就是 “有規律的表述形式”。

這,聽起來,是不是就更加接地氣了?

但是,給妳補壹下 “假行家 101” 課程:

說別人聽得懂的話,妳能唬得住誰?

約定俗成,咱們繼續沿用 “正則表達式”,來稱呼它好了。

從創生之日起,它就給文本處理帶來了高效率。

但是,用它的主要人群,卻不是時常跟文字打交道的作家、編輯、學者、文員,而是……

程序員!

程序員寫的代碼,是文本;程序員處理的數據,很多也是文本格式。其中便有很多顯著的規律可循。

正是靠著正則表達式這種獨門秘籍,許多別人做起來,需要昏天黑地壹整周的任務,程序員可以半小時搞定,然後喝著咖啡等下班。

即便到了泛人工智能的今天,正則表達式依然有許多令妳意想不到的應用。

例如人機對話系統。

妳可能看了新聞報道,總以為人機對話都是靠著知識圖譜或者深度學習搞出來的。

不能說這裏面,沒有上述炫酷技術的參與。但它們充其量,只占其中壹部分,或許還只是壹小部分。

生產實踐裏面,大量的對話規則後面,並不是讓妳倍感神奇深奧的神經網絡,而是壹堆正則表達式。

妳可能會擔心,這樣高端的應用技術,自己能掌握嗎?

答案是:

當然!

正則表達式,並不難學。

尤其是當妳把它和 Python 結合到壹起,那簡直就是效率神器了。

我們這就來看看,正則表達式怎麽幫我們識別出樣例文本裏面 “人名” 和 “去向” 信息。

試練

請妳開啟壹個瀏覽器,鍵入這個網址(/)。

妳會看見如下界面。

它可是壹個正則表達式實驗的利器。我教 INFO 5731 課程時,學生們就是在掌握了這個工具以後,迅速玩兒轉了正則表達式。

這麽好的工具,壹定要價不菲吧?

不,它是免費的。妳放心大膽使用就好了。

我們首先把左側的編程語言,從默認的 PHP ,調整為 Python。

之後,把需要進行處理的文本,貼到中間空白的大文本框裏面。

下面我們來嘗試進行 “匹配”。

什麽叫做匹配呢?

就是妳寫壹個表達式,電腦便拿著雞毛當令箭,在每壹行文本上,都認認真真地找有沒有符合該表達式的文本段落。

如有,則會高亮顯示出來。

這裏我們觀察壹下,發現每個句子裏面,人員去向前面,都有壹個 “了” 字。

好,我們就在中部上方小文本框裏,把 “了” 字輸入進去。

可以看到,三句話裏面的 “了”,全都亮了

這就是妳接觸到的第壹種匹配方式 —— 按照字符原本的意思來查找壹致的內容。

因為樣例文本的規律性,我們可以把 “了” 當成壹個定位符,它後面,到句子結束位置,是 “去向” 信息。

咱們需要找的壹半結構化信息,不就是這個 “去向” 嗎?

我們嘗試匹配 “去向”。

怎麽匹配呢?這次每壹行的字兒都不壹樣啊?

沒關系,正則表達式強大之處,此時就顯示出來了。

妳可以用壹個點號,也就是.,表示任意字符。

字母、數字、標點…… 甚至是中文,也能涵蓋在內。

然後我們繼續想想看,去向信息這裏,會有幾個字呢?

不好說。

例子裏面這簡單的三句話,就有 “4 個字” 或者 “6 個字” 兩種情況。

所以,我們無法指定去向信息裏面字符的長度。

但這也沒關系,我們只需要用壹個星號(*),就可以代表出現次數,從?0 到無窮大都可以匹配。

當然,實際情況中,是不會真出現無窮大的。

我們在剛才輸入的基礎上,加上.*,結果就成了這個樣子:

不錯嘛!

不過似乎去向信息和 “了” 字兒都是壹樣顏色的高亮。那不就混到了壹起嗎?

我們可不想這樣。

怎麽辦?

請妳在.*?的兩側,嘗試加入壹對小括號(註意,不要用中文全角符號)試試看。

妳會發現,這次 “了” 依然用藍色表示,而後面的去向信息,已經變成了綠色。

這壹對小括號,很重要,它叫做 “分組”,是提取信息的基本單位。

我們的任務已經解決了壹半了,是吧?

下面我們來嘗試把人名壹並抽取出來。

我們來找人名的錨定位置。

細細觀察,妳不難發現,每個人名的後面,都有個動詞跟著。

升學的同學,用的是 “考” 字,而就業的同學,用的是 “進” 字。

我們先嘗試壹下 “考” 字。

這裏我們嘗試直接把 “考” 字放在 “了” 字以前。但是妳會發現,什麽匹配結果也沒有。

為什麽?

回看數據,妳會發現,人家用的原詞是 “考上了”。

當然這裏我們可以輸入 “上” 字。不過妳要考慮壹下更為通用的情況。

好比說,“考取了” 怎麽辦?“考入了” 呢?

更好的方式,是繼續使用我們剛才學會的 “大招”,在 “考” 和 “了” 之間,插入壹個.*。

這時候,妳的正則表達式的樣子是?考.*了(.*)

看,第壹行的信息成功匹配了吧?

但是,那後面還有兩行沒有匹配,怎麽辦?

我們依樣畫葫蘆,就會發現,使用進.*了(.*)?就能正確匹配後兩行。

問題來了:

匹配第壹行的,匹配不了後兩行,反之亦然。

這不好。我們希望寫的表達式,能夠更通用

怎麽辦?

我們看看正則表達式當中 “或” 關系的表示。

這裏,我們可以把兩個字符用豎線隔開,旁邊用中括號括起來,代表兩者任壹出現,都算匹配成功。

也就是,把正則表達式,寫成這樣:[考|進].*了(.*)

太棒了,三行的內容都已經匹配成功。

這裏,動詞詞組,和代表時態的 “了” 作為中間錨定信息,我們可以放心大膽,把之前的人名信息,提取出來了。

也就是這樣寫:(.*)[考|進].*了(.*)

註意此時,人名分組是綠色,去向分組是紅色的。

我們成功提取了兩組信息!慶祝壹下!

可是,如果妳給班主任看這裏的結果,估計他不會滿意。

表格,我要表格!

別著急,該 Python 出場了。

下面我們嘗試在 Python 把數據正式提取出來。

環境

本文的配套源代碼,我放在了 Github 上。

妳可以在我的公眾號 “玉樹芝蘭”(nkwangshuyi)後臺回復 “regex”,查看完整的代碼鏈接。

如果妳對我的教程滿意,歡迎在頁面右上方的 Star 上點擊壹下,幫我加壹顆星。謝謝!

註意這個頁面的中央,有個按鈕,寫著 “在 Colab 打開”(Open in Colab)。請妳點擊它。

然後,Google Colab 就會自動開啟。

我建議妳點壹下上圖中紅色圈出的 “COPY TO DRIVE” 按鈕。這樣就可以先把它在妳自己的 Google Drive 中存好,以便使用和回顧。

Colab 為妳提供了全套的運行環境。妳只需要依次執行代碼,就可以復現本教程的運行結果了。

如果妳對 Google Colab 不熟悉,沒關系。我這裏有壹篇教程,專門講解 Google Colab 的特點與使用方式。

為了妳能夠更為深入地學習與了解代碼,我建議妳在 Google Colab 中開啟壹個全新的 Notebook ,並且根據下文,依次輸入代碼並運行。在此過程中,充分理解代碼的含義。

這種看似笨拙的方式,其實是學習的有效路徑。

代碼

首先,讀入 Python 正則表達式包。

import re

然後,我們把數據準備好。註意為了演示代碼的通用性,我這裏在最後加了壹行文字,區別於之前的文字規律,看看我們的代碼能否正確處理它。

data = """張華考上了北京大學

李萍進了中等技術學校

韓梅梅進了百貨公司

他們都有光明的前途"""

然後,該寫正則表達式了。妳真的需要自己手動來寫嗎?

當然不必。

強大的 regex101 網站,已經幫助我們準備好了。

請妳點擊上圖中紅色圈出的按鈕,網站會為妳準備好壹個初始代碼的模板,可以匹配妳需要的模式。

妳不需要完全照搬代碼。其中有這樣壹句,是很重要的,拷貝過來,貼到 Colab Notebook 就好。

regex = r"(.*)[考|進].*了(.*)"

以上就是妳的正則表達式,在 Python 裏面應有的樣子。

我們準備壹個空列表,用來接收數據。

mylist = []

接著,寫壹個循環。

for line in data.split('n'):

?mysearch = re.search(regex, line)

?if mysearch:

name = mysearch.group(1)

dest = mysearch.group(2)

mylist.append((name, dest))

我給妳解釋壹下這個循環裏面,各條語句的含義:

data.split('n')?把文本數據按行來拆分開。這樣我們就可以針對每壹行,來獲取數據。mysearch = re.search(regex, line)?這壹句嘗試匹配模式到該行內容。if mysearch?這個判斷語句,是讓程序分辨壹下,該行是否有我們要找的模式。例如最後壹行文字,裏面並沒有咱們前面分析的文字模式。遇到這樣的行,直接跳過。name = mysearch.group(1)?是說匹配的第壹組內容,也就是 regex101 網站裏綠色代表的人名分組存到?name?變量裏。下壹句依次類推。註意?group?對應妳正則表達式裏面小括號出現的順序,從 1 開始計數。mylist.append((name, dest))?把該行抽取到的信息,存入到咱們之前定義的空列表裏面。

註意,如果不加?mysearch = re.search(regex, line)?這壹句,程序會對每壹行都嘗試匹配並且抽取分組內容,那麽結果就會報這樣的錯誤:

所以妳看,用正則表達式抽取信息時,不能蠻幹。

此時,我們查看壹下?mylist?這個列表裏面的內容:

mylist

結果為:

[('張華', '北京大學'), ('李萍', '中等技術學校'), ('韓梅梅', '百貨公司')]

不錯,壹個不多,壹個不少,恰好是我們需要的。

我們要把它導出成為表格。方法有很多,但是最簡便順手的,是用 Pandas 數據分析軟件包。

import pandas as pd

只需要利用?pd.DataFrame?函數,我們就能把上面列表和元組(tuple)組成的壹個二維結構,變成數據框。

df = pd.DataFrame(mylist)

df.columns = ['姓名', '去向']

註意,這裏我們還非常細心地修改了表頭。

看看妳的勞動成果吧:

df

有了數據框,轉換成為 Excel ,就是壹行代碼的事情了:

df.to_excel("dest.xlsx", index=False)

進入 Files 標簽頁,刷新並且查看壹下當前目錄下的內容:

這個?dest.xlsx?就是輸出的結果了。下載之後我們可以用 Excel 打開查看。

任務完成!

妳可以把結果提交給班主任,看他滿意的笑容了。

小結

這篇教程裏面,咱們談了如何利用文本字符規律,借助 Python 和正則表達式,來提取結構化信息。

希望妳已經掌握了以下本領:

了解正則表達式的功用;

用 regex101 網站嘗試正則表達式匹配,並且生成初步的代碼;

用 Python 批量提取信息,並且根據需求導出結構化數據為指定格式。

再次強調壹下,對於這麽簡單的樣例,使用上述方法,絕對是大炮轟蚊子。

然而,如果妳需要處理的數據是海量的,這個方法給妳節省下來的時間,會非常可觀。

希望妳能夠舉壹反三,在自己的工作中靈活運用它。

更多Python知識,請關註:Python自學網!!

  • 上一篇:我想利用網上免費教程學習數據庫知識,請問哪裏有呢?
  • 下一篇:非京籍人員上幼兒園的條件
  • copyright 2024編程學習大全網