簡單铸磅、直接、高效地從文本中提煉關鍵內容杭朱。讓你體驗正則表達式的威力愚屁。
痛點
很多人的日常工作,都是要和大量的文本打交道的痕檬。
例如學者需要閱讀大量的文獻材料霎槐,從中找到靈感、數(shù)據(jù)與論據(jù)梦谜。
學生需要閱讀很多教科書和論文丘跌,然后寫自己的報告或者做幻燈。
財經(jīng)分析師唁桩,需要從大量的新聞報道中闭树,找到行業(yè)的發(fā)展趨勢和目標企業(yè)動態(tài)的蛛絲馬跡。
不是所有的文本處理荒澡,都那么新鮮而有趣报辱。
有一項重要但繁瑣的工作,就是從大量的文本當中抽取結構化的信息单山。
許多數(shù)據(jù)分析的場景碍现,都要求輸入結構化的信息。
例如在咱們之前介紹過的《貸還是不貸:如何用Python和機器學習幫你決策米奸?》和《如何用Python和深度神經(jīng)網(wǎng)絡鎖定即將流失的客戶昼接?》中,你都看到了悴晰,機器模型更喜歡被結構化的表格信息來喂養(yǎng)慢睡。
然而,結構化的信息铡溪,不一定就在那里漂辐,靜候你來使用。很多時候棕硫,它蘊藏在以往生成的非結構化文本中髓涯。
你可能早已習慣,人工閱讀文本信息饲帅,把關鍵點摘取出來复凳,然后把它們拷貝粘貼放到一個表格中瘤泪。從原理上講灶泵,這樣做無可厚非育八。但是實際操作里面,效率太低赦邻,而且太麻煩髓棋。
大部分人,是不愿意從事這種簡單重復的枯燥工作的惶洲。
一遍遍機械重復鼠標劃定文本范圍按声,“Ctrl+C”、切換到表格文檔恬吕、找準輸入位置签则,再“Ctrl+V”……
這種事兒做得太多,對你的肩肘關節(jié)铐料,甚至是身心健康渐裂,都有可能造成不利影響。
想不想嘗試用一種更簡單的自動化方式钠惩,替你快速完成這些煩人的操作步驟呢柒凉?
讀過本文后,希望你能找到答案篓跛。
樣例
這里膝捞,我們舉一個極端簡化的中文文本抽取信息例子。
之所以這樣做愧沟,是為了避免你在解讀數(shù)據(jù)上花費太多時間蔬咬。
我更希望,你能夠聚焦于方法沐寺,從而掌握新知计盒。
假設一個高中班主任,高考后讓班長統(tǒng)計一下學生們的畢業(yè)去向芽丹。班長很認真地進行了調查北启,然后做了如下匯報:
張華考上了北京大學
李萍進了中等技術學校
韓梅梅進了百貨公司
……
為了讓你對樣例足夠熟悉,甚至有共鳴拔第,這里我從1998年版的新華字典中咕村,“借鑒”了部分內容。
夠貼心吧蚊俺?
現(xiàn)實生活中懈涛,一個班大概不會只有3個人,因此你可以想象這是一個長長的句子列表泳猬。
但其實班主任有個隱含的意思沒有表達出來批钠,即:
我想要一張表格宇植!
所以,看到這一長串的句子埋心,你可以想象他的表情指郁。
班長估計也很難堪:
想要表格你早說啊拷呆!
這時候闲坎,假設你是班長,怎么辦茬斧?
信息都在文本里面腰懂。但如果需要轉換成表格,就得一個個信息點去尋找和處理项秉。
其實绣溜,對于四五十人的班級來說,手動操作也不是什么太難的事情娄蔼。
但是設想一下怖喻,如果你需要處理的數(shù)據(jù)量,是這個例子的十倍贷屎、百倍甚至千萬倍呢罢防?
繼續(xù)堅持手動處理?
這不僅麻煩唉侄,而且不現(xiàn)實咒吐。
我們需要找到一種簡單的方法,幫助我們自動抽取相應的信息属划。
此處我們使用的方法恬叹,是正則表達式。
正則
“正則表達式”這個名字同眯,初聽起來好像很玄妙绽昼。實際上,它是從英文“regular expression”翻譯過來的须蜗。
如果譯成白話硅确,那就是“有規(guī)律的表述形式”。
這明肮,聽起來菱农,是不是就更加接地氣了?
但是柿估,給你補一下“假行家101”課程:
說別人聽得懂的話循未,你能唬得住誰?
約定俗成秫舌,咱們繼續(xù)沿用“正則表達式”的妖,來稱呼它好了绣檬。
從創(chuàng)生之日起,它就給文本處理帶來了高效率嫂粟。
但是娇未,用它的主要人群,卻不是時常跟文字打交道的作家赋元、編輯忘蟹、學者飒房、文員搁凸,而是……
程序員!
程序員寫的代碼狠毯,是文本护糖;程序員處理的數(shù)據(jù),很多也是文本格式嚼松。其中便有很多顯著的規(guī)律可循嫡良。
正是靠著正則表達式這種獨門秘籍,許多別人做起來献酗,需要昏天黑地一整周的任務寝受,程序員可以半小時搞定,然后喝著咖啡等下班罕偎。
即便到了泛人工智能的今天很澄,正則表達式依然有許多令你意想不到的應用。
例如人機對話系統(tǒng)颜及。
你可能看了新聞報道甩苛,總以為人機對話都是靠著知識圖譜或者深度學習搞出來的。
不能說這里面俏站,沒有上述炫酷技術的參與讯蒲。但它們充其量,只占其中一部分肄扎,或許還只是一小部分墨林。
生產實踐里面,大量的對話規(guī)則后面犯祠,并不是讓你倍感神奇深奧的神經(jīng)網(wǎng)絡旭等,而是一堆正則表達式。
你可能會擔心雷则,這樣高端的應用技術辆雾,自己能掌握嗎?
答案是:
當然月劈!
正則表達式度迂,并不難學藤乙。
尤其是當你把它和 Python 結合到一起,那簡直就是效率神器了惭墓。
我們這就來看看坛梁,正則表達式怎么幫我們識別出樣例文本里面“人名”和“去向”信息。
試練
請你開啟一個瀏覽器腊凶,鍵入這個網(wǎng)址(https://regex101.com/)划咐。
你會看見如下界面。
它可是一個正則表達式實驗的利器钧萍。我教 INFO 5731 課程時褐缠,學生們就是在掌握了這個工具以后,迅速玩兒轉了正則表達式风瘦。
這么好的工具队魏,一定要價不菲吧?
不万搔,它是免費的胡桨。你放心大膽使用就好了。
我們首先把左側的編程語言瞬雹,從默認的 PHP 昧谊,調整為 Python。
之后酗捌,把需要進行處理的文本呢诬,貼到中間空白的大文本框里面。
下面我們來嘗試進行“匹配”意敛。
什么叫做匹配呢馅巷?
就是你寫一個表達式,電腦便拿著雞毛當令箭草姻,在每一行文本上钓猬,都認認真真地找有沒有符合該表達式的文本段落。
如有撩独,則會高亮顯示出來敞曹。
這里我們觀察一下,發(fā)現(xiàn)每個句子里面综膀,人員去向前面澳迫,都有一個“了”字。
好剧劝,我們就在中部上方小文本框里橄登,把“了”字輸入進去。
可以看到,三句話里面的“了”拢锹,全都亮了谣妻。
這就是你接觸到的第一種匹配方式——按照字符原本的意思來查找一致的內容。
因為樣例文本的規(guī)律性卒稳,我們可以把“了”當成一個定位符蹋半,它后面,到句子結束位置充坑,是“去向”信息减江。
咱們需要找的一半結構化信息,不就是這個“去向”嗎捻爷?
我們嘗試匹配“去向”辈灼。
怎么匹配呢?這次每一行的字兒都不一樣耙酆狻茵休?
沒關系薪棒,正則表達式強大之處手蝎,此時就顯示出來了。
你可以用一個點號俐芯,也就是.
棵介,表示任意字符。
字母吧史、數(shù)字邮辽、標點……甚至是中文,也能涵蓋在內贸营。
然后我們繼續(xù)想想看吨述,去向信息這里,會有幾個字呢钞脂?
不好說揣云。
例子里面這簡單的三句話,就有“4個字”或者“6個字”兩種情況冰啃。
所以邓夕,我們無法指定去向信息里面字符的長度。
但這也沒關系阎毅,我們只需要用一個星號(*
)焚刚,就可以代表出現(xiàn)次數(shù),從0到無窮大都可以匹配扇调。
當然矿咕,實際情況中,是不會真出現(xiàn)無窮大的。
我們在剛才輸入的基礎上碳柱,加上.*
雌团,結果就成了這個樣子:
不錯嘛!
不過似乎去向信息和“了”字兒都是一樣顏色的高亮士聪。那不就混到了一起嗎锦援?
我們可不想這樣。
怎么辦剥悟?
請你在.*
的兩側灵寺,嘗試加入一對小括號(注意,不要用中文全角符號)試試看区岗。
你會發(fā)現(xiàn)略板,這次“了”依然用藍色表示,而后面的去向信息慈缔,已經(jīng)變成了綠色叮称。
這一對小括號,很重要藐鹤,它叫做“分組”瓤檐,是提取信息的基本單位。
我們的任務已經(jīng)解決了一半了,是吧?
下面我們來嘗試把人名一并抽取出來咆贬。
我們來找人名的錨定位置。
細細觀察谴古,你不難發(fā)現(xiàn),每個人名的后面稠歉,都有個動詞跟著掰担。
升學的同學,用的是“考”字怒炸,而就業(yè)的同學带饱,用的是“進”字。
我們先嘗試一下“考”字横媚。
這里我們嘗試直接把“考”字放在“了”字以前纠炮。但是你會發(fā)現(xiàn),什么匹配結果也沒有灯蝴。
為什么恢口?
回看數(shù)據(jù),你會發(fā)現(xiàn)穷躁,人家用的原詞是“考上了”耕肩。
當然這里我們可以輸入“上”字因妇。不過你要考慮一下更為通用的情況。
好比說猿诸,“考取了”怎么辦婚被?“考入了”呢?
更好的方式梳虽,是繼續(xù)使用我們剛才學會的“大招”址芯,在“考”和“了”之間,插入一個.*
窜觉。
這時候谷炸,你的正則表達式的樣子是 考.*了(.*)
看,第一行的信息成功匹配了吧禀挫?
但是旬陡,那后面還有兩行沒有匹配,怎么辦语婴?
我們依樣畫葫蘆描孟,就會發(fā)現(xiàn),使用進.*了(.*)
就能正確匹配后兩行砰左。
問題來了:
匹配第一行的匿醒,匹配不了后兩行,反之亦然菜职。
這不好青抛。我們希望寫的表達式,能夠更通用酬核。
怎么辦?
我們看看正則表達式當中“或”關系的表示适室。
這里嫡意,我們可以把兩個字符用豎線隔開,旁邊用中括號括起來捣辆,代表兩者任一出現(xiàn)蔬螟,都算匹配成功。
也就是汽畴,把正則表達式旧巾,寫成這樣:[考|進].*了(.*)
太棒了,三行的內容都已經(jīng)匹配成功忍些。
這里鲁猩,動詞詞組,和代表時態(tài)的“了”作為中間錨定信息罢坝,我們可以放心大膽廓握,把之前的人名信息,提取出來了。
也就是這樣寫:(.*)[考|進].*了(.*)
注意此時隙券,人名分組是綠色男应,去向分組是紅色的。
我們成功提取了兩組信息娱仔!慶祝一下沐飘!
可是,如果你給班主任看這里的結果牲迫,估計他不會滿意薪铜。
表格,我要表格恩溅!
別著急隔箍,該 Python 出場了。
下面我們嘗試在 Python 把數(shù)據(jù)正式提取出來脚乡。
環(huán)境
本文的配套源代碼蜒滩,我放在了 Github 上。
你可以在我的公眾號“玉樹芝蘭”(nkwangshuyi)后臺回復“regex”奶稠,查看完整的代碼鏈接俯艰。
如果你對我的教程滿意,歡迎在頁面右上方的 Star 上點擊一下锌订,幫我加一顆星竹握。謝謝!
注意這個頁面的中央辆飘,有個按鈕啦辐,寫著“在 Colab 打開”(Open in Colab)。請你點擊它蜈项。
然后芹关,Google Colab 就會自動開啟。
我建議你點一下上圖中紅色圈出的 “COPY TO DRIVE” 按鈕紧卒。這樣就可以先把它在你自己的 Google Drive 中存好侥衬,以便使用和回顧。
Colab 為你提供了全套的運行環(huán)境跑芳。你只需要依次執(zhí)行代碼轴总,就可以復現(xiàn)本教程的運行結果了。
如果你對 Google Colab 不熟悉博个,沒關系怀樟。我這里有一篇教程,專門講解 Google Colab 的特點與使用方式坡倔。
為了你能夠更為深入地學習與了解代碼漂佩,我建議你在 Google Colab 中開啟一個全新的 Notebook 脖含,并且根據(jù)下文,依次輸入代碼并運行投蝉。在此過程中养葵,充分理解代碼的含義。
這種看似笨拙的方式瘩缆,其實是學習的有效路徑关拒。
代碼
首先,讀入 Python 正則表達式包庸娱。
import re
然后着绊,我們把數(shù)據(jù)準備好。注意為了演示代碼的通用性熟尉,我這里在最后加了一行文字归露,區(qū)別于之前的文字規(guī)律,看看我們的代碼能否正確處理它斤儿。
data = """張華考上了北京大學
李萍進了中等技術學校
韓梅梅進了百貨公司
他們都有光明的前途"""
然后剧包,該寫正則表達式了。你真的需要自己手動來寫嗎往果?
當然不必疆液。
強大的 regex101 網(wǎng)站,已經(jīng)幫助我們準備好了陕贮。
請你點擊上圖中紅色圈出的按鈕堕油,網(wǎng)站會為你準備好一個初始代碼的模板,可以匹配你需要的模式肮之。
你不需要完全照搬代碼掉缺。其中有這樣一句,是很重要的局骤,拷貝過來攀圈,貼到 Colab Notebook 就好。
regex = r"(.*)[考|進].*了(.*)"
以上就是你的正則表達式峦甩,在 Python 里面應有的樣子。
我們準備一個空列表现喳,用來接收數(shù)據(jù)凯傲。
mylist = []
接著,寫一個循環(huán)嗦篱。
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))
我給你解釋一下這個循環(huán)里面冰单,各條語句的含義:
-
data.split('\n')
把文本數(shù)據(jù)按行來拆分開。這樣我們就可以針對每一行灸促,來獲取數(shù)據(jù)诫欠。 -
mysearch = re.search(regex, line)
這一句嘗試匹配模式到該行內容涵卵。 -
if mysearch
這個判斷語句,是讓程序分辨一下荒叼,該行是否有我們要找的模式轿偎。例如最后一行文字,里面并沒有咱們前面分析的文字模式被廓。遇到這樣的行坏晦,直接跳過。 -
name = mysearch.group(1)
是說匹配的第一組內容嫁乘,也就是 regex101 網(wǎng)站里綠色代表的人名分組存到name
變量里昆婿。下一句依次類推。注意group
對應你正則表達式里面小括號出現(xiàn)的順序蜓斧,從1開始計數(shù)仓蛆。 -
mylist.append((name, dest))
把該行抽取到的信息,存入到咱們之前定義的空列表里面挎春。
注意看疙,如果不加 mysearch = re.search(regex, line)
這一句,程序會對每一行都嘗試匹配并且抽取分組內容搂蜓,那么結果就會報這樣的錯誤:
所以你看狼荞,用正則表達式抽取信息時,不能蠻干帮碰。
此時相味,我們查看一下 mylist
這個列表里面的內容:
mylist
結果為:
[('張華', '北京大學'), ('李萍', '中等技術學校'), ('韓梅梅', '百貨公司')]
不錯,一個不多殉挽,一個不少丰涉,恰好是我們需要的。
我們要把它導出成為表格斯碌。方法有很多一死,但是最簡便順手的,是用 Pandas 數(shù)據(jù)分析軟件包傻唾。
import pandas as pd
只需要利用 pd.DataFrame
函數(shù)投慈,我們就能把上面列表和元組(tuple)組成的一個二維結構,變成數(shù)據(jù)框冠骄。
df = pd.DataFrame(mylist)
df.columns = ['姓名', '去向']
注意伪煤,這里我們還非常細心地修改了表頭。
看看你的勞動成果吧:
df
有了數(shù)據(jù)框凛辣,轉換成為 Excel 抱既,就是一行代碼的事情了:
df.to_excel("dest.xlsx", index=False)
進入 Files 標簽頁,刷新并且查看一下當前目錄下的內容:
這個 dest.xlsx
就是輸出的結果了扁誓。下載之后我們可以用 Excel 打開查看防泵。
任務完成蚀之!
你可以把結果提交給班主任,看他滿意的笑容了捷泞。
小結
這篇教程里面足删,咱們談了如何利用文本字符規(guī)律,借助 Python 和正則表達式肚邢,來提取結構化信息壹堰。
希望你已經(jīng)掌握了以下本領:
- 了解正則表達式的功用;
- 用 regex101 網(wǎng)站嘗試正則表達式匹配骡湖,并且生成初步的代碼贱纠;
- 用 Python 批量提取信息,并且根據(jù)需求導出結構化數(shù)據(jù)為指定格式响蕴。
再次強調一下谆焊,對于這么簡單的樣例,使用上述方法浦夷,絕對是大炮轟蚊子辖试。
然而,如果你需要處理的數(shù)據(jù)是海量的劈狐,這個方法給你節(jié)省下來的時間罐孝,會非常可觀肥缔。
希望你能夠舉一反三莲兢,在自己的工作中靈活運用它。
資源
先別急著走续膳。
由于篇幅所限改艇,教程中我只給你介紹了幾項最簡單正則語法》夭恚肯定會有很多你感興趣的語法知識谒兄,沒來得及一一講給你聽。
如果你對于正則表達式很感興趣社付,因為科研或者工作目的承疲,需要馬上學習,也請不要著急鸥咖。
我這里剛好有一份免費的優(yōu)秀教程資源分享給你纪隙。
我在 UNT 講授 INFO 5731 課程的時候,就是用這份教程結合翻轉教學扛或,讓從沒聽說過正則表達式的學生們,在一兩周之內掌握并且熟練應用碘饼。相信對你來說熙兔,這份教程資源也會很有用悲伶。
你可以在我的公眾號“玉樹芝蘭”(nkwangshuyi)后臺回復“regex”,查看教程鏈接住涉。
祝學習愉快麸锉!
喜歡別忘了點贊。
還可以微信關注我的公眾號“玉樹芝蘭”(nkwangshuyi)舆声。別忘了加星標花沉,以免錯過新推送提示。
如果本文可能對你身邊的親友有幫助媳握,也歡迎你把本文通過微博或朋友圈分享給他們碱屁。讓他們一起參與到我們的討論中來。
延伸閱讀
你可能也會對以下話題感興趣蛾找。點擊鏈接就可以查看娩脾。
題圖: Photo by Tim St. Martin on Unsplash