數(shù)據(jù)抓取之正則表達式(未)

目前在學(xué)習(xí)《基于R語言的自動數(shù)據(jù)收集》和《用pyton寫網(wǎng)絡(luò)爬蟲》,兩者都介紹網(wǎng)頁數(shù)據(jù)獲取的相關(guān)途徑,前者分析了xml、json、xpath、正則表達式,后者對python內(nèi)正則表達式、Beautiful Soup和Lxml三者性能比較,如下表:

image01.png

今天僅僅對正則表達式知識學(xué)習(xí)整理。Web上的內(nèi)容主要是無結(jié)構(gòu)的文本。網(wǎng)絡(luò)抓取的一項核心任務(wù)就是從文本數(shù)據(jù)堆中采集和我們研究問題相關(guān)的信息。

正則表達式

正則表達式是用于搜索和操作文本數(shù)據(jù)的概括性文本特征。嚴(yán)格意義上,與其說它們是一個工具,不如說它們是如何通過各種函數(shù)對字符串進行查詢的慣例。本文介紹R中實現(xiàn)擴展正則表達式的基本組成部分。下面字符串會貫穿本文的例子:

  R> example.obj <- "1. A small sentence. - 2. Another tiny sentence."

嚴(yán)格的字符匹配

最基礎(chǔ)的層次就是字符和字符的匹配,即使正則表達式也是如此。因此,從一個字符串提取一個子串就會得到子串本身,如果有:

  R> str_extract(example.obj , "small")
  [1] "small"

否則,函數(shù)會返回一個缺失值:

  R> str_extract(example.obj , "banana")
  [1] NA

這里及其它部分使用的函數(shù)主要是來自stringr組件的str_extract(),我們假定這個組件的所有后續(xù)例子里都已加載了的。該函數(shù)的定義是str_extract(string , pattern),這樣首先輸入要被操作的字符串,然后就是要查找的表達式。該函數(shù)會在一個給定的字符串里返回與給定正則表達式匹配的第一個實例。我們也可以調(diào)用str_extract_all()函數(shù)要求R取出每一個匹配的結(jié)果。大家有興趣了解R和string字符串操作函數(shù)的比較,可以百度資料自行了解。

  R> unlist(str_extract_all(example.obj , "sentence"))
  [1] "sentence" "sentence"

由于str_extract_all()通??梢詫Χ鄠€字符串進行調(diào)用,所以結(jié)果是作為一個列表返回的,每個列表元素提供了針對其中的一個字符串的結(jié)果。上述調(diào)用中,輸入字符串是一個長度為1的字符向量,因此,函數(shù)會返回一個長度為1的列表,對它調(diào)用unlist()以便解析。下面把上述結(jié)果和同時對多個字符串進行調(diào)用時國企函數(shù)的表現(xiàn)進行比較。我們創(chuàng)建一個包含了"text" "manipulation" "basics"幾個字符串的向量。然后使用str_extract_all()函數(shù)來提取符合特征"a"的所有實例:

  R> out <-str_extract_all(c("text","manipulation","basics") , "a")
  R> out 
  [[1]]
  character(0)

  [[2]]
  [1] "a" "a"

  [[3]]
  [1] "a"

該函數(shù)返回一個與輸入向量長度(也就是3)相同的列表,列表每個元素包含一個字符串的結(jié)果。因為第一個字符串里沒有a,所以第一個元素是一個空字符向量。第二個字符串包含2個a,第三個字符串有1個。
默認(rèn)情況下,字符匹配是區(qū)分字母大小寫的。因此,正則表達式里的大寫字母和小寫字母是不一樣的。

  R> str_extract(example.obj , "small")
  [1] "small" 

在上面的字符串里包含small,而沒有SMALL。

  R> str_extract(example.obj , "SMALL")
  [1] NA

結(jié)果,該函數(shù)提取不到匹配的值。我們可以用ignore.case()包裹該字符串,從而改變這種結(jié)果。

  R> str_extract(example.obj , ignore.case("SMALL"))
  [1] "small"

使用正則表達式并不局限于匹配的單詞。一個字符串無非是一個字符的序列。因此,我們也可以匹配字根:

  R> unlist(str_extract_all(example.obj , "en"))
  [1] "en" "en" "en" "en"

或字母字符和空格的混合。

  R> unlist(str_extract_all(example.obj , "mall sent"))
  [1] "mall sent"

正則表達式的廣義化

到目前為止,我們只是進行固定表達式的匹配。但正則表達式的威力來源于能夠編寫靈活及廣義化的查詢條件。其中最為廣義化的是句號( . )。它可以匹配任意字符。

  R> str_extract(example.obj , "sm.ll")
  [1] "small" 

在正則表達式中,另一個強大的廣義化是字符類(character class),它被包裹在中括號里[ ]。一個字符類的含義是任何中括號里的字符都會被匹配。

  R> str_extract(example.obj , "sm[abc]ll")
  [1] "small"

還有另一種方法也可以利用字符范圍來指定字符類的元素,它使用 - 。

  R> str_extract(example.obj , "sm[a-p]ll")
  [1] "small"

在這種情況下,任何a到p的字符都是合法的匹配。除了字母和數(shù)字字符,也可以在正則表達式里包括標(biāo)點和空格。相類似,它們也可以放在字符類里。例如,字符[uvw.]能匹配u、v、w,也能匹配句號和空格。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容