用python读取邮件正文想把一批html中的正文提取出来,怎么做比较高效实用

5958人阅读
python(63)
http://blog.csdn.net/nwpulei/article/details/7272832
python提供了SGMLParser类用于html文件的解析。用户只需从SGMLParser类继承子类,并在子类中对html文件做具体处理。
例如 具有如下结构的html文件
&class='entry-content'&&感兴趣内容1&&感兴趣内容2&&……&&感兴趣内容n&&&&&class='content'&&内容1&&内容2&&……&&内容n&&&&
我们尝试获得'感兴趣内容'
对于文本内容,我们保存到IDList中。
可是如何标记我们遇到的文本是感兴趣的内容呢,也就是,处于
&class='entry-content'&&这里的内容&&还有这里&&……&&以及这里的内容&&&&
遇到&div class='entry-content'& 设置标记flag = True遇到&/div&后 设置标记flag = False当flag 为True时遇到&p& 设置标记getdata = True遇到&/p& 且getdata = True,设置getdata = False
python为我们提供了SGMLParser类,SGMLParser 将 HTML 分析成 8 类数据[1],然后对每一类调用单独的方法:使用时只需继承SGMLParser 类,并编写页面信息的处理函数。
可用的处理函数如下:
开始标记 (Start tag)&
是一个开始一个块的 HTML 标记,象 &html&,&head&,&body& 或 &pre& 等,或是一个独一的标记,象 &br& 或 &img& 等。当它找到一个开始标记 tagname,SGMLParser 将查找名为&start_tagname&或&do_tagname&的方法。例如,当它找到一个 &pre& 标记,它将查找一个 start_pre 或 do_pre 的方法。如果找到了,SGMLParser
会使用这个标记的属性列表来调用这个方法;否则,它用这个标记的名字和属性列表来调用&unknown_starttag&方法。&
结束标记 (End tag)&
是结束一个块的 HTML 标记,象 &/html&,&/head&,&/body& 或 &/pre& 等。当找到一个结束标记时,SGMLParser 将查找名为&end_tagname&的方法。如果找到,SGMLParser 调用这个方法,否则它使用标记的名字来调用&unknown_endtag&。&
字符引用 (Character reference)&
用字符的十进制或等同的十六进制来表示的转义字符,象  。当找到,SGMLParser 使用十进制或等同的十六进制字符文本来调用&handle_charref&。&
实体引用 (Entity reference)&
HTML 实体,象 &。当找到,SGMLParser 使用 HTML 实体的名字来调用&handle_entityref&。&
注释 (Comment)&
HTML 注释, 包括在 &!-- ... --&之间。当找到,SGMLParser 用注释内容来调用&handle_comment。&
处理指令 (Processing instruction)&
HTML 处理指令,包括在 &? ... & 之间。当找到,SGMLParser 用处理指令内容来调用&handle_pi。&
声明 (Declaration)&
HTML 声明,如 DOCTYPE,包括在 &! ... &之间。当找到,SGMLParser 用声明内容来调用&handle_decl。&
文本数据 (Text data)&
文本块。不满足其它 7 种类别的任何东西。当找到,SGMLParser 用文本来调用&handle_data。&
综上,的到如下代码
from&sgmllib&import&SGMLParser&&class&GetIdList(SGMLParser):&&&&&&def&reset(self):&&&&&&&&&&self.IDlist&=&[]&&&&&&&&&&self.flag&=&False&&&&&&&&&&self.getdata&=&False&&&&&&&&&&SGMLParser.reset(self)&&&&&&&&&&&&&&&&def&start_div(self,&attrs):&&&&&&&&&&for&k,v&in&attrs:&&&&&&&&&&&&&&if&k&==&'class'&and&v&==&'entry-content':&&&&&&&&&&&&&&&&&&self.flag&=&True&&&&&&&&&&&&&&&&&&return&&&&&&&&def&end_div(self):&&&&&&self.flag&=&False&&&&&&&&&&&&&&&&&&&&def&start_p(self,&attrs):&&&&&&&&&&if&self.flag&==&False:&&&&&&&&&&&&&&return&&&&&&&&&&self.getdata&=&True&&
def&end_p(self):&&&&&&if&self.getdata:&&&&&&&&&&self.getdata&=&False&&&&def&handle_data(self,&text):&&&&&&if&self.getdata:&&&&&&&&&&self.IDlist.append(text)&&
def&printID(self):&&&&&&for&i&in&self.IDlist:&&&&&&&&&&print&i&&
上面的思路存在一个bug
遇到&/div&后 设置标记flag = False
如果遇到div嵌套怎么办?
&class='entry-content'我是来捣乱的感兴趣&&
在遇到第一个&/div&之后标记flag = False,导致无法的到‘感兴趣内容’。
怎么办呢?如何判断遇到的&/div&是和&div class='entry-content'&匹配的哪个呢?
很简单,&/div&和&div&是对应的,我们可以记录他所处的层数。进入子层div verbatim加1,退出子层div &verbatim减1.这样就可以判断是否是同一层了。
修改后&如下
from&sgmllib&import&SGMLParser&&class&GetIdList(SGMLParser):&&&&&&def&reset(self):&&&&&&&&&&self.IDlist&=&[]&&&&&&&&&&self.flag&=&False&&&&&&&&&&self.getdata&=&False&&&&&&&&&&self.verbatim&=&0&&&&&&&&&&SGMLParser.reset(self)&&&&&&&&&&&&&&&&def&start_div(self,&attrs):&&&&&&&&&&if&self.flag&==&True:&&&&&&&&&&&&&&self.verbatim&+=1&&&&&&&&&&&&&&&return&&&&&&&&&&for&k,v&in&attrs:&&&&&&&&&&&&&&if&k&==&'class'&and&v&==&'entry-content':&&&&&&&&&&&&&&&&&&self.flag&=&True&&&&&&&&&&&&&&&&&&return&&&&&&&&def&end_div(self):&&&&&&&&&&if&self.verbatim&==&0:&&&&&&&&&&&&&&self.flag&=&False&&&&&&&&&&if&self.flag&==&True:&&&&&&&&&&&&&&self.verbatim&-=1&&&&&&&&def&start_p(self,&attrs):&&&&&&&&&&if&self.flag&==&False:&&&&&&&&&&&&&&return&&&&&&&&&&self.getdata&=&True&&&&&&&&&&&&&&&&def&end_p(self):&&&&&&&&&&if&self.getdata:&&&&&&&&&&&&&&self.getdata&=&False&&&&&&&&def&handle_data(self,&text):&&&&&&&&&&if&self.getdata:&&&&&&&&&&&&&&self.IDlist.append(text)&&&&&&&&&&&&&&&&&&&&def&printID(self):&&&&&&&&&&for&i&in&self.IDlist:&&&&&&&&&&&&&&print&i&&
最后&&建立了我们自己的类GetIdList后如何使用呢?
简单建立实例 t = GetIdList()
the_page为字符串,内容为html
t.feed(the_page)#对html解析
t.printID()打印出结果
全部测试代码为
from&sgmllib&import&SGMLParser&&class&GetIdList(SGMLParser):&&&&&&def&reset(self):&&&&&&&&&&self.IDlist&=&[]&&&&&&&&&&self.flag&=&False&&&&&&&&&&self.getdata&=&False&&&&&&&&&&self.verbatim&=&0&&&&&&&&&&SGMLParser.reset(self)&&&&&&&&&&&&&&&&def&start_div(self,&attrs):&&&&&&&&&&if&self.flag&==&True:&&&&&&&&&&&&&&self.verbatim&+=1&&&&&&&&&&&&&&&return&&&&&&&&&&for&k,v&in&attrs:&&&&&&&&&&&&&&if&k&==&'class'&and&v&==&'entry-content':&&&&&&&&&&&&&&&&&&self.flag&=&True&&&&&&&&&&&&&&&&&&return&&&&&&&&def&end_div(self):&&&&&&&&&&if&self.verbatim&==&0:&&&&&&&&&&&&&&self.flag&=&False&&&&&&&&&&if&self.flag&==&True:&&&&&&&&&&&&&&self.verbatim&-=1&&&&&&&&def&start_p(self,&attrs):&&&&&&&&&&if&self.flag&==&False:&&&&&&&&&&&&&&return&&&&&&&&&&self.getdata&=&True&&&&&&&&&&&&&&&&def&end_p(self):&&&&&&&&&&if&self.getdata:&&&&&&&&&&&&&&self.getdata&=&False&&&&&&&&def&handle_data(self,&text):&&&&&&&&&&if&self.getdata:&&&&&&&&&&&&&&self.IDlist.append(text)&&&&&&&&&&&&&&&&&&&&def&printID(self):&&&&&&&&&&for&i&in&self.IDlist:&&&&&&&&&&&&&&print&i&&&&&&&&&&&&&&&&&&&&&&the_page&=''&&&&&&&&&&&&&&&&&&&&&&&&lister&=&GetIdList()&&lister.feed(the_page)&&lister.printID()&&
执行后 输出为
感兴趣内容1&&感兴趣内容2&&感兴趣内容n&&
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:497134次
积分:6046
积分:6046
排名:第2812名
原创:33篇
转载:586篇
评论:13条
(45)(5)(1)(3)(14)(26)(22)(43)(17)(31)(19)(17)(10)(36)(26)(46)(25)(15)(5)(4)(4)(1)(3)(3)(1)(2)(2)(1)(2)(8)(5)(5)(12)(4)(9)(17)(25)(1)(13)(2)(1)(1)(2)(1)(1)(5)(1)(15)(4)(1)(3)(3)(2)(1)(1)(4)(1)(1)(1)(2)(6)(12)(5)(4)(3)(2)(2)(1)(10)(1)如何用Python从大量pdf 中提取表格中的数据进行分析_百度知道&&&&&&&&&&&&&&&&&&&&&&&& 15:33:49
&&网站联系: qq: email:&trackbacks-0
事情的起因是,我做survey的时候搜到了这两本书:和,感觉都蛮不错的,想下载下来看看,但是点开网页发现这个只能分章节下载,晕,我可没时间一章一章下载,想起了迅雷的下载全部链接,试试看,果真可以把他们一网打尽,但是,sadly,迅雷下载的时候,文件名没办法跟章节名对应起来,晕,我可没时间一章一章去改名字,怎么办呢?由于做过网站,我看着它那&整洁&的页面就笑了,因为这种规整的页面是有规律可循的,虽然下载PDF的每个链接都含有用HASH随机生成的数字码,但是HTML+CSS的排版是规整的,就可以用正则等方法来把title和PDF都挖出来并且一一对应上。想到下一步是要用到网页分析、抓取、下载的技术的,所以,今天就把这个技术给拿下吧。由于python似乎是我知道的这方面的&利器&,有比较好的原生和社区支持,简单明了以及良好的跨平台性,所以就用python来做这个工作了。
抓取一个网页并分析,从而:
得到半结构化数据,如抓取新浪微博一个页面中的内容。
得到其他网页的指针,如抓取新浪微博中下一个页面。
下载文件,如这次要下载PDF的任务。
多线程抓取与分布式抓取。
自动密钥破解。
S2.方法概述
有多少种方法可以用的呢?
urllib2+urlparse+re
最原始的办法,其中urllib2是python的web库、urlparse能处理url、re是正则库,这种方法写起来比较繁琐,但也比较&实在&,具体可以参考[4].
urllib2+beautifulsoup
这里的得力干将是beautifulsoup[5],beautifulsoup可以非常有效的解析HTML页面,就可以免去自己用re去写繁琐的正则等。我比较喜欢这种方法,在下面具体讲解部分会详解。
Mechanize+BeautifulSoup
Mechanize是对于urllib2的部分功能的替换,使得除了http以外其他任何连接也都能被打开,也更加动态可配置,具体参考[6].
PycURL,据说速度非常快,具体方法可以参考[1][2].
这个暂且未尝试,这种公开的库的有点应该就是速度快、更强大,好像是可以并行的,所以以后有时间再尝试下。
其他更多的开源库参考[3].
S3.具体讲解
假设你已经把python安装好了(我用的版本是python2.7),现在我们用urllib2+BeautifulSoup的方法来抓取springerlink网站上的Computational Social Network Analysis和Computational Social Network,也就是上面提到的,这两本书。
BeautifulSoup的安装,我是在Windows下安装的,官网上没有window下安装的教程,我是凭感觉装上的。它有一个setup.py,我就用"python.exe setup.py install"运行了,但提示"error: package directory 'bs4' does not exist",原来是默认python执行路径不在当前目录,而是在C盘下面的用户目录中,所以把bs4文件移动过去就好了。跑完好,生成一个build文件夹,我知道它肯定要放到Python文件下的LIB文件夹里面去,所以就把下面的bs4移到LIB中去,就可以了。以后要用,直接import即可。如果是linux用户装起来应该会更顺利些。
用urllib2抓取网页/下载文件,urllib中最关键的可能就是urlopen这个函数了,返回的就是这个webpage/文件对象,可以用read等方法将其读出来。urlopen这个函数的参数可以是url也可以是Request,如下:
req = urllib2.Request(url, headers={'User-Agent' : "Magic Browser"})
webpage= urllib2.urlopen(req)
webpage.read()...
这里要注意的一点是headers={&User-Agent&:'Magic Browser'},这个最好加上,否则的话,由于内部信息默认显示为机器代理,可能被服务器403 Forbidden拒绝访问,在抓取上数据的时候不加上一定会被403毙掉的。
用BeautifulSoup处理解析网页,import后,一切从soup = BeautifulSoup(webpage.read( ))开始,你可以用python的终端自己玩玩这个产生的soup对象。我这里就说下一种我比较喜欢的用法,详细具体的API参考[9].我喜欢用嵌套的方式来提取内容,什么意思呢,其实我认为大多数解析定位问题,其实就是下面这样一个问题:
假设有一个页面如下:
并且你已经用soup = BeautifulSoup()初始过了,现在你要根据&div id="a"& -& &div class='aa'& -& &p&这样的结构把下面所有的链接抽取出来,怎么做呢?比较简单的做法,就是一层一层向下分析,具体如下:
top_div = soup.find('div', {'id':'a'}) #注意:返回的是list对象
aa_div = top_div.findAll('div', {'class':'aa'}) #同样是list对象
links = [div.findAll('a') for div in aa_div] #还是list对象
links[0].get('href') ##
links[0].contents #ff
除了链接以外,其他内容也是通过类似的方法解析得到。(PS,我发现我若干个小时前自己还没解决这个问题的时候在SO上发的一个已经有人回答了,真好,那时候其实是困在了对list对象直接用find_all出错)
好吧,最后看看我们的战利品:
声明1,其实有一个2M多的文件下载失败了,今天网络确实有点慢,其实用chrome下载它也差点失败了,因此,其实还是有可改进的地方。当然,可改进地方多了,多线程啥的,暂不讨论了。
声明2,由于是用T学校的网来下的,并且没有复制扩散内容,所以没有侵权!
最后感叹下,最近多以看论文为主,好久没学&技术&了,今天用了一些时间搞搞这种敏捷学习,重新体验那种多线程、开N个窗口、各种任务并发的感觉,真舒服,哈哈:-D
源代码下载:
阅读(...) 评论()

我要回帖

更多关于 python 正文抽取算法 的文章

 

随机推荐