【用python搞个大新闻】尝试分析wikileaks泄露的民主党邮件--信息提取、入库

技术博客 / 开发   2016-08-02 20:07:07  阅读量: 5346
  数据挖掘   造轮子   Python  

上周wikileaks搞了个大新闻,泄露了20000多封民主党高层的往来邮件,被民主党搞得很惨的阿桑奇算是出了一口恶气。

作为一名自称技术宅的菜鸟程序员,看到这些邮件自然想分析一把,看看能不能挖出一些有意思的信息,于是想尝试对这些邮件进行数据分析,目前已经用python的email模块完成了对邮件内容的提取和入库工作,后续将不定期开展数据挖掘和可视化的尝试,看看能不能找出一些有意思的信息。

wikileaks也算是业界良心,这种邮件挂在网上,url还非常规律,要下下来一个shell脚本搞定:

for i in `seq 1 30000`
    do
    wget https://wikileaks.org/dnc-emails//get/$i
done

国内服务器比较慢,建议放在主机在国外的vps上跑,然后再弄到本地。

最后看下来总共22456封邮件。

要分析邮件,首先开始要从邮件中提取出有效的邮件内容,一般来说,邮件有用的信息估计有如下几个:

  1. 发件人

  2. 收件人

  3. 抄送

  4. 时间

  5. 主题

  6. 正文

  7. 附件


对于从wikileaks上弄下来的邮件,大致内容是这样的:

查阅资料,可以前面部分叫邮件头,里边包含主题、发件人、收件人、抄送、时间戳、传输协议等信息。

正文有两种形式,一种是text/plain,纯文本形式,一种是text/html,html形式,可以定义css样式,如果有附件的话,一般是base64形式传输。

所以,要分析邮件,就需要弄出邮件头、正文和附件中的内容。

由于自己对python还算熟悉,然后看到python里有专门的email模块,不用再重复造轮子,就选择用python来分析邮件,此外,为了数据持久化,还得将分析提取出的数据入库,在家里数据库只能用mysql,所以还需要用MySQLdb连接python和mysql。因此引入两个模块,对于邮件中读取的信息,email模块可以直接生成一个email对象,对于每一个邮件,可以如下处理:

import email
import MySQLdb

fp = open(email_file, "r")
msg = email.message_from_file(fp)

分析邮件头

下面分析邮件头,对于邮件头,要提取主题,发件人,收件人,抄送,时间戳等信息,email模块可以比较轻松做到这点,定义如下几个函数提取这些信息:

def get_subject(msg): #提取主题
	subject = msg.get("subject") 
	h = email.Header.Header(subject)
	dh = email.Header.decode_header(h)
	subject = dh[0][0]
	return subject

def get_from(msg): #提取发件人
	return email.utils.parseaddr(msg.get("from"))[1]
	

def get_to(msg): #提取收件人
	list_to = []
	to_list = email.utils.getaddresses(msg.get_all("to", []))
	for i in range(0,len(to_list)):
		list_to.append(to_list[i][1])
	return list_to

def get_CC(msg): #提取抄送
	list_CC=[]
	CC_list = email.utils.getaddresses(msg.get_all("CC", []))
	for i in range(0,len(CC_list)):
		list_CC.append(CC_list[i][1])
	return list_CC

def get_timestamp(msg): #提取时间戳
	return email.utils.parseaddr(msg.get_all("date", []))[1]

其中收件人和抄送由于可能不止一个人,所以需要全部提取返回一个链表。

分析正文和附件

正文和附件前面提到,正文可能是text/plain或者text/html的,一般邮件中两种形式都存在,用作数据分析一般text/plain的足够,附件都是base64编码的,需要对其进行译码,写一个函数来提取正文和附件:

def get_content(msg,i):
	attachments=[]
	dic_content={}
	attachments_dir="/home/wiki/attachments/"
	for par in msg.walk():
		if not par.is_multipart():
			name1 = par.get_param("name") #获取附件名
			if name1:
				h = email.Header.Header(name1)
				dh = email.Header.decode_header(h)
				fname = dh[0][0]
				attachments.append(fname)
				data = par.get_payload(decode=True) #对附件base64进行译码,解析出附件数据
				try:
					file=attachments_dir+i+"_"+fname
					f = open(file, 'wb') 
				except:
					print 'ileagel'
					f = open('aaaa', 'wb')
				f.write(data)  #将附件还原成文件
				f.close()
			else:
				contents = par.get_payload(decode=True)
				if contents.find('</html>')<0 and contents.find('<meta')<0:  #获取text/plain格式的邮件正文
					dic_content["contents"] = contents
	dic_content["attachments"] = attachments
	return dic_content

附件名存在一个链表中,然后附件名和正文生成一个字典返回,最为重要的是,可以直接解析出附件内容,还原出附件文件!

由此,便完成邮件数据解析,下面测试一下,尝试解析编号8767邮件,使用上面的函数跑一遍,结果如下:

subject: Fwd: NC Press Call
++++++++++++++++++++++++++++++++++++++++++++++++++
from: JeffersonD@dnc.org
++++++++++++++++++++++++++++++++++++++++++++++++++
to: ['MirandaL@dnc.org', 'PaustenbachM@dnc.org', 'WalshT@dnc.org', 'WalkerE@dnc.org']
++++++++++++++++++++++++++++++++++++++++++++++++++
CC: []
++++++++++++++++++++++++++++++++++++++++++++++++++
Tue, 26 Apr 2016 15:55:11 -0700
++++++++++++++++++++++++++++++++++++++++++++++++++


Sent from my iPhone

Begin forwarded message:

From: Pratt Wiley <WileyP@dnc.org<mailto:WileyP@dnc.org>>
Date: April 26, 2016 at 6:37:39 PM EDT
To: "Jefferson, Deshundra" <JeffersonD@dnc.org<mailto:JeffersonD@dnc.org>>, "Walker, Eric" <WalkerE@dnc.org<mailto:WalkerE@dnc.org>>
Subject: RE: NC Press Call

Here is the draft of my comments.  Deshundra has seen most of this (I added back the contrast between our litigation priorities from today�s statement).

What we�re witnessing in North Carolina is hardly unique to that state. Republican-controlled legislatures, particularly in presidential battlegrounds, are passing laws that target women, students, the elderly, and people of color. These voters represent the Democrat�s core constituency, and the majority of Americans.

It�s not hard to see that this is a part of a cynical political ploy to boast the Republican�s electoral success this fall.

Earlier this month, students at the Marquette University polling station faced two hour wait times to vote. Many still stood in line well after the polls official closed and the race was called. At the same time, a Republican Wisconsin Congressman bragged to reporters that the state�s restrictive photo ID law would help the GOP defeat Democrats.

In Texas, Senator Ted Cruz recently filed an amicus brief in support of Texas� restrictive photo ID law. Cruz wears his opposition to voting rights as a badge of honor. In 2012, he voiced his opposition to a key provision of the landmark Voting Rights Act of 1965. He also led the fight as Texas Solicitor General to limit voter registration efforts in communities of color, vigorously defending a discriminatory law against a civil rights lawsuit.

And we all remember just four years ago when the Pennsylvania Republican House Leader announced that the state�s restrictive photo ID law was �gonna allow Governor Romney to win the State of Pennsylvania.�

While Democrats have gone to court in Arizona to reverse the culture of discrimination and disenfranchisement, Republicans are going to court to defend laws designed to decrease voter turnout � because that is their only path to victory.

As mentioned by our distinguished speakers, the DNC and Democrats across the nation will not waver in defending the right to vote � the most fundamental of all of our rights.   And we support efforts like those the voting rights activists in North Carolina who plan to file an appeal in the Circuit Courts to overturn H.B. 589.



-          Pratt asks for any questions -


From: Jefferson, Deshundra
Sent: Tuesday, April 26, 2016 6:31 PM
To: Pratt Wiley; Walker, Eric
Subject: NC Press Call

I have to leave shortly so that I can make it home in time for media monitoring. Attached is the script that I sent Reps. Butterfield and Adams.

Eric � Pratt is working on his portion. Can you submit it through the approvals process?



[SigDems]<http://www.democrats.org/>Deshundra Jefferson, Southern Regional Communications Director
Democratic National Committee
JeffersonD@dnc.org<mailto:JeffersonD@dnc.org> | (202) 863-8112


++++++++++++++++++++++++++++++++++++++++++++++++++
attachments: ['image002.png']

可见该邮件没有抄送,有一个图片附件,虽然有点乱码,但基本的内容已经全部弄出来,可以用作数据分析。

此外,对于邮件中附件,解析出来效果如下:

图片、pdf、docx、csv全弄出来了,感觉会被查水表~~

数据入库

根据上面的分析方法,可以得到所有有用的邮件信息,下面进行数据入库进行数据持久化,便于后面要做的数据分析工作。

由于主题、发件人、时间戳、正文都是唯一的,可以建一张表来放这些内容:

CREATE TABLE emails (
  id int(11) not null primary key auto_increment,
  email_id varchar(10) NOT NULL,
  subject varchar(1000) NOT NULL,
  mail_from varchar(100)  NOT NULL,
  pub_time varchar(100) NOT NULL,
  content longtext  NULL
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;

收件人、抄送、附件可能不唯一或不存在,建几张表来存放,使用email_id字段来和邮件进行关联(PS:我实在不喜欢用外键这个东西)

CREATE TABLE email_attachment (
  id int(11) not null primary key auto_increment,
  email_id varchar(10) NOT NULL,
  attachment varchar(300) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;

CREATE TABLE email_CC (
  id int(11) not null primary key auto_increment,
  email_id varchar(10) NOT NULL,
  CC_addr varchar(300) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;

CREATE TABLE email_to (
  id int(11) not null primary key auto_increment,
  email_id varchar(10) NOT NULL,
  to_addr varchar(300) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;

由此便完成了几张数据表的设计。将相关数据插入这几张表中,后面便可以开始数据分析工作。