自然語言處理3.7——用正則表達式為文本分詞


1、分詞的簡單方法:

在空格字符處分割文本是文本分詞最簡單的方法。考慮一下摘自《愛麗絲夢游仙境》中的文本。

>>> raw = """'When I'M a Duchess,' she said to herself, (not in a very hopeful tone
... though), 'I won't have any pepper in my kitchen AT ALL. Soup does very
... well without--Maybe it's always pepper that makes people hot-tempered,'..."""

 可以使用raw.split()在空格符處分割原始文本。使用正則表達式能做同樣的事情,匹配字符串中的所有空白符是遠遠不夠的,因為這會導致結果中包含'\n'換行符。需要同時匹配任何數量的空格符、制表符或者換行符。

>>>import re
>>>re.split(r' ',raw)
["'When", "I'M", 'a', "Duchess,'", 'she', 'said', 'to', 'herself,', '(not', 'in',
'a', 'very', 'hopeful', 'tone\nthough),', "'I", "won't", 'have', 'any', 'pepper',
'in', 'my', 'kitchen', 'AT', 'ALL.', 'Soup', 'does', 'very\nwell', 'without--Maybe',
"it's", 'always', 'pepper', 'that', 'makes', 'people', "hot-tempered,'..."]
>>>re.split(r'[ \t\n]+',raw)
["'When", "I'M", 'a', "Duchess,'", 'she', 'said', 'to', 'herself,', '(not', 'in',
'a', 'very', 'hopeful', 'tone', 'though),', "'I", "won't", 'have', 'any', 'pepper',
'in', 'my', 'kitchen', 'AT', 'ALL.', 'Soup', 'does', 'very', 'well', 'without--Maybe',
"it's", 'always', 'pepper', 'that', 'makes', 'people', "hot-tempered,'..."]

 正則表達式"[ \t\n]+"匹配一個多個空格、制表符或者換行符。其他的空白字符如回車和換行符也應該包含在內。於是re庫內置了縮寫'\s',表示匹配所有的空白字符。所有前面這個例子第二條語句可以改寫為re.split(r'\s',raw)

    在空格符出分割文本可得到如"(not"和"herself,"這樣的標識符。另一種方法是使用Python提供給我們的字符類"\w"匹配所有的字符,相當於[0-9a-zA-Z].定義這個類的補充部分"\W"即所有的字母,數字以外的字符。還可以在一個簡單的正則表達式中用\W來分割所有單詞以外的輸入。

>>> re.split(r'\W+', raw)
['', 'When', 'I', 'M', 'a', 'Duchess', 'she', 'said', 'to', 'herself', 'not', 'in',
'a', 'very', 'hopeful', 'tone', 'though', 'I', 'won', 't', 'have', 'any', 'pepper',
'in', 'my', 'kitchen', 'AT', 'ALL', 'Soup', 'does', 'very', 'well', 'without',
'Maybe', 'it', 's', 'always', 'pepper', 'that', 'makes', 'people', 'hot', 'tempered',
'']

 可以看到,在開始和結尾處都有一個空字符串,通過re.findall(r'\w+',raw)使用模式匹配詞匯而不是空白符號,得到相同的標識符。但是沒有空字符串。

正則表達式"\w+|\S\w*"會首先嘗試匹配詞中字符的所有序列,如果沒有找到匹配的,會嘗試匹配后面跟着詞中字符的任何非空白符。這意味着標點會很跟在后面的字母如’s在一起,但是兩個或兩個以上標點字符會被分割。

>>> re.findall(r'\w+|\S\w*', raw)
["'When", 'I', "'M", 'a', 'Duchess', ',', "'", 'she', 'said', 'to', 'herself', ',',
'(not', 'in', 'a', 'very', 'hopeful', 'tone', 'though', ')', ',', "'I", 'won', "'t",
'have', 'any', 'pepper', 'in', 'my', 'kitchen', 'AT', 'ALL', '.', 'Soup', 'does',
'very', 'well', 'without', '-', '-Maybe', 'it', "'s", 'always', 'pepper', 'that',
'makes', 'people', 'hot', '-tempered', ',', "'", '.', '.', '.']

 擴展前面正則表達式中的“\w+”,允許連字符和撇號“\w+(-')\w+”,他會匹配如hot-dog和it's這樣的單詞。還需要添加一個模式來匹配引號字符使他們與他們包含的文字分開。

>>> print(re.findall(r"\w+(?:[-']\w+)*|'|[-.(]+|\S\w*", raw))
["'", 'When', "I'M", 'a', 'Duchess', ',', "'", 'she', 'said', 'to', 'herself', ',',
'(', 'not', 'in', 'a', 'very', 'hopeful', 'tone', 'though', ')', ',', "'", 'I',
"won't", 'have', 'any', 'pepper', 'in', 'my', 'kitchen', 'AT', 'ALL', '.', 'Soup',
'does', 'very', 'well', 'without', '--', 'Maybe', "it's", 'always', 'pepper',
'that', 'makes', 'people', 'hot-tempered', ',', "'", '...']

 

NLTK的正則表達式分詞器

函數nltk.regexp_tokenize()和re.findall()類型,但是nltk.regexp_tokenize()分詞效率更高,避免了括號的特殊處理的需要。為了增加可讀性,將正則表達式分為幾行寫,每一行添加一個解釋。(?x)‘Verbose’標志告訴Python去掉嵌入的注釋和空格

>>> text = 'That U.S.A. poster-print costs $12.40...'
>>> pattern = r'''(?x)    # set flag to allow verbose regexps
...     ([A-Z]\.)+        # abbreviations, e.g. U.S.A.
...   | \w+(-\w+)*        # words with optional internal hyphens
...   | \$?\d+(\.\d+)?%?  # currency and percentages, e.g. $12.40, 82%
...   | \.\.\.            # ellipsis
...   | [][.,;"'?():-_`]  # these are separate tokens; includes ], [
... '''
>>> nltk.regexp_tokenize(text, pattern)
['That', 'U.S.A.', 'poster-print', 'costs', '$12.40', '...']

 使用verbose標志時,可以不使用' '來匹配空格字符,而是使用‘\s’代替。regexp_tokenize()有一個可選參數gaps。設置為True時,正則表達式指定標識符之間的距離。就行re.split()一樣。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM