python网络编程学习笔记(七):HTML和XHTML解析(HTMLParser、BeautifulSoup)
一、利用HTMLParser进行网页解析
具体HTMLParser官方文档可参考http://docs.python.org/library/htmlparser.html#HTMLParser.HTMLParser
1、从一个简单的解析例子开始
例1:
test1.html文件内容如下:
<html> <head> <title>XHTML与HTML4.01标准没有太多的不同</title> </head> <body> iloveyou </body> </html>
下面是能够列出title和body的程序示例:
##@小五义: ##HTMLParser示例 importHTMLParser classTitleParser(HTMLParser.HTMLParser): def__init__(self): self.taglevels=[] self.handledtags=['title','body']#提出标签 self.processing=None HTMLParser.HTMLParser.__init__(self) defhandle_starttag(self,tag,attrs): iftaginself.handledtags: self.data='' self.processing=tag defhandle_data(self,data): ifself.processing: self.data+=data defhandle_endtag(self,tag): iftag==self.processing: printstr(tag)+':'+str(tp.gettitle()) self.processing=None defgettitle(self): returnself.data fd=open('test1.html') tp=TitleParser() tp.feed(fd.read())
运行结果如下:
title:XHTML与HTML4.01标准没有太多的不同
body:
iloveyou
程序定义了一个TitleParser类,它是HTMLParser类的子孙。HTMLParser的feed方法将接收数据,并通过定义的HTMLParser对象对数据进行相应的解析。其中handle_starttag、handle_endtag判断起始和终止tag,handle_data检查是否取得数据,如果self.processing不为None,那么就取得数据。
2、解决html实体问题
(HTML中有用的字符实体)
(1)实体名称
当与到HTML中的实体问题时,上面的例子就无法实现,如这里将test1.html的代码改为:
例2:
<html> <head> <title>XHTML与"HTML4.01"标准没有太多的不同</title> </head> <body> iloveyou× </body> </html>
利用上面的例子进行分析,其结果是:
title:XHTML与HTML4.01标准没有太多的不同
body:
iloveyou
实体完全消失了。这是因为当出现实体的时候,HTMLParser调用了handle_entityref()方法,因为代码中没有定义这个方法,所以就什么都没有做。经过修改后,如下:
##@小五义: ##HTMLParser示例:解决实体问题 fromhtmlentitydefsimportentitydefs importHTMLParser classTitleParser(HTMLParser.HTMLParser): def__init__(self): self.taglevels=[] self.handledtags=['title','body'] self.processing=None HTMLParser.HTMLParser.__init__(self) defhandle_starttag(self,tag,attrs): iftaginself.handledtags: self.data='' self.processing=tag defhandle_data(self,data): ifself.processing: self.data+=data defhandle_endtag(self,tag): iftag==self.processing: printstr(tag)+':'+str(tp.gettitle()) self.processing=None defhandle_entityref(self,name): ifentitydefs.has_key(name): self.handle_data(entitydefs[name]) else: self.handle_data('&'+name+';') defgettitle(self): returnself.data fd=open('test1.html') tp=TitleParser() tp.feed(fd.read())
运行结果为:
title:XHTML与"HTML4.01"标准没有太多的不同
body:
iloveyou×
这里就把所有的实体显示出来了。
(2)实体编码
例3:
<html> <head> <title>XHTML与"HTML4.01"标准没有太多的不同</title> </head> <body> ilove÷you× </body> </html>
如果利用例2的代码执行后结果为:
title:XHTML与"HTML4.01"标准没有太多的不同
body:
iloveyou×
结果中÷对应的÷没有显示出来。
添加handle_charref()进行处理,具体代码如下:
##@小五义: ##HTMLParser示例:解决实体问题 fromhtmlentitydefsimportentitydefs importHTMLParser classTitleParser(HTMLParser.HTMLParser): def__init__(self): self.taglevels=[] self.handledtags=['title','body'] self.processing=None HTMLParser.HTMLParser.__init__(self) defhandle_starttag(self,tag,attrs): iftaginself.handledtags: self.data='' self.processing=tag defhandle_data(self,data): ifself.processing: self.data+=data defhandle_endtag(self,tag): iftag==self.processing: printstr(tag)+':'+str(tp.gettitle()) self.processing=None defhandle_entityref(self,name): ifentitydefs.has_key(name): self.handle_data(entitydefs[name]) else: self.handle_data('&'+name+';')
defhandle_charref(self,name): try: charnum=int(name) exceptValueError: return ifcharnum<1orcharnum>255: return self.handle_data(chr(charnum))
defgettitle(self): returnself.data fd=open('test1.html') tp=TitleParser() tp.feed(fd.read())