2017-02-07 28 views
1

Я извлек триграммы из кучи файлов HTML, следуя определенному шаблону. Когда я их печатаю, я получаю список списков (где каждая строка - триграмма). Я хотел бы распечатать его в outfile для дальнейшего анализа текста, но когда я его пробую, он печатает только первые триграммы. Как я могу напечатать все триграммы в outfile? (Список списка из трехграмм). В идеале я хотел бы объединить все триграммы в один список, вместо того, чтобы иметь несколько списков с одной трехграммой. Ваша помощь будет высоко оценена.Запись фильтрованных ngrams в outfile - список списков

Мой код выглядит следующим образом до сих пор:

from nltk import sent_tokenize, word_tokenize 
from nltk import ngrams 
from bs4 import BeautifulSoup 
from string import punctuation 
import glob 
import sys 
punctuation_set = set(punctuation) 

# Open and read file 
text = glob.glob('C:/Users/dell/Desktop/python-for-text-analysis-master/Notebooks/TEXTS/*') 
for filename in text: 
with open(filename, encoding='ISO-8859-1', errors="ignore") as f: 
    mytext = f.read() 

# Extract text from HTML using BeautifulSoup 
soup = BeautifulSoup(mytext, "lxml") 
extracted_text = soup.getText() 
extracted_text = extracted_text.replace('\n', '') 

# Split the text in sentences (using the NLTK sentence splitter) 
sentences = sent_tokenize(extracted_text) 

# Create list of tokens with their POS tags (after pre-processing: punctuation removal, tokenization, POS tagging) 
all_tokens = [] 

for sent in sentences: 
    sent = "".join([char for char in sent if not char in punctuation_set]) # remove punctuation from sentence (optional; comment out if necessary) 
    tokenized_sent = word_tokenize(sent) # split sentence into tokens (using NLTK word tokenization) 
    all_tokens.extend(tokenized_sent) # add tagged tokens to list 

n=3 
threegrams = ngrams(all_tokens, n) 


# Find ngrams with specific pattern 
for (first, second, third) in threegrams: 
    if first == "a": 
     if second.endswith("bb") and second.startswith("leg"): 
      print(first, second, third) 

ответ

0

Во-первых, удаление знаков препинания может быть проще, см Removing a list of characters in string

>>> from string import punctuation 
>>> text = "The lazy bird's flew, over the rainbow. We'll not have known." 
>>> text.translate(None, punctuation) 
'The lazy birds flew over the rainbow Well not have known' 

Но это не совсем правильно удалить пунктуация, прежде чем делать лексемизацию , вы видите, что We'll ->Well, что я считаю нежелательным.

Возможно, это лучший подход:

>>> from nltk import sent_tokenize, word_tokenize 
>>> [[word for word in word_tokenize(sent) if word not in punctuation] for sent in sent_tokenize(text)] 
[['The', 'lazy', 'bird', "'s", 'flew', 'over', 'the', 'rainbow'], ['We', "'ll", 'not', 'have', 'known']] 

Но обратите внимание, что идиома выше не обрабатывает несколько символов пунктуации.

E.g. Мы видим, что что word_tokenize() меняет " -> ``, и используя идиомы выше она не устранила его:

>>> sent = 'He said, "There is no room for room"' 
>>> word_tokenize(sent) 
['He', 'said', ',', '``', 'There', 'is', 'no', 'room', 'for', 'room', "''"] 
>>> [word for word in word_tokenize(sent) if word not in punctuation] 
['He', 'said', '``', 'There', 'is', 'no', 'room', 'for', 'room', "''"] 

Чтобы справиться с этим, явно сделать punctuation в список и добавить пунктуацию в нескольких символов к нему:

>>> sent = 'He said, "There is no room for room"' 
>>> punctuation 
'!"#$%&\'()*+,-./:;<=>[email protected][\\]^_`{|}~' 
>>> list(punctuation) 
['!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~'] 
>>> list(punctuation) + ['...', '``', "''"] 
['!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~', '...', '``', "''"] 
>>> p = list(punctuation) + ['...', '``', "''"] 
>>> [word for word in word_tokenize(sent) if word not in p] 
['He', 'said', 'There', 'is', 'no', 'room', 'for', 'room'] 

что касается получения потока документа (как вы назвали его all_tokens), вот отличный способ, чтобы получить его:

>>> from collections import Counter 
>>> from nltk import sent_tokenize, word_tokenize 
>>> from string import punctuation 
>>> p = list(punctuation) + ['...', '``', "''"] 
>>> text = "The lazy bird's flew, over the rainbow. We'll not have known." 
>>> [[word for word in word_tokenize(sent) if word not in p] for sent in sent_tokenize(text)] 
[['The', 'lazy', 'bird', "'s", 'flew', 'over', 'the', 'rainbow'], ['We', "'ll", 'not', 'have', 'known']] 

И теперь к части вашего фактического вопроса.

Что вам действительно нужно, это не проверка строки в ngrams, скорее, вам следует рассмотреть соответствие шаблона регулярного выражения.

Вы хотите, чтобы найти нужный шаблон \ba\b\s\bleg[\w]+bb\b\s\b[\w]+\b см https://regex101.com/r/zBVgp4/4

>>> import re 
>>> re.findall(r"\ba\b\s\bleg[\w]+bb\b\s\b[\w]+\b", "This is a legobatmanbb cave hahaha") 
['a legobatmanbb cave'] 
>>> re.findall(r"\ba\b\s\bleg[\w]+bb\b\s\b[\w]+\b", "This isa legobatmanbb cave hahaha") 
[] 

Теперь записать строку в файл, вы можете использовать эту идиому, см https://docs.python.org/3/whatsnew/3.0.html#print-is-a-function:

with open('filename.txt', 'w') as fout: 
    print('Hello World', end='\n', file=fout) 

В факт, если вас интересуют только ngrams без токенов, нет необходимости фильтровать или маркировать текст; P

Вы можете просто код для этого:

soup = BeautifulSoup(mytext, "lxml") 
extracted_text = soup.getText() 
pattern = r"\ba\b\s\bleg[\w]+bb\b\s\b[\w]+\b" 

with open('filename.txt', 'w') as fout: 
    for interesting_ngram in re.findall(pattern, extracted_text): 
     print(interesting_ngram, end='\n', file=fout) 
+0

Большое спасибо. Я получил соответствие шаблону регулярного выражения, но я все еще не могу распечатать его в текстовом файле. Точно так же печатает первую строку, к сожалению. Как вы могли подозревать, что я совершенно новый, поэтому я могу сделать что-то не так ... – Lee

+0

Вы используете фрагмент кода в ответе? Или все еще используете ваши? Что такое входной файл, вы можете поделиться им? И каков ожидаемый результат? – alvas

+0

Проверьте свои отступы. Удалите весь код и затем начните проверку с итерации файла, например. распечатайте контент по строкам. Часть кода НЛП должна быть в порядке. – alvas