使用Python的HTMLParser解析HTML文本


一. HTMLParser

是python用来解析html的模块。它可以分析出html里面的标签、数据等等,是一种处理html的简便途径。 HTMLParser采用的是一种事件驱动的模式, 当HTMLParser找到一个特定的标记时, 它会去调用一个用户定义的函数(就是回调函数).

它主要的用户回调函数的命名都是以handler_开头的, 都是HTMLParser的成员函数. 当我们使用时,就从HTMLParser派生出新的类, 然 后重新定义这几个以handler_开头的函数即可.

这几个函数包括: 

handle_startendtag  处理开始标签和结束标签, 例如 <img src='http://www.baidu.com/logo.gif'/>

handle_starttag     处理开始标签, 比如<body> 

handle_endtag       处理结束标签, 比如</body> 

handle_charref      处理特殊字符串, 就是以&#开头的, 一般是内码表示的字符 

handle_entityref    处理一些特殊字符, 以&开头的, 比如  

handle_data         处理数据, 就是<xx>data</xx>中间的那些数据 

handle_comment      处理注释 

handle_decl         处理<!开头的, 比如<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 

handle_pi           处理形如<?instruction>的东西


二. 基本使用模式

import HTMLParser
# 重写的这些类函数相当于回调函数, 在不同的情况会调用不同的类函数.
class MyClass(HTMLParser.HTMLParser):
	def __init__(self):
		'''
		构造函数, 做一些初始化工作
		'''		
		HTMLParser.__init__(self)
		
	def handle_starttag(self, tag, attrs):
		'''
		tag 表示解析到的任何标签
		attrs是一个序列, 序列中的内容为元组, 
		一个元组中有两个元素, 分别是该标签的属性和该属性的值判断逻辑语句
		'''
		
	def handle_data(self,data):
		'''
		这里的data为上面tag标签包含的内容
		'''
	
	def handle_endtag(self,tag):
		'''
		这里tag对应的上面那个标签的结束标签
		例如上的标签为<p>,则这里对应的是</p>
		'''
			
	def getresult(self):
		'''
		写一些自己要返回的内容
		'''
		
if __name__=="__main__":
	obname = MyClass()
	obname.feed(html_data)		# 这里传入HTML文本.
	obname.getresult()

在obname.feed(html_data)被调用后, HTMLParser解析HTML文本.

例如

遇到标签开始, 就会调用handle_starttag函数了, 你根据标签做自己想做的事情, 例如输出显示, 其他等.

遇到内容, 就会调用handle_data函数, 你想干嘛都可以.


三. 举例


3.1 该例子分析HTML文本, 并写入文件


#!/usr/bin/env python
# Python 2.7.3
# 使用HTMLParser解析HTML文本, 把分析结果写入文件 htmldata.txt
import urllib2
import HTMLParser
# from HTMLParser import HTMLParser

class MyParser(HTMLParser.HTMLParser):
	def __init__(self):
		HTMLParser.HTMLParser.__init__(self)	# 调用父类的构造函数, 这里调用时有self的
		self.f = open('htmldata.txt', 'w')		# 写入文件(你使用浏览器打开这个文件看看)

	def __del__(self):
		self.f.close()
		#HTMLParser.HTMLParser.__del__(self)

	def handle_starttag(self, tag, attrs):
		print >> self.f, "Start tag:", tag
		for attr in attrs:
			print >> self.f, "     attr:", attr

	def handle_endtag(self, tag):
		print >> self.f, "End tag  :", tag

	def handle_data(self, data):
		print >> self.f, "Data     :", data

	def handle_comment(self, data):
		print >> self.f, "Comment  :", data

	#def handle_entityref(self, name):
	#	c = unichr(name2codepoint[name])
	#	print >> self.f, "Named ent:", c

	def handle_charref(self, name):
		if name.startswith('x'):
			c = unichr(int(name[1:], 16))
		else:
			c = unichr(int(name))
		print >> self.f, "Num ent  :", c

	def handle_decl(self, data):
		print >> self.f, "Decl     :", data


if __name__ == '__main__':
	req = urllib2.Request('http://www.baidu.com')
	response = urllib2.urlopen(req)
	htmlStr = response.read()		# 得到百度的HTML文本
	my = MyParser()
	# 传入要分析的数据,是html的。
	htmlStr = '<html><head><title>Test</title></head><body><h1>Parse me!</h1></body></html>'	
	my.feed(htmlStr)

输出结果:

Start tag: html

Start tag: head

Start tag: title

Data     : Test

End tag  : title

End tag  : head

Start tag: body

Start tag: h1

Data     : Parse me!

End tag  : h1

End tag  : body

End tag  : html

对比一些要分析的HTML文本"<html><head><title>Test</title></head><body><h1>Parse me!</h1></body></html>"和输出的顺序.

参考: http://cloudaice.com/yong-pythonde-htmlparserfen-xi-htmlye-mian/