Kevin

用Perl将一堆email的内容整理到excel中去

0
阅读(2239)
每周都要收到很多系统提示邮件,提示我某某老师在系统中进行了捐赠申请或者提出了问题。 装了个google desktop, 基本上可以不访问数据库就能解决不少老师的捐赠查询问题。

但是,如果需要更多的组合信息,就需要将数百个email内容,根据关键词,进行信息整理,导出到 excel表格中去,方便查找和管理。 

以前我用gawk这种比较原始的语言干过类似的事,最近有空,研究了一下如何用perl做。 

为简单起见和保持可移植性,没有引入复杂的操作,而是直接用文本操作搞定。 

过程如下:
1.在windows下建立perl环境
1.1安装ActivePerl
1.2安装集成环境Perl Express

2.把数百个email打包为一个email. 
同时选中所有关心的email, 转发,这样所有的email就作为附件存在一个汇总的email里了。 然后,将此email另存为msg格式。 

3.用Perl处理

采用Text::CSV_XS包进行CSV格式的文件处理,得到excel认识的CSV文件. 

将总email文件强行当作文本文件打开, 由于email里面我关心的信息,目前用=分隔,比如lastname=xie, 因此,new了一个用“=”做分隔符的CSV类。 有些我关心的信息用“:”做分隔符,因此new了一个用“:”做分隔符的CSV类, 另外,输出文件格式是标准的用逗号为分隔符的CSV,因此new了一个不带参数缺省的类。 

然后生成表头,扫描整个文件,碰见lastname= firstname= 之类的关键词,放到相应的地方。 碰见自由书写的地方,用正则表达式匹配,翻译成统一的表达方式,把email信头中的时间格式裁剪转换为excel表格认识的日期格式。

生成的outputfile.csv可以拷贝到 xls文件中进一步处理。

4.遇到的问题
4.1 Text::CSV_XS和Text::CSV
最初抄的例程用的是Text::CSV,在ActivePerl默认的安装中并没有,取而代之的是编 译版本的Text::CSV_XS,实践证明,Text::CSV_XS比Text::CSV快将近10倍。 
4.2 Perl Express 的路径设置
一开始用Perl Express跑程序,无法打开本地目录的测试msg文件,原因是需要在Perl Express菜单中设置工作路径,Perl->excution directory->select 中,设置工作路径即可。 

5.讨论
5.1 Perl还有很多更复杂的包,可以处 理email,excel等,也可以用,只不过,用简单的Text::CSV搞定,性能也很好,目前俺就不深入了。 
5.2 

以下是代码:

#!/usr/bin/perl

use strict;
use warnings;
use Text::CSV_XS;

my $NUMBER=0;
my $REQDATE=1;
my $SCHOOL=2;
my $PROF=3;
my $EMAIL=4;
my $REQUEST=5;

my $csv_emailheader = Text::CSV_XS->new({'sep_char'    => ':'
                     });

my $csv = Text::CSV_XS->new({'sep_char'    => '='
                     });

my $outcsv = Text::CSV_XS->new();

my $infile = 'chinaapprovals.msg';
system("dir");
open (INFD, "<", $infile) or die $!;

my $outfile='outputfile.csv';
open (OUTFD, ">", $outfile) or die $!;

my @array;
my $id=1;

$array[$NUMBER]='number';
$array[$REQDATE]='req date';
$array[$SCHOOL]='school';
$array[$PROF]='prof';
$array[$EMAIL]='email';
$array[$REQUEST]='request';

$outcsv->combine(@array);
print OUTFD $outcsv->string()."\n";

my @columns;

while (<INFD>) {
      if ($csv->parse($_)) {
        @columns = $csv->fields();

        if($columns[0] =~ /^ firstname $/){
           $array[$PROF]=$columns[1];
        }
        if($columns[0] =~ /^ lastname $/){
           $array[$PROF]=$array[$PROF].$columns[1];
        }
        if($columns[0] =~ /^ email $/){
           $array[$EMAIL]=$columns[1];
        }
        if($columns[0] =~ /^ company $/){
           $array[$SCHOOL]=$columns[1];
        }
        if($columns[0] =~ /^ req_software $/){
           if ($columns[1] =~ /No softwareI/)
           {
               $array[$REQUEST]="";
           }else{
               $array[$REQUEST]="SW".$columns[1];
           }
        }
        if($columns[0] =~ /^ software_qty $/){
           if ($columns[1] =~ /[0-9]+/)
           {
             $array[$REQUEST]=$array[$REQUEST].$columns[1]."Lc";
           }
        }
        if($columns[0] =~ /^ req_board $/){
           if ($columns[1] =~ /No boards/){
             $array[$REQUEST]=$array[$REQUEST]."";
           }else{
            if ($columns[1] =~ /Digilent S3E/){
             $array[$REQUEST]=$array[$REQUEST]." S3E ";
           }else{
             $array[$REQUEST]=$array[$REQUEST]."";
           }
           }
        }
        if($columns[0] =~ /^ board_qty $/){
             if($columns[1] =! /"How Many Boards"/){
             $array[$REQUEST]=$array[$REQUEST].$columns[1]."pcs";
             }
        }
        if($columns[0] =~ /^ other_products $/){

           $array[$REQUEST]=$array[$REQUEST]." ".$columns[1];
        }
        if($columns[0] =~ /^ Comments $/){
           $array[$REQUEST]=$array[$REQUEST]." ".$columns[1];
        }
      }
      if($csv_emailheader->parse($_)) {
         @columns = $csv_emailheader->fields();
         if($columns[0] =~ /X-OriginalArrivalTime/){
            $array[$REQDATE]= $columns[1];
            $array[$REQDATE]=~ s/..$//;
            $array[$REQDATE]=~ s/ /-/;
            $array[$REQDATE]=~ s/^-//;
            $array[$REQDATE]=~ s/-$//;
            $array[$NUMBER]=$id++;
            $outcsv->combine(@array);
            print OUTFD $outcsv->string()."\n";
         }
      }
}
close INFD;
close OUTFD;
print "done\n";