Извлечение писем с помощью NLP - Spacy Matcher, а затем их шифрование и дешифрование - PullRequest
0 голосов
/ 16 июня 2020

Изображение файла csv У меня есть файл csv, который выглядит как предоставленное изображение. Я читаю файл csv, определяю шаблон и использую spacy Matcher. Я просматриваю строки и столбцы файла CSV. Моя конечная цель - определить идентификаторы электронной почты и номера SSN как конфиденциальную информацию, а также зашифровать и расшифровать их. Но, к сожалению, вся информация в процессе шифруется и расшифровывается.

import spacy
from spacy.matcher import Matcher
import csv
from cryptography.fernet import Fernet
from spacy.vocab import Vocab
from spacy.tokens import Span
from spacy import displacy
nlp = spacy.load('en_core_web_sm')
# pattern = [{"TEXT": {"REGEX": "[a-zA-z0-9-_.] +@[a-zA-z0-9-_.]+"}, "OP":"?"}]
pattern =[{"TEXT": {"REGEX": "[a-z0-9\.\-+_] +@[a-z0-9\.\-+_]+\.[a-z]+"}, "OP":"?"}]
matcher = Matcher(nlp.vocab)
matcher.add("Email", None, pattern)
some_list = []
count = 0

file = open("PIIsampleData.csv")
csv_file = csv.reader(file)
for row in csv_file:
    # print(row)
    for text in row:
        doc = nlp(text)
        # print(doc.ents)
        matches = matcher(doc)
        print(matches)

        ent = [(ent.text,ent.label_) for ent in doc.ents]
        for match_id, start, end in matches:
            span = doc[start:end]
            print(span)
            # print(span.text)
            # print(span.text)[Here is the image of csv file][1]
        #     entity = [(ent.text, ent.label_) for ent in doc.ents]
        if ent:
            some_dict = {}
            b = bytes(doc.text, 'utf-8')
            name = Fernet.generate_key()
            lock = Fernet(name)
            code = lock.encrypt(b)
            original = lock.decrypt(code)
            # print(code, original, doc.text)
            some_dict = {'code': code, 'original': original, 'label': ent}
            some_list.append(some_dict)
            # print(some_list)
            count = count + 1

Я думаю, что здесь чего-то не хватает, не уверен, что это EntityRuler или что-то еще, или какая-то проблема с моим кодом.

for match_id, start, end in matches:
            span = doc[start:end]
            print(span)
This span is coming as blank. Ideally this should have fetched me the emails, right? 
The final output when i am printing some_list is all the columns encrypted and decrypted, where as i want only emails and SSN to be identified as sensitive information and encrypted. I know i haven't defined regex for SSN yet, so just help me with emails for now. 

CSV

Employee Name,Employee Email,Phone,Personal number,Organisation number,SSN
Price Cummings,lectus.Nullam@tristique.ca,1-509-928-5746,0,364858-2678,795-63-3325
McKenzie G. Rios,ullamcorper.Duis@sempertellus.ca,1-118-309-0368,16680213 -6611,208206-7964,183-91-0062
Scarlet Estrada,ornare@dolorFuscemi.net,163-5585,16330216 -1611,727359-3280,739-89-4031
Virginia Knowles,lorem@dui.co.uk,874-2186,16691013 -3450,497114-4243,382-62-1298
Reed S. Pennington,nunc@Phasellusataugue.edu,358-0513,16930326 -4221,724596-5152,190-00-3181
Mona Nelson,pellentesque.Sed.dictum@luctus.com,1-681-841-0005,16750725 -6951,028041-2412,943-18-8562

1 Ответ

0 голосов
/ 17 июня 2020

Должен сказать, я не понимаю, почему вы используете spacy для сопоставления вещей, которые вы указываете как регулярное выражение, которое может быть сопоставлено с тем же успехом и проще с помощью обычных регулярных выражений.

У меня есть это хотя бы указание адреса электронной почты, который необходимо зашифровать - я уверен, что вы сможете сделать все остальное.

Мне пришлось изменить ваше регулярное выражение, чтобы оно действительно соответствовало адресу электронной почты. В частности, в вашем регулярном выражении было +@, что похоже на способ не соответствовать адресу электронной почты, поскольку они не включают пробел перед @. Я изменил это на *@, но этого места, вероятно, не должно быть. Также бит перед пробелом не имел + после него. И я упростил бит после @, я уверен, вы сможете разобраться.

Также мне пришлось специально пропустить строку заголовка CSV.

Вы не были фактически обнаруживая совпадение, поэтому вы все зашифровываете - этот код обнаруживает непустое значение span как требующее шифрования. Вам придется обработать, если в совпадении есть несколько span.

Python 3.8.3 код (вам придется отредактировать операторы print(), где они используют новый f "{ value =} "синтаксис)

import spacy
from spacy.matcher import Matcher
import csv
from cryptography.fernet import Fernet
# UNUSED from spacy.vocab import Vocab
# UNUSED from spacy.tokens import Span
#UNUSED from spacy import displacy

nlp = spacy.load('en_core_web_sm')

# doesn't work pattern =[{"TEXT": {"REGEX": "[a-z0-9\.\-+_] +@[a-z0-9\.\-+_]+\.[a-z]+"}, "OP":"?"}]
pattern =[{"TEXT": {"REGEX": "[a-z0-9\.\-+_]+ *@[a-z0-9\.\-+_]+"}, "OP":"?"}]
matcher = Matcher(nlp.vocab)
matcher.add("Email", None, pattern)
some_list = []
count = 0

file = open("ex1.csv")
csv_file = csv.reader(file)
first=True
for row in csv_file:
    # skip the header row
    if first:
        first=False
        continue
    print( f"{row=}" )
    for text in row:
        print( "===============================" )
        print( f"{text=}" )
        doc = nlp(text)
        print(f"{doc=}" )
        print(f"{doc.ents=}" )
        matches = matcher(doc)
        print(f"{matches=}")

        encrypted=False
        for match_id, start, end in matches:
            span = doc[start:end]
            print(f"Match {match_id=} span {start=} {end=} {span=}")
            if span:
                print( f"ENCRYPT '{span}'" )
                encrypted=True
        if encrypted:
            # do something with the encrypted value
            pass
        else:
            print( f"NOT ENCYRPTED {text}" )
            # do something with the non-encrypted value
            pass

Но это было бы намного менее сложно (и, следовательно, легче реализовать), просто используя обычные регулярные выражения. Например, это соответствует адресам электронной почты или SSN (перед SSN не должно стоять di git):

import csv
import re

emailpattern = r"([a-z0-9\.\-+_]+ *@[a-z0-9\.\-+_]+)"
emailorssnpattern=r"([a-z0-9\.\-+_]+ *@[a-z0-9\.\-+_]+|(?<!\d)\d{3}-\d{2}-\d{4}(?!\d))"

some_list = []
count = 0

file = open("ex1.csv")
csv_file = csv.reader(file)
first=True
for row in csv_file:
    # skip the header row
    if first:
        first=False
        continue
    print( f"{row=}" )
    for text in row:
        print( "===============================" )
        print( f"{text=}" )
        match = re.findall(emailorssnpattern,text)
        print( "match=",match )
        if match:
            print( f"ENCRYPT {text}" )
        else:
            print( f"NO NEED TO ENCRYPT {text}" )

Удачи!

...