一、python处理XML
XML 指可扩展标记语言(eXtensible Markup Language)。XML 被设计用来传输和存储数据。XML是一套定义语义标记的规则,这些标记将文档分成许多部件并对这些部件加以标识。它也是元标记语言,即定义了用于定义其他与特定领域有关的、语义的、结构化的标记语言的句法语言。
Python对XML的解析:常见的XML编程接口有DOM和SAX,这两种接口处理XML文件的方式不同,当然使用场合也不同。
1.SAX (simple API for XML )
python 标准库包含SAX解析器,SAX用事件驱动模型,通过在解析XML的过程中触发一个个的事件并调用用户定义的回调函数来处理XML文件。
2.DOM(Document Object Model)
将XML数据在内存中解析成一个树,通过对树的操作来操作XML。
注:因DOM需要将XML数据映射到内存中的树,一是比较慢,二是比较耗内存,而SAX流式读取XML文件,比较快,占用内存少,但需要用户实现回调函数(handler)。
例:
cat book.xml
1
2
3
4
5
6
7
8
9
10
11
|
<? xml version = "1.0" encoding = "ISO-8859-1" ?>
< bookstore >
< book >
< title lang = "eng" >Harry Potter</ title >
< price >29.99</ price >
</ book >
< book >
< title lang = "eng" >Learning XML</ title >
< price >39.95</ price >
</ book >
</ bookstore >
|
使用python处理的相关代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
import string
from xml.parsers.expat import ParserCreate
class DefaultSaxHandler( object ):
def start_element( self ,name,attrs):
self .name = name
#print('element:%s, attrs:%s' % (name,str(attrs)))
print ( "<" + name + ">" )
def end_element( self ,name):
#print('end element:%s' % name)
print ( "</" + name + ">" )
def char_data( self ,text):
if text.strip():
print ( "%s's text is %s" % ( self .name,text))
handler = DefaultSaxHandler()
parser = ParserCreate()
parser.StartElementHandler = handler.start_element
parser.EndElementHandler = handler.end_element
parser.CharacterDataHandler = handler.char_data
with open ( 'book.xml' ) as f:
parser.Parse(f.read())
|
抓取全国各省邮编的实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
import requests
from xml.parsers.expat import ParserCreate
class DefaultSaxHandler( object ):
def __init__( self ,provinces):
self .provinces = provinces
def start_element( self ,name,attrs):
if name ! = 'map' :
name = attrs[ 'title' ]
number = attrs[ 'href' ]
self .provinces.append((name,number))
def end_element( self ,name):
pass
def char_data( self ,text):
pass
def get_province_entry(url):
content = requests.get(url).content.decode( 'gb2312' )
start = content.find( '<map name="map_86" id="map_86">' )
end = content.find( '</map>' )
content = content[start:end + len ( '</map>' )].strip()
#print(content)
provinces = []
handler = DefaultSaxHandler(provinces)
parser = ParserCreate()
parser.StartElementHandler = handler.start_element
parser.EndElementHandler = handler.end_element
parser.CharacterDataHandler = handler.char_data
parser.Parse(content)
return provinces
provinces = get_province_entry( 'http://www.ip138.com/post' )
print (provinces)
|
DOM的一个小例子:
1
2
3
4
5
6
7
8
9
|
from xml.dom import minidom
doc = minidom.parse( 'book.xml' )
root = doc.documentElement
print (root.nodeName)
books = root.getElementsByTagName( 'book' )
for book in books:
titles = book.getElementsByTagName( 'title' )
prices = book.getElementsByTagName( 'price' )
print (titles[ 0 ].childNodes[ 0 ].nodeValue + ":" + prices[ 0 ].childNodes[ 0 ].nodeValue)
|
二、HTMLParser
html.parser的核心是HTMLParser类。工作的流程是:当feed给它一个类似HTML格式的字符串时,它会调用goahead方法向前迭代各个标签,并调用对应的parse_xxxx方法提取start_tag, tag, data, comment 和end_tag 等标签信息和数据,然后调用对应的方法对这些抽取出来的内容进行处理
handle_startendtag #处理开始标签和结束标签
handle_starttag #处理开始标签,比如<xx>
handle_endtag #处理结束标签,比如</xx>或者<……/>
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>的
markupbase安装方法: 直接'pip install'无法安装成功,尝试命令'pip search markupbase'得到包名'micropython-markupbase’,然后直接在网页上下载这个包,下载后里面有一个'_markupbase.py'文件,将文件名前缀去掉后文件复制到python安装目录'\lib\site-packages'下。例:cp markupbase.py /usr/local/lib/python3.6/site-packages/
下例:处理指定的html文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
#coding=utf-8 from HTMLParser import HTMLParser
class MyParser(HTMLParser):
"""一个简单的HTMLparser的例子"""
def handle_decl( self , decl):
"""处理头文档"""
HTMLParser.handle_decl( self , decl)
print (decl)
def handle_starttag( self , tag, attrs):
"""处理起始标签"""
HTMLParser.handle_starttag( self , tag, attrs)
if not HTMLParser.get_starttag_text( self ).endswith( "/>" ):
print ( "<" + tag + ">" )
def handle_data( self , data):
"""处理文本元素"""
HTMLParser.handle_data( self , data)
print (data)
def handle_endtag( self , tag):
"""处理结束标签"""
HTMLParser.handle_endtag( self , tag)
if not HTMLParser.get_starttag_text( self ).endswith( "/>" ):
print ( "</" + tag + ">" )
def handle_startendtag( self , tag, attrs):
"""处理自闭标签"""
HTMLParser.handle_startendtag( self , tag, attrs)
print (HTMLParser.get_starttag_text( self ))
def handle_comment( self , data):
"""处理注释"""
HTMLParser.handle_comment( self , data)
print (data)
def close( self ):
HTMLParser.close( self )
print ( "parser over" )
demo = MyParser()
demo.feed( open ( "test.html" ).read())
demo.close() |