Làm cách nào để thoát khỏi dấu chấm câu bằng cách sử dụng mã thông báo NLTK?


125

Tôi mới bắt đầu sử dụng NLTK và tôi hoàn toàn không hiểu làm thế nào để có được danh sách các từ trong văn bản. Nếu tôi sử dụng nltk.word_tokenize(), tôi nhận được một danh sách các từ và dấu câu. Tôi chỉ cần những từ thay thế. Làm thế nào tôi có thể thoát khỏi dấu câu? Cũng word_tokenizekhông hoạt động với nhiều câu: dấu chấm được thêm vào từ cuối cùng.


12
Tại sao bạn không tự xóa dấu câu? nltk.word_tokenize(the_text.translate(None, string.punctuation))nên làm việc trong python2 trong khi trong python3 bạn có thể làm nltk.work_tokenize(the_text.translate(dict.fromkeys(string.punctuation))).
Bakuriu

3
Điều này không hoạt động. Không có gì xảy ra với văn bản.
lizarisk

Quy trình công việc được giả định bởi NLTK là trước tiên bạn token hóa thành câu và sau đó mỗi câu thành từ. Đó là lý do tại sao word_tokenize()không làm việc với nhiều câu. Để thoát khỏi dấu câu, bạn có thể sử dụng biểu thức chính quy hoặc isalnum()hàm python .
Suzana

2
làm việc: >>> 'with dot.'.translate(None, string.punctuation) 'with dot'(lưu ý không nằm rải rác ở phần cuối của kết quả) nó có thể gây ra vấn đề nếu bạn có những thứ như 'end of sentence.No space', trong trường hợp làm việc này thay vì: the_text.translate(string.maketrans(string.punctuation, ' '*len(string.punctuation)))thay thế tất cả các dấu câu với khoảng trắng.
Bakuriu

Rất tiếc, nó thực sự hoạt động, nhưng không phải với chuỗi Unicode.
lizarisk

Câu trả lời:


162

Hãy xem các tùy chọn mã thông báo khác mà nltk cung cấp ở đây . Ví dụ: bạn có thể xác định mã thông báo chọn ra các chuỗi ký tự chữ và số dưới dạng mã thông báo và loại bỏ mọi thứ khác:

from nltk.tokenize import RegexpTokenizer

tokenizer = RegexpTokenizer(r'\w+')
tokenizer.tokenize('Eighty-seven miles to go, yet.  Onward!')

Đầu ra:

['Eighty', 'seven', 'miles', 'to', 'go', 'yet', 'Onward']

55
Lưu ý rằng nếu bạn sử dụng tùy chọn này, bạn sẽ mất các tính năng ngôn ngữ tự nhiên đặc biệt để word_tokenizethích tách các cơn co thắt. Bạn có thể phân chia một cách ngây thơ trên regex \w+mà không cần bất kỳ NLTK nào.
sffc

3
Để minh họa bình luận @sffc, bạn có thể mất các từ như "Mr."
geekazoid

nó thay thế 'không' thành 't' làm thế nào để thoát khỏi điều này?
Md. Ashikur Rahman

46

Bạn không thực sự cần NLTK để xóa dấu câu. Bạn có thể loại bỏ nó với python đơn giản. Đối với chuỗi:

import string
s = '... some string with punctuation ...'
s = s.translate(None, string.punctuation)

Hoặc cho unicode:

import string
translate_table = dict((ord(char), None) for char in string.punctuation)   
s.translate(translate_table)

và sau đó sử dụng chuỗi này trong mã thông báo của bạn.

Mô-đun chuỗi PS có một số bộ phần tử khác có thể được loại bỏ (như chữ số).


3
Xóa tất cả dấu câu bằng biểu thức danh sách cũng hoạt động. a = "*fa,fd.1lk#$" print("".join([w for w in a if w not in string.punctuation]))
Johnny Zhang

32

Mã bên dưới sẽ loại bỏ tất cả các dấu chấm câu cũng như các ký tự không chữ cái. Sao chép từ cuốn sách của họ.

http://www.nltk.org/book/ch01.html

import nltk

s = "I can't do this now, because I'm so tired.  Please give me some time. @ sd  4 232"

words = nltk.word_tokenize(s)

words=[word.lower() for word in words if word.isalpha()]

print(words)

đầu ra

['i', 'ca', 'do', 'this', 'now', 'because', 'i', 'so', 'tired', 'please', 'give', 'me', 'some', 'time', 'sd']

17
Chỉ cần lưu ý rằng sử dụng phương pháp này bạn sẽ mất từ ​​"không" trong các trường hợp như "không thể" hoặc "không", điều đó có thể rất quan trọng để hiểu và phân loại câu. Tốt hơn là sử dụng câu.translate (string.maketrans ("", "",), chars_to_remove), trong đó chars_to_remove có thể là "., ':;!?"
MikeL

3
@MikeL Bạn không thể giải quyết các từ như "không thể" và "không" bằng cách nhập các cơn co thắt và cơn co thắt.fix (câu_here) trước khi kích hoạt. Nó sẽ biến "không thể" thành "không thể" và "không" thành "không".
zipline86

16

Như được chú ý trong các bình luận bắt đầu bằng sent_tokenize (), vì word_tokenize () chỉ hoạt động trên một câu duy nhất. Bạn có thể lọc dấu chấm câu bằng bộ lọc (). Và nếu bạn có một chuỗi unicode, hãy chắc chắn rằng đó là một đối tượng unicode (không phải là một 'str' được mã hóa với một số mã hóa như 'utf-8').

from nltk.tokenize import word_tokenize, sent_tokenize

text = '''It is a blue, small, and extraordinary ball. Like no other'''
tokens = [word for sent in sent_tokenize(text) for word in word_tokenize(sent)]
print filter(lambda word: word not in ',-', tokens)

14
Hầu hết sự phức tạp liên quan đến mã thông báo Penn Treebank phải thực hiện với việc xử lý dấu câu đúng. Tại sao nên sử dụng mã thông báo đắt tiền xử lý dấu chấm câu tốt nếu bạn chỉ loại bỏ dấu chấm câu?
rmalouf

3
word_tokenizelà một hàm trả về [token for sent in sent_tokenize(text, language) for token in _treebank_word_tokenize(sent)]. Vì vậy, tôi nghĩ rằng câu trả lời của bạn đang làm những gì nltk đã làm: sử dụng sent_tokenize()trước khi sử dụng word_tokenize(). Ít nhất đây là cho nltk3.
Kurt Bourbaki

2
@rmalouf vì bạn không cần mã thông báo chỉ chấm câu? Vì vậy, bạn muốn didn'tkhông.
Ciprian Tomoiagă

11

Tôi chỉ sử dụng đoạn mã sau, loại bỏ tất cả các dấu câu:

tokens = nltk.wordpunct_tokenize(raw)

type(tokens)

text = nltk.Text(tokens)

type(text)  

words = [w.lower() for w in text if w.isalpha()]

2
Tại sao chuyển đổi mã thông báo thành văn bản?
Sadik

6

Tôi nghĩ rằng bạn cần một số loại kết hợp biểu thức chính quy (đoạn mã sau có trong Python 3):

import string
import re
import nltk

s = "I can't do this now, because I'm so tired.  Please give me some time."
l = nltk.word_tokenize(s)
ll = [x for x in l if not re.fullmatch('[' + string.punctuation + ']+', x)]
print(l)
print(ll)

Đầu ra:

['I', 'ca', "n't", 'do', 'this', 'now', ',', 'because', 'I', "'m", 'so', 'tired', '.', 'Please', 'give', 'me', 'some', 'time', '.']
['I', 'ca', "n't", 'do', 'this', 'now', 'because', 'I', "'m", 'so', 'tired', 'Please', 'give', 'me', 'some', 'time']

Nên hoạt động tốt trong hầu hết các trường hợp vì nó loại bỏ dấu chấm câu trong khi bảo quản các mã thông báo như "không", không thể lấy được từ các mã thông báo regex như wordpunct_tokenize.


Điều này cũng sẽ loại bỏ những thứ như ...--trong khi bảo tồn các cơn co thắt, điều s.translate(None, string.punctuation)sẽ không xảy ra
CJ Jackson

5

Trân trọng hỏi, một từ là gì? Nếu giả định của bạn là một từ chỉ bao gồm các ký tự chữ cái, thì bạn đã sai vì các từ như can'tsẽ bị hủy thành từng mảnh (chẳng hạn như cant) nếu bạn xóa dấu chấm câu trước khi tokenisation , rất có thể ảnh hưởng tiêu cực đến chương trình của bạn.

Do đó, giải pháp là mã thông báo và sau đó xóa mã thông báo dấu chấm câu .

import string

from nltk.tokenize import word_tokenize

tokens = word_tokenize("I'm a southern salesman.")
# ['I', "'m", 'a', 'southern', 'salesman', '.']

tokens = list(filter(lambda token: token not in string.punctuation, tokens))
# ['I', "'m", 'a', 'southern', 'salesman']

... Và sau đó nếu bạn muốn, bạn có thể thay thế một số mã thông báo như 'mbằng am.


4

Tôi sử dụng mã này để xóa dấu chấm câu:

import nltk
def getTerms(sentences):
    tokens = nltk.word_tokenize(sentences)
    words = [w.lower() for w in tokens if w.isalnum()]
    print tokens
    print words

getTerms("hh, hh3h. wo shi 2 4 A . fdffdf. A&&B ")

Và nếu bạn muốn kiểm tra xem mã thông báo có phải là một từ tiếng Anh hợp lệ hay không, bạn có thể cần PyEnchant

Hướng dẫn:

 import enchant
 d = enchant.Dict("en_US")
 d.check("Hello")
 d.check("Helo")
 d.suggest("Helo")

2
Coi chừng rằng giải pháp này giết chết các cơn co thắt. Đó là bởi vì word_tokenizesử dụng mã thông báo tiêu chuẩn, TreebankWordTokenizerphân tách các cơn co thắt (ví dụ như can't( ca, n't). Tuy nhiên, đó n'tkhông phải là chữ và số và bị mất trong quá trình.
Diego Ferri

1

Xóa dấu chấm câu (Nó sẽ xóa. Cũng như một phần của xử lý dấu câu bằng mã bên dưới)

        tbl = dict.fromkeys(i for i in range(sys.maxunicode) if unicodedata.category(chr(i)).startswith('P'))
        text_string = text_string.translate(tbl) #text_string don't have punctuation
        w = word_tokenize(text_string)  #now tokenize the string 

Đầu vào / đầu ra mẫu:

direct flat in oberoi esquire. 3 bhk 2195 saleable 1330 carpet. rate of 14500 final plus 1% floor rise. tax approx 9% only. flat cost with parking 3.89 cr plus taxes plus possession charger. middle floor. north door. arey and oberoi woods facing. 53% paymemt due. 1% transfer charge with buyer. total cost around 4.20 cr approx plus possession charges. rahul soni

['direct', 'flat', 'oberoi', 'esquire', '3', 'bhk', '2195', 'saleable', '1330', 'carpet', 'rate', '14500', 'final', 'plus', '1', 'floor', 'rise', 'tax', 'approx', '9', 'flat', 'cost', 'parking', '389', 'cr', 'plus', 'taxes', 'plus', 'possession', 'charger', 'middle', 'floor', 'north', 'door', 'arey', 'oberoi', 'woods', 'facing', '53', 'paymemt', 'due', '1', 'transfer', 'charge', 'buyer', 'total', 'cost', 'around', '420', 'cr', 'approx', 'plus', 'possession', 'charges', 'rahul', 'soni']


Cảm ơn bạn rất nhiều

1

Chỉ cần thêm vào giải pháp bằng @rmalouf, điều này sẽ không bao gồm bất kỳ số nào vì \ w + tương đương với [a-zA-Z0-9_]

from nltk.tokenize import RegexpTokenizer
tokenizer = RegexpTokenizer(r'[a-zA-Z]')
tokenizer.tokenize('Eighty-seven miles to go, yet.  Onward!')

Điều này tạo ra một mã thông báo cho mỗi chữ cái.
Rishabh Gupta

1

Bạn có thể làm điều đó trong một dòng mà không cần nltk (python 3.x).

import string
string_text= string_text.translate(str.maketrans('','',string.punctuation))
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.