Como posso agrupar e-mails por domínio, combinados e resumidos de todos os arquivos em um diretório?

3

Eu tenho alguns arquivos CSV. Cada arquivo tem uma lista de endereços de email. A seguir, os dados extraídos do arquivo:

%%%%%%%%%%@yahoo.com
%%%%%%@wanadoo.fr
%%%%[email protected]
%%nameemail%%@yahoo.com
%[email protected]
%1%[email protected]
%[email protected]

O que estou tentando tentar é extrair domínios desses endereços de e-mail e, em seguida, organizar os endereços de e-mail de maneira que os e-mails associados a um determinado domínio sejam listados juntos. Por exemplo:

yahoo.com,%%%%%%%%%%@yahoo.com
wanadoo.fr,%%%%%%@wanadoo.fr
yahoo.comravi,%%%%[email protected]
yahoo.com,%%nameemail%%@yahoo.com
numberland.com,%[email protected]
example.com,%1%[email protected]
example.com,%[email protected]

A saída final que estou tentando adquirir é como a seguinte:

yahoo.com,%%%%%%%%%%@yahoo.com,%%nameemail%%@yahoo.com
wanadoo.fr,%%%%%%@wanadoo.fr
yahoo.comravi,%%%%[email protected]
numberland.com,%[email protected]
example.com,%1%[email protected],%[email protected]
    
por Jaffer Wilson 25.01.2017 / 08:32

3 respostas

6

Uma maneira em python, usando itertools ' groupby() :

1. Escrever saída por arquivo (de todos os arquivos em um diretório) no terminal

N.B. Lembre-se de que o terminal mostra um número limitado de linhas

#!/usr/bin/env python3
from operator import itemgetter
from itertools import groupby
import os
import sys

dr = sys.argv[1]

for f in os.listdir(dr):
    lines = [[l.strip(), l.split("@")[-1].strip()] for l in \
             open(os.path.join(dr, f)).readlines()]
    lines.sort(key=itemgetter(1))
    for item, occurrence in groupby(lines, itemgetter(1)):
        func = [s[0] for s in list(occurrence)]; print(item+","+",".join(func))

Para usar

  1. Copie o script em um arquivo vazio, salve-o como group_domains.py
  2. Execute-o com o diretório de destino como argumento:

    python3 /path/to/group_domains.py /directory/with/files
    

A saída será como:

example.com,%1%[email protected],%[email protected]
numberland.com,%[email protected]
wanadoo.fr,%%%%%%@wanadoo.fr
yahoo.com,%%%%%%%%%%@yahoo.com,%%nameemail%%@yahoo.com
yahoo.comravi,%%%%[email protected]

Notas

Como está, o script cria uma saída por arquivo no terminal. Poderíamos facilmente combinar (resumir) a (s) saída (s) dos arquivos separados, e subsequentemente escrever o resultado agrupado em um arquivo etc., mas por favor mencione.

Explicação

No conceito:

  1. As linhas do arquivo são lidas e divididas por "@" para ler o domínio
  2. A lista criada é subsequentemente classificada por domínio:

    lines.sort(key=itemgetter(1))
    
  3. e agrupados por domínio:

    groupby(lines, itemgetter(1))
    

O resultado (linha) é feito do item (domínio) e seus "membros".

2. Escrever relatório por arquivo (novamente de todos os arquivos em um diretório) em arquivos renomeados.

O script abaixo irá escrever a saída em um arquivo renomeado, o uso é o mesmo:

#!/usr/bin/env python3
from operator import itemgetter
from itertools import groupby
import os
import sys

dr = sys.argv[1]


for f in os.listdir(dr):
    write = []
    file = os.path.join(dr, f)
    lines = [[l.strip(), l.split("@")[-1].strip()] for l in open(file).readlines()]
    lines.sort(key=itemgetter(1))
    for item, occurrence in groupby(lines, itemgetter(1)):
        func = [s[0] for s in list(occurrence)]
        write.append(item+","+",".join(func))
    open(os.path.join(dr, "grouped_"+f), "wt").write("\n".join(write))

de um arquivo como:

some_list.txt

ele criará um renomeado:

grouped_some_list.txt

Para usar

simplesmente:

python3 /path/to/group_domains.py /directory/with/files

3. Escreva um relatório (resumo) em todo o diretório em um único arquivo

A versão abaixo resumirá todos os domínios dentro dos arquivos em um diretório. O relatório é salvo em um arquivo, para definir como segundo argumento.

#!/usr/bin/env python3
from operator import itemgetter
from itertools import groupby, chain
import os
import sys

dr = sys.argv[1]
outfile = sys.argv[2]

report = []

for f in os.listdir(dr):
    lines = [[l.strip(), l.split("@")[-1].strip()] for l in \
             open(os.path.join(dr, f)).readlines()]
    lines.sort(key=itemgetter(1))
    for item, occurrence in groupby(lines, itemgetter(1)):
        func = [s[0] for s in list(occurrence)]
        report.append([item, func])

report.sort(key=itemgetter(0))

with open(outfile, "wt") as out:
    for item, occurrence in groupby(report, itemgetter(0)):
        func = [item for sublist in [it[1] for it in list(occurrence)] for item in sublist]
        out.write(item+","+",".join(func)+"\n")

Para usar

  1. Copie o script em um arquivo emty
  2. Execute:

    python3 /path/to/group_domains.py /directory/with/files /path/to/outputfile.txt
    

    (ou qualquer extensão)

Notas

A última versão irá primeiro resumir por arquivo , como mencionado na pergunta, e adicionalmente resumir todos os arquivos em um arquivo de saída, onde domínios semelhantes dos arquivos separados serão combinados em uma linha por domínio.

    
por Jacob Vlijm 25.01.2017 / 09:15
5

Aqui está uma versão perl , usando um hash de matrizes anônimas:

$ perl -F@ -alne '
    push @{ $h{$F[1]} }, $_ }{ 
    for $k (reverse sort keys %h) {print join ",", $k, @{ $h{$k} }
  }' emails.csv
yahoo.comravi,%%%%[email protected]
yahoo.com,%%%%%%%%%%@yahoo.com,%%nameemail%%@yahoo.com
wanadoo.fr,%%%%%%@wanadoo.fr
numberland.com,%[email protected]
example.com,%1%[email protected],%[email protected]

O pedido não é exatamente o que você pediu

    
por steeldriver 25.01.2017 / 10:25
2

Usando awk :

awk -F, '{a[] = a[]","} END {for (i in a) print i a[i]}'

A saída não está em nenhuma ordem específica:

$ awk -F, '{a[] = a[]","} END {for (i in a) print i a[i]}' foo
yahoo.comravi,%%%%[email protected]
yahoo.com,%%%%%%%%%%@yahoo.com,%%nameemail%%@yahoo.com
numberland.com,%[email protected]
example.com,%1%[email protected],%[email protected]
wanadoo.fr,%%%%%%@wanadoo.fr
    
por muru 25.01.2017 / 11:59