一、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()
|