1 综述

有很多种解析方法。

(1)  DOM   缺点是:1 不能解析格式不正确或者不规则xml  2据说只能解析utf-8格式,非utf-8需要转码

与SAX比较,DOM典型的缺点是比较慢,消耗更多的内存,因为DOM会将整个XML数读入内存中,并为树

中的第一个节点建立一个对象。使用DOM的好处是你不需要对状态进行追踪,因为每一个节点都知道谁是它的

父节点,谁是子节点。但是DOM用起来有些麻烦。

 

Python中使用minidom解析xml,会遇到编码问题。minidom支持UTF-8的编码,对于其他的编码,必须进行转换,否则解析时会产生异常。下面以读取gb2312编码的xml文件为例。

          sourceFile = codecs.open(sourceFilePath,mode='r')

           xmlContentStr = sourceFile.read()

           xmlContentStr = xmlContentStr.decode('gb2312').encode('utf-8')

           xmlContentStr =xmlContentStr.replace('encoding="gb2312"','encoding="utf-8"')

           sourceXML = minidom.parseString(xmlContentStr)



(2) beatifulsoup    特点是可以处理格式不正确的html文档

(3).SAX
(simple API for XML )

       pyhton 标准库包含SAX解析器,SAX是一种典型的极为快速的工具,在解析XML时,不会占用大量内存。

但是这是基于回调机制的,因此在某些数据中,它会调用某些方法进行传递。这意味着必须为数据指定句柄,

以维持自己的状态,这是非常困难的。



 (4)   ElementTree(元素树)

     ElementTree就像一个轻量级的DOM,具有方便友好的API。代码可用性好,速度快,消耗内存少,这里主要

介绍ElementTree。

2 DOM(Document
Object Model)

与SAX比较,DOM典型的缺点是比较慢,消耗更多的内存,因为DOM会将整个XML数读入内存中,并为树

中的第一个节点建立一个对象。使用DOM的好处是你不需要对状态进行追踪,因为每一个节点都知道谁是它的

父节点,谁是子节点。但是DOM用起来有些麻烦。

一 、xml.dom 解析XML的API描述

minidom.parse(filename)

加载读取XML文件

doc.documentElement

获取XML文档对象

node.getAttribute(AttributeName)

获取XML节点属性值

node.getElementsByTagName(TagName)

获取XML节点对象集合

node.childNodes #返回子节点列表。

node.childNodes[index].nodeValue

获取XML节点值

node.firstChild

#访问第一个节点。等价于pagexml.childNodes[0]

doc = minidom.parse(filename)

doc.toxml('UTF-8')

返回Node节点的xml表示的文本

Node.attributes["id"]

a.name #就是上面的 "id"

a.value #属性的值 

访问元素属性

二、代码演示

1、创建user.xml文件,添加XMl节点

<?xml version="1.0" encoding="UTF-8" ?>
<users>
<user id="1000001">
<username>Admin</username>
<email>admin@live.cn</email>
<age>23</age>
<sex>男</sex>
</user>
<user id="1000002">
<username>Admin2</username>
<email>admin2@live.cn</email>
<age>22</age>
<sex>男</sex>
</user>
<user id="1000003">
<username>Admin3</username>
<email>admin3@live.cn</email>
<age>27</age>
<sex>男</sex>
</user>
<user id="1000004">
<username>Admin4</username>
<email>admin4@live.cn</email>
<age>25</age>
<sex>女</sex>
</user>
<user id="1000005">
<username>Admin5</username>
<email>admin5@live.cn</email>
<age>20</age>
<sex>男</sex>
</user>
<user id="1000006">
<username>Admin6</username>
<email>admin6@live.cn</email>
<age>23</age>
<sex>女</sex>
</user>
</users>

2、Demo.py解析user.xml文档数据

# -*- coding:utf-8 -*-
"""
* User: lhj588
* Date: 11-11-9
* Time: 13:20
* Desc:
"""
from xml.dom import minidom

def get_attrvalue(node, attrname):
return node.getAttribute(attrname) if node else ''

def get_nodevalue(node, index = 0):
return node.childNodes[index].nodeValue if node else ''

def get_xmlnode(node,name):
return node.getElementsByTagName(name) if node else []

def xml_to_string(filename='user.xml'):
doc = minidom.parse(filename)
return doc.toxml('UTF-8')

def get_xml_data(filename='user.xml'):
doc = minidom.parse(filename)
root = doc.documentElement

user_nodes = get_xmlnode(root,'user')
user_list=[]
for node in user_nodes:
user_id = get_attrvalue(node,'id')
node_name = get_xmlnode(node,'username')
node_email = get_xmlnode(node,'email')
node_age = get_xmlnode(node,'age')
node_sex = get_xmlnode(node,'sex')

user_name =get_nodevalue(node_name[0]).encode('utf-8','ignore')
user_email = get_nodevalue(node_email[0]).encode('utf-8','ignore')
user_age = int(get_nodevalue(node_age[0]))
user_sex = get_nodevalue(node_sex[0]).encode('utf-8','ignore')
user = {}
user['id'] , user['username'] , user['email'] , user['age'] , user['sex'] = (
int(user_id), user_name , user_email , user_age , user_sex
)
user_list.append(user)
return user_list

def test_xmltostring():
print xml_to_string()

def test_laod_xml():
user_list = get_xml_data()
for user in user_list :
#print user['sex']
print '-----------------------------------------------------'
if user:
user_str='编 号:%d\n用户名:%s\n性 别:%s\n年 龄:%s\n邮 箱:%s\n ' % (int(user['id']) , user['username'], user['sex'] , user['age'] , user['email'])
print user_str
print '====================================================='

if __name__ == "__main__":
test_xmltostring()
test_laod_xml()

3、测试效果

A、测试toxml

demo.py 文件中修改成
if __name__ == "__main__":
test_xmltostring()
 执行打印结果:
<user id="1000001">
<username>Admin</username>
<email>admin@live.cn</email>
<age>23</age>
<sex>男</sex>
</user>
<user id="1000002">
<username>Admin2</username>
<email>admin2@live.cn</email>
<age>22</age>
<sex>男</sex>
</user>
<user id="1000003">
<username>Admin3</username>
<email>admin3@live.cn</email>
<age>27</age>
<sex>男</sex>
</user>
<user id="1000004">
<username>Admin4</username>
<email>admin4@live.cn</email>
<age>25</age>
<sex>女</sex>
</user>
<user id="1000005">
<username>Admin5</username>
<email>admin5@live.cn</email>
<age>20</age>
<sex>男</sex>
</user>
<user id="1000006">
<username>Admin6</username>
<email>admin6@live.cn</email>
<age>23</age>
<sex>女</sex>
</user>
B、测试解析XML
demo.py 文件中修改成

if __name__ == "__main__": 

        test_laod_xml()

执行打印出结果:
-----------------------------------------------------
编 号:1000001
用户名:Admin
性 别:男
年 龄:23
邮 箱:admin@live.cn

=====================================================
-----------------------------------------------------
编 号:1000002
用户名:Admin2
性 别:男
年 龄:22
邮 箱:admin2@live.cn

=====================================================
-----------------------------------------------------
编 号:1000003
用户名:Admin3
性 别:男
年 龄:27
邮 箱:admin3@live.cn

=====================================================
-----------------------------------------------------
编 号:1000004
用户名:Admin4
性 别:女
年 龄:25
邮 箱:admin4@live.cn

=====================================================
-----------------------------------------------------
编 号:1000005
用户名:Admin5
性 别:男
年 龄:20
邮 箱:admin5@live.cn

=====================================================
-----------------------------------------------------
编 号:1000006
用户名:Admin6
性 别:女
年 龄:23
邮 箱:admin6@live.cn

=====================================================

转自:http://www.cnblogs.com/lhj588/archive/2011/11/09/2242483.html

3  Beautiful
Soup

Beautiful
Soup 是用 Python 写的一个 HTML/XML 的解析器,它可以很好的处理不规范标记并生成剖析树。通常用来分析爬虫抓取的web文档。对于 不规则的 Html文档,也有很多的补全功能,节省了开发者的时间和精力。

Beautiful Soup 的官方文档齐全,将官方给出的例子实践一遍就能掌握。官方英文文档中文文档

一 安装 Beautiful Soup

安装 BeautifulSoup 很简单,下载 BeautifulSoup  源码。解压运行

python setup.py install 即可。

测试安装是否成功。键入 import BeautifulSoup 如果没有异常,即成功安装

二 使用 BeautifulSoup

1. 导入BeautifulSoup ,创建BeautifulSoup 对象

1
2
3
4
5
6
7
8
9
10
11
12
fromBeautifulSoupimportBeautifulSoup          #
HTML
fromBeautifulSoupimportBeautifulStoneSoup     #
XML
importBeautifulSoup                             #
ALL
                                                                                               
doc=[
    '<html><head><title>Page
title</title></head>'
,
    '<body><p
id="firstpara" align="center">This is paragraph <b>one</b>.'
,
    '<p
id="secondpara" align="blah">This is paragraph <b>two</b>.'
,
    '</html>'
]
#
BeautifulSoup 接受一个字符串参数
soup=BeautifulSoup(''.join(doc))

2. BeautifulSoup对象简介

用BeautifulSoup 解析 html文档时,BeautifulSoup将 html文档类似 dom文档树一样处理。BeautifulSoup文档树有三种基本对象。

2.1. soup BeautifulSoup.BeautifulSoup

1
2
type(soup)
<class'BeautifulSoup.BeautifulSoup'>

2.2. 标记 BeautifulSoup.Tag

1
2
type(soup.html)
<class'BeautifulSoup.Tag'>

2.3 文本 BeautifulSoup.NavigableString

1
2
type(soup.title.string)
<class'BeautifulSoup.NavigableString'>

3. BeautifulSoup 剖析树

3.1 BeautifulSoup.Tag对象方法

获取 标记对象(Tag)

标记名获取法 ,直接用 soup对象加标记名,返回 tag对象.这种方式,选取唯一标签的时候比较有用。或者根据树的结构去选取,一层层的选择

1
2
3
4
5
6
7
>>>
html = soup.html
>>>
html
<html><head><title>Page
title</
title></head><body><pid="firstpara"align="center">This
is paragraph<
b>one</b>.</p><pid="secondpara"align="blah">This
is paragraph<
b>two</b>.</p></body></html>
>>>
type(html)
<class'BeautifulSoup.Tag'>
>>>
title = soup.title
<title>Page
title</
title>

content方法

content方法 根据文档树进行搜索,返回标记对象(tag)的列表

1
2
>>>
soup.contents
[<html><head><title>Page
title<
/title></head><body><pid="firstpara"align="center">Thisisparagraph<b>one</b>.</p><pid="secondpara"align="blah">Thisisparagraph<b>two</b>.</p></body></html>]
1
2
3
4
5
6
>>>
soup.contents[
0].contents
[<head><title>Page
title<
/title></head>,
<body><p
id="firstpara"align="center">Thisisparagraph<b>one</b>.</p><pid="secondpara"align="blah">Thisisparagraph<b>two</b>.</p></body>]
>>>len(soup.contents[0].contents)
2
>>>type(soup.contents[0].contents[1])
<class'BeautifulSoup.Tag'>

使用contents向后遍历树,使用parent向前遍历树

next 方法

获取树的子代元素,包括 Tag 对象 和 NavigableString 对象。。。

1
2
3
4
>>>
head.
next
<title>Page
title<
/title>
>>>
head.
next.next
u'Page
title'
1
2
3
4
5
>>>
p1
=soup.p
>>>
p1
<pid="firstpara"align="center">Thisisparagraph<b>one</b>.</p>
>>>
p1.
next
u'This
is paragraph'

nextSibling 下一个兄弟对象 包括 Tag 对象 和 NavigableString 对象

1
2
3
4
>>>
head.nextSibling
<body><pid="firstpara"align="center">Thisisparagraph<b>one</b>.</p><pid="secondpara"align="blah">Thisisparagraph<b>two</b>.</p></body>
>>>
p1.
next.nextSibling
<b>one</b>

与 nextSibling 相似的是 previousSibling,即上一个兄弟节点。

replacewith方法

将对象替换为,接受字符串参数

1
2
3
4
5
6
7
8
9
10
11
12
>>>
head
=soup.head
>>>
head
<head><title>Page
title<
/title></head>
>>>
head.parent
<html><head><title>Page
title<
/title></head><body><pid="firstpara"align="center">Thisisparagraph<b>one</b>.</p><pid="secondpara"align="blah">Thisisparagraph<b>two</b>.</p></body></html>
>>>
head.replaceWith(
'head
was replace'
)
>>>
head
<head><title>Page
title<
/title></head>
>>>
head.parent
>>>
soup
<html>head
was replace<body><p
id="firstpara"align="center">Thisisparagraph<b>one</b>.</p><pid="secondpara"align="blah">Thisisparagraph<b>two</b>.</p></body></html>
>>>

搜索方法

搜索提供了两个方法,一个是 find,一个是findAll。这里的两个方法(findAll和 find)仅对Tag对象以及,顶层剖析对象有效,但 NavigableString不可用。

findAll(nameattrsrecursivetextlimit**kwargs)

接受一个参数,标记名

寻找文档所有 P标记,返回一个列表

1
2
3
4
>>>
soup.findAll(
'p')
[<pid="firstpara"align="center">Thisisparagraph<b>one</b>.</p>,
<p
id="secondpara"align="blah">Thisisparagraph<b>two</b>.</p>]
>>>type(soup.findAll('p'))
<type'list'>

寻找 id="secondpara"的 p 标记,返回一个结果集

1
2
3
>>>
pid
=type(soup.findAll('p',id='firstpara'))
>>>
pid
<class'BeautifulSoup.ResultSet'>

传一个属性或多个属性对

1
2
3
4
5
>>>
p2
=soup.findAll('p',{'align':'blah'})
>>>
p2
[<pid="secondpara"align="blah">Thisisparagraph<b>two</b>.</p>]
>>>type(p2)
<class'BeautifulSoup.ResultSet'>

利用正则表达式

1
2
>>>
soup.findAll(
id=re.compile("para$"))
[<pid="firstpara"align="center">Thisisparagraph<b>one</b>.</p>,
<p
id="secondpara"align="blah">Thisisparagraph<b>two</b>.</p>]

读取和修改属性

1
2
3
4
5
6
7
8
9
10
11
12
>>>
p1
=soup.p
>>>
p1
<pid="firstpara"align="center">Thisisparagraph<b>one</b>.</p>
>>>
p1[
'id']
u'firstpara'
>>>
p1[
'id']='changeid'
>>>
p1
<pid="changeid"align="center">Thisisparagraph<b>one</b>.</p>
>>>
p1[
'class']='new
class'
>>>
p1
<pid="changeid"align="center"class="new
class"
>Thisisparagraph<b>one</b>.</p>
>>>

剖析树基本方法就这些,还有其他一些,以及如何配合正则表达式。具体请看官方文档

3.2 BeautifulSoup.NavigableString对象方法

NavigableString  对象方法比较简单,获取其内容

1
2
3
4
5
6
7
8
9
>>>
soup.title
<title>Page
title<
/title>
>>>
title
=soup.title.next
>>>
title
u'Page
title'
>>>type(title)
<class'BeautifulSoup.NavigableString'>
>>>
title.string
u'Page
title'

至于如何遍历树,进而分析文档,已经 XML 文档的分析方法,可以参考官方文档。

转自:http://rsj217.diandian.com/post/2012-11-01/40041235132

最新文章

  1. C#语言基础
  2. Java程序猿学习的建议(转)
  3. jquery中append跟prepend的用法
  4. linux命令学习-复制(cp,scp)
  5. java 14 -7 Date
  6. python使用open经常报错:TypeError: an integer is required的解决方案
  7. 最简的Dubbo例子部署
  8. NSURLConnection 网络超时的那些事(转别人整理的)
  9. 一位IT行业高收入者的理财规划方案
  10. TaskTracker获取并执行map或reduce任务的过程1
  11. android6.0 SerialPort 服务
  12. 我对Spring的理解。
  13. jmeter 使用白皮书
  14. JavaScript之基础语法整理
  15. 基于框架的RPC通信技术原理解析
  16. ubuntu 初始安装完成后的一些设置
  17. Vistual Studio XML 智能提示
  18. div+css感悟
  19. BZOJ1012最大数 [JSOI2008] 单调栈+二分
  20. C# 拼接字符串的几种方式和性能

热门文章

  1. 初识golang
  2. php 获取地址栏参数
  3. 未能加载文件或程序集“ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73”或它的某一个依赖项
  4. linux 文件系统操作()
  5. get 和 post请求的区别
  6. Mishka and Interesting sum
  7. linux的视频学习4(网络配置和rpm)
  8. android图片加水印,文字
  9. robot framework -记录关键字
  10. Listview多条目展示