python 爬蟲括弧的用法

來源:互聯網
上載者:User

標籤:second   特殊   條件   string   pattern   eth   dal   bre   結構   

首先是文檔說明:

>>> import re

>>> help(re.findall)

Help on function findall in module re:

 

findall(pattern, string, flags=0)

    Return a list of all non-overlapping matches in the string.

   

    If one or more capturing groups are present in the pattern, return

    a list of groups; this will be a list of tuples if the pattern

    has more than one group.

   

    Empty matches are included in the result.


意思很明顯,分組匹配下(一對括弧內是一個組),findall函數返回元組形式的匹配結果,並且匹配為空白也會返回到元組中。
所以一般用法是這樣的:

>>> a = "one two threefour five six"

>>> import re

 

 

>>> b = re.findall(r"(one) (two) (three) (four) (five) (six)",a)#去掉了"|"號

>>> print(b)

[(‘one‘, ‘two‘, ‘three‘, ‘four‘, ‘five‘, ‘six‘)]#按組將匹配結果添加到元組中返回

 

>>> b = re.findall(r"(one) (two) (three) (four)",a)

#不完全符合

>>> print(b)

[(‘one‘, ‘two‘, ‘three‘, ‘four‘)]

 #按組返回匹配成功部分,列表長度為1

 

>>> b = re.findall(r"one|two|three|four|five|six",a)

#不安組的條件匹配

>>> print(b)

[‘one‘, ‘two‘, ‘three‘, ‘four‘, ‘five‘, ‘six‘]#返回長度為6的列表

 

>>> b = re.findall(r"one two three four five six",a)

>>> print(b)

[‘onetwo three four five six‘] #完全符合,返回長度為1的列表

 

>>> b = re.findall(r"(one) (two) (three) (four) (five) (six)(seven)",a)

>>> print(b)

[]#沒法全部匹配,返回空

 

>>> print (re.findall(r"[abc]","abc"))#[]的效果

[‘a‘,‘b‘,‘c‘]

>>> print (re.findall(r"a|b|c","abc"))#"|"的效果

[‘a‘,‘b‘,‘c‘]

通過以上實驗可以得出的結論:
1條件匹配符"|"使得findall按每一種條件匹配一次,且"|"和"[]"效果是相同的,返回形式一樣。
2圓括弧分組匹配使得findall返回元組,元組中,幾對圓括弧就有幾個元素,保留空匹配。

再看我提問中舉的例子,將條件匹配與分組匹配結合在了一起。

>>> a = "one two threefour five six"

>>> b = re.findall("(one)|(two)|(three)|(four)|(five)|(six)",a)#加上了"|"號

>>> print(b)

[(‘one‘, ‘‘, ‘‘, ‘‘, ‘‘, ‘‘), (‘‘, ‘two‘, ‘‘, ‘‘, ‘‘, ‘‘),

(‘‘, ‘‘, ‘three‘, ‘‘, ‘‘, ‘‘),(‘‘, ‘‘, ‘‘, ‘four‘, ‘‘, ‘‘),

(‘‘, ‘‘, ‘‘, ‘‘, ‘five‘, ‘‘),(‘‘, ‘‘, ‘‘, ‘‘, ‘‘, ‘six‘)]

於是就理解了:
1這個結果是因為按組匹配所以有元組,每個元組都有六個元素。
2而因為是條件匹配,列了六種匹配條件,於是findall匹配六次,結果清單有六個元素。
3又因為每次匹配只能用一種條件,所以按組匹配結果清單中的每個元組只有一組有值而其他均為空白。

這有什麼用呢?比如:

>>> x = "3 min 46 sec300 ms"

 #分秒毫秒的提取

>>> print(re.findall(r"(\d{0,}) (min|sec|ms)",x))

[(‘3‘, ‘min‘), (‘46‘, ‘sec‘), (‘300‘, ‘ms‘)] #會不會很方便?


--------------------------------------------------------------------------------------------------
這個理解其實對下面那個問題(如何匹配某種單詞搭配)沒什麼用,因為還有一個符號沒有介紹,那就是"?:"符號,表示取消按分組返回。

#這個正則式子是隨意寫就的,

#按照人的思維理解。

#這個式子匹配以h或s為開頭,ef或cd的(a或b)結尾為結尾的東西。

#一共有2*2*2八種可能性,findall的結果會有八個元素。

>>>print(re.findall(r"\b((h|s)(ef|(cd|(a|b))))\b","sef scd sa sbhef hcd ha hb"))

#不添加?:符號時結果如下:

#正則式子中的括弧一共有五個,所以返回列表裡的每個元組有五個元素

[(‘sef‘,‘s‘, ‘ef‘, ‘‘, ‘‘), (‘scd‘, ‘s‘, ‘cd‘, ‘cd‘, ‘‘),

(‘sa‘, ‘s‘,‘a‘, ‘a‘, ‘a‘), (‘sb‘, ‘s‘, ‘b‘, ‘b‘, ‘b‘),

(‘hef‘,‘h‘, ‘ef‘, ‘‘, ‘‘), (‘hcd‘, ‘h‘, ‘cd‘, ‘cd‘, ‘‘),

(‘ha‘, ‘h‘,‘a‘, ‘a‘, ‘a‘), (‘hb‘, ‘h‘, ‘b‘, ‘b‘, ‘b‘)]

 

#下面是加上"?:"的結果

>>>print(re.findall(r"\b(?:(?:h|s)(?:ef|(?:cd|(?:a|b))))\b","sefscd sa sb hef hcd ha hb"))

[‘sef‘,‘scd‘, ‘sa‘, ‘sb‘, ‘hef‘, ‘hcd‘, ‘ha‘, ‘hb‘]

#非常簡潔

第一個式子返回的結果其實也算OK,因為已經覆蓋到了所有的可能,只不過冗餘項比較多,想得到純粹的結果還要處理一次。
第二個式子加了"?:"後就簡潔許多。
作為初學者,可能用不到分組這麼複雜的正則式子,也就更不用提取消分組的符號了,所以很多正則的入門教程並不會花太多時間在這兩項上。
所以現在就介紹一下如何解決匹配單詞搭配的問題。
就比如說找數量結構的片語吧。

我們先進行書面的結構分析
數量結構是一種表示數量關係的短語,比如漢語中的一斤酒一兩牛肉,由數詞+量詞+名詞構成,也可以是一下,輕輕一按,用力一踢,由副詞/+數詞+動詞構成。
在英語中數量結構又分為兩種。
第一種是 a/an + n1 + of + n2,其中n1、n2是名詞。比如 a piece of bread 。這種結構往往用來修飾不可數名詞。
第二種是 num. + n 這個簡單,就是數詞+可數名詞的複數形式,窮舉所有的數詞就行了。

第一種的正則式很簡單,是這樣的:

r"\ban{0,1}\b\b\w+\b \bof\b \b\w+\b" #凡是在不定冠詞和of之間的必然是名詞,在of之外的是名詞

第二種就稍微複雜一點,我們要把所有的數詞都列出來,尋找其中的規律

差不多能分出這麼幾組
沒有規律的:(?:hundred|thounsand|million|billion|trillion|one|two|three|ten|five|eleven|twelvetwenty|forty)
結尾可加teen也可不加的:(?:(?:four)(?:teen){0,1})
結尾可加teen或ty也可不加的 :(?:(?:six|seven|eight|nine)|(?:ty|teen))
結尾必須加teen或ty的: (?:(?:fif|thir)(?:ty|teen))
把他們組合起來就是:

r"(?:(?:hundred|thounsand|million|billion|trillion|one|two|three|ten|five|eleven|twelve|twenty|forty)|(?:(?:four)(?:teen){0,1})|(?:(?:six|seven|eight|nine)|(?:ty|teen))|(?:(?:fif|thir)(?:ty|teen)))\b"

再加上第一種可能就成了:

(?:\ban{0,1}\b\b\w+\b\bof\b)|(?:(?:(?:hundred|thounsand|million|billion|trillion|one|two|three|ten|five|eleven|twelve|twenty|forty)|(?:(?:four)(?:teen){0,1})|(?:(?:six|seven|eight|nine)|(?:ty|teen))|(?:(?:fif|thir)(?:ty|teen)))\b)

這還只是選了前部分,後面還要接一個名詞,所以:

(?:(?:\ban{0,1}\b \b\w+\b \bof\b)|(?:(?:(?:hundred|thounsand|million|billion|trillion|one|two|three|ten|five|eleven|twelve|twenty|forty)|(?:(?:four)(?:teen){0,1})|(?:(?:six|seven|eight|nine)|(?:ty|teen))|(?:(?:fif|thir)(?:ty|teen)))\b)) (?:\b\w+\b)

於是這就是是完成狀態了,我們來檢測一下成果吧:

input

 

import rea = "acup of tea million stars forty people "

b = re.compile(r"(?:(?:\ban{0,1}\b\b\w+\b\bof\b)|(?:(?:(?:hundred|thounsand|million|billion|trillion|one|two|three|ten|five|eleven|twelve|twenty|forty)|(?:(?:four)(?:teen){0,1})|(?:(?:six|seven|eight|nine)|(?:ty|teen))|(?:(?:fif|thir)(?:ty|teen)))\b))(?:\b\w+\b)")

print(re.findall(b,a))

 

output

[‘acup of tea‘, ‘million stars‘, ‘forty people‘]

 

這種眼花繚亂的式子,看著很麻煩,也不好解讀,還好python提供了鬆散Regex。
只要在re.comile的第二個參數上填上"re.VERBOSE"即可寫成如
‘‘‘
example
‘‘‘
注釋的形式,此時空格不再被匹配,必須使用\s表達(下面這個版本已經更新了,這次更新囊括了所有的序數詞):

a = "give me a kiss million stars one piece"

b = re.compile(r"""

#隨時可以以#號備忘

(?:\b\w+\b\s\b\w+\b\s)?

(?:

 

    (?:\ban?\b\s\b\w+\b\s\bof\b)

    |#第一類數量結構

    (?:

       (?:\b(?:one|two|three|five|first|second|third|fifth|sixth|an?))

        |#fifth在這裡 沒有規律的數詞 fifth sixth

       (?:(?:hundred|thounsand|million|billion|trillion|ten|eleven|twel(?:f|ve))(?:th)?)

        |

        (?:(?:twent|fort)(?:y|ieth))

        |

        (?:(?:four)(?:teen|th)?)

        |#加不加teen皆可的數詞

       (?:(?:six|seven|eight?|nine?)(?:(?:(?:t[yh])(?:eth)?)|(?:teen)(?:th)?)?)

        |#加不加teen或ty皆可的數詞

       (?:(?:fif|thir)(?:(?:t[yi])(?:eth)?|(?:teen)(?:th)?))

        #必須加teen或ty的數詞 fifteenthirteen fifty thirty  fiftieth thirtiethfifteenth thirteenth

    )\b#第二類數量結構

)\s

(?:\b\w+\b)#後跟的名詞

""",re.VERBOSE)

 

這個式子到這裡還是比較粗糙的,比如對於任何一文章中的“the one you”他都會當作數量結構匹配,所以還要增加一些其他條件來過濾這樣的可能,不過我還沒學到那個地步,所以我也沒法解決這個問題,以後學會再來添加吧!

 

更新一下:
關鍵詞:零寬斷言
在pythonRegex中使用零寬斷言,網上也有很多教程。
簡單說,零寬斷言要完成的目標是:當字串符合一定條件,則匹配某些字元。
什麼叫斷言?
一個斷言就是對條件做出判斷,相當於if判斷結構,滿足條件,則做某事,不過else只能是不匹配。
什麼叫零寬?
也就是這個東西所佔的匹配字元中的寬度是零,也就是不匹配本身。
其他的關鍵詞如零寬度正預測先行斷言太複雜了我也不太清楚,就不講了,會用就行。

使用方法:exp(?=exp)
在括弧中使用?=後,這個括弧內?=之後的字元就成了零寬斷言所要判斷的條件,前面括弧之外的運算式則是判斷滿足條件要啟用的匹配字元。
舉例:
\w+(?=logy)
該運算式匹配任意以logy結尾的單詞,但是不匹配logy本身。

如果要把這個判斷放在前面,則要用:(?<=exp)exp
舉例:
(?<=href=")http
可以匹配href="開頭的http,但是不包括href=",這樣的操作也省去了爬蟲清洗資料時的一部分壓力。

需要注意的是,前置的斷言在python中不能使用不確定寬度的字元作為判斷條件,必須確定字元的個數。所以如果你還想同時匹配(?<=src=")http,你不能寫(?<=src="|href=")http,你可以寫:
(?:(?<=src=")|(?<=href="))http
這是python實現的一個小缺陷。
不過後置的就可以這麼寫
http(?=src="|href=")

接著我們還有滿足條件不匹配的用法,也就是在?後面加!。前置的就成了
(?!<=exp)
後置的成了(?!=exp)
這時候填寫進去的字元,就成了遇到則不匹配的條件。

而我的數詞尋找就需要這個功能,來實現避免數詞出現在省略先行詞從句的開頭的情況。
當然下面這個運算式是不能啟動並執行,必須放到之前那個大串裡。

re.compile(r"""

(?!

    (?:

        \b

        (?:

        (?:[Yy]ou|[Tt]hey)(?:‘re)?

        |

        I|to|with|in|[SsHh]h?e|[Ii]t

        |

        (?:[Tt]h)(?:is|at|e[sr]e|)

        |

        (?:(?:[Ww]h)(?:o[ms]?e?|ere|at|en|i[cl][he]))

        )

        \b

    )

)

#篩掉的特殊詞you I he she it this there thatthose with to in which where what when while whose who whom

""",re.VERBOSE)



結合兩者就是:

En_value =re.compile(r"""

#隨時可以以#號備忘

#尾斷言可以有不確定符號數的匹配,首斷言不可以。

(?:\b\w+\b\s\b\w+\b\s)?

(?:

 

    (?:\ban?\b\s\b\w+\b\s\bof\b)

    |#第一類數量結構

    (?:

       (?:\b(?:one|two|three|five|first|second|third|fifth|sixth|an?))

        |#fifth在這裡 沒有規律的數詞 fifth sixth

       (?:(?:hundred|thounsand|million|billion|trillion|ten|eleven|twel(?:f|ve))(?:th)?)

        |

        (?:(?:twent|fort)(?:y|ieth))

        |

        (?:(?:four)(?:teen|th)?)

        |#加不加teen皆可的數詞

       (?:(?:six|seven|eight?|nine?)(?:(?:(?:t[yh])(?:eth)?)|(?:teen)(?:th)?)?)

        |#加不加teen或ty皆可的數詞

        (?:(?:fif|thir)(?:(?:t[yi])(?:eth)?|(?:teen)(?:th)?))

        #必須加teen或ty的數詞 fifteen thirteen fifty thirty fiftieth thirtieth fifteenth thirteenth

    )\b#第二類數量結構

)\s

(?!

    (?:

        \b

        (?:

        (?:[Yy]ou|[Tt]hey)(?:‘re)?

        |

        I|to|with|in|[SsHh]h?e|[Ii]t

        |

        (?:[Tt]h)(?:is|at|e[sr]e|)

        |

       (?:(?:[Ww]h)(?:o[ms]?e?|ere|at|en|i[cl][he]))

        )

        \b

    )

)

#篩掉的特殊詞(you I he she it this therethat those with to in which where what when while whose who whom

(?:\b\w+\b)#後跟的名詞

""",re.VERBOSE)

python 爬蟲括弧的用法

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.