使用python分析文本字符串中的bigrams

时间:2016-11-28 16:47:55

标签: python cryptography n-gram frequency-analysis vigenere

我正在尝试使用python来帮助我破解Vigenère密码。我对编程很新,但我已经设法制作了一个算法来分析一串文本中的二元组频率。这就是我到目前为止所做的:

import nltk, string
from nltk import bigrams

Ciphertext = str(input("What is the text to be analysed?"))

#Removes spacing and punctuation to make the text easier to analyse
def Remove_Formatting(str):
    str = str.upper()
    str = str.strip()
    str = str.replace(' ','')
    str = str.translate(str.maketrans({a:None for a in string.punctuation}))
    return str

Ciphertext = Remove_Formatting(Ciphertext)

#Score is meant to increase if most common bigrams are in the text
def Bigram(str):
    Common_Bigrams = ['TH',        'EN',        'NG',
                      'HE',        'AT',        'AL',
                      'IN',        'ED',        'IT',
                      'ER',        'ND',        'AS',
                      'AN',        'TO',        'IS',
                      'RE',        'OR',        'HA',
                      'ES',        'EA',        'ET',
                      'ON',        'TI',        'SE',
                      'ST',        'AR',        'OU',
                      'NT',        'TE',        'OF']
    Bigram_score = int(0)
    for bigram in str:
        if bigram in Common_Bigrams:
            Bigram_score += 1
            return Bigram_score

Bigram(Ciphertext)

print (Bigram_score)

然而,当我尝试使用文本运行时,我收到此错误:

Traceback (most recent call last):
  File "C:/Users/Tony/Desktop/Bigrams.py", line 36, in <module>
    print (Bigram_score)
NameError: name 'Bigram_score' is not defined

这是什么意思?我以为我已经将Bigram_score定义为一个变量,并且我已经尝试了所有内容,但它仍然以这种方式返回错误。我做错了什么?请帮忙......

提前致谢,

1 个答案:

答案 0 :(得分:1)

您可以将Bigram_score设为全局,如下所示:

def Bigram(string): # don't override str
    global Bigram_score
    Common_Bigrams = ['TH',        'EN',        'NG',
                      'HE',        'AT',        'AL',
                      'IN',        'ED',        'IT',
                      'ER',        'ND',        'AS',
                      'AN',        'TO',        'IS',
                      'RE',        'OR',        'HA',
                      'ES',        'EA',        'ET',
                      'ON',        'TI',        'SE',
                      'ST',        'AR',        'OU',
                      'NT',        'TE',        'OF']
    Bigram_score = 0 # that 0 is an integer is implicitly understood
    for bigram in string:
        if bigram in Common_Bigrams:
            Bigram_score += 1
            return Bigram_score

您还可以将Bigram函数的返回结果绑定到变量,如下所示:

Bigram_score = Bigram(Ciphertext)

print(Bigram_score)

或:

print(Bigram(Ciphertext))

为函数中的变量赋值时,它们是本地的并绑定到该函数。如果函数返回任何内容,则返回的值必须绑定到变量才能正确重用(或直接使用)。

这是一个如何运作的例子:

spam = "spam" # global spam variable

def change_spam():
    spam = "ham" # setting the local spam variable
    return spam

change_spam()
print(spam) # prints spam

spam = change_spam() # here we assign the returned value to global spam
print(spam) # prints ham

此外,你的for循环遍历unigrams而不是bigrams。让我们仔细看看:

for x in "hellothere":
    print(x)

这将打印unigrams。因此,我们在代码中重命名bigram变量,以查看存在某些逻辑问题的位置。

for unigram in string:
    if unigram in Common_Bigrams:
        print("bigram hit!")

由于没有与任何双字母相同的unigrams,"bigram hit!"永远不会打印出来。我们可以尝试使用不同的方法来获取bigrams,使用while循环和索引号。

index = 0
n = 2 # for bigrams
while index < len(string)-(n-1): # minus the length of n-1 (n-grams)
    ngram = string[index:index+n] # collect ngram
    index += 1 # important to add this, otherwise the loop is eternal!
    print(ngram)

接下来,只需在循环中包含你想用bigram做什么。