本文共 4948 字,大约阅读时间需要 16 分钟。
一、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() |