加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

XML和HTML解析

发布时间:2020-12-16 09:08:18 所属栏目:百科 来源:网络整理
导读:所谓的解析,实质就是在一段XML或HTML代码中提取我们想要的信息,方法是XML或HTML它们都有自己的标识——开始、结束还是数据。利用python提供的解析器可以根据这些标识,利用相应的函数(方法)提取出信息,有点正则表达式的味道! 一、XML Python中使用SAX

所谓的解析,实质就是在一段XML或HTML代码中提取我们想要的信息,方法是XML或HTML它们都有自己的标识——开始、结束还是数据。利用python提供的解析器可以根据这些标识,利用相应的函数(方法)提取出信息,有点正则表达式的味道!

一、XML

Python中使用SAX解析XML非常简洁,SAX 是XML 的简单 API。

基于事件的语法分析器将(分析出来的)事件发送给应用程序。这些事件类似于用户界面事件,例如,浏览器中的ONCLICK事件或者 Java 中的 AWT/Swing 事件。

事件通知应用程序(如浏览器等)发生了某件事并需要应用程序作出反应。在浏览器中,通常为响应用户操作而生成事件:当用户单击按钮时,按钮产生一个ONCLICK事件。

在 XML 语法分析器中,事件与用户操作无关,而仅仅与正在读取的 XML 文档中的元素有关——语言标识。有对于以下方面的事件:

  • 元素开始和结束标记
  • 元素内容
  • 实体
  • 语法分析错误

下图显示了语法分析器在读取文档(XML语言的源码)时如何生成事件——根据语言相应的标识。

言归正传,通常我们关心的事件是start_element,end_element和char_data,准备好这3个函数,然后就可以解析xml了。

from xml.parsers.expat import ParserCreate

class DefaultSaxHandler(object):
    def start_element(self,name,attrs):
        print('sax:start_element: %s,attrs: %s' % (name,str(attrs)))

    def end_element(self,name):
        print('sax:end_element: %s' % name)

    def char_data(self,text):
        print('sax:char_data: %s' % text)

xml = r'''<?xml version="1.0"?>
<ol>
    <li><a href="/python">Python</a></li>
    <li><a href="/ruby">Ruby</a></li>
</ol>
'''
handler = DefaultSaxHandler()
parser = ParserCreate()  #创建解析器实例
parser.returns_unicode = True  #设置returns_unicode为True时,返回的所有element名称和char_data都是unicode,处理国际化更方便
parser.StartElementHandler = handler.start_element  #赋予相应的处理方法(解析器的正常工作还依赖于我们自己定义的处理函数)
parser.EndElementHandler = handler.end_element
parser.CharacterDataHandler = handler.char_data
parser.Parse(xml)
parser.StartElementHandler、parser.EndElementHandler、parser.CharacterDataHandler这三个方法的名称是固定的,而后面赋予的处理方法由我们自己定义,这些方法所做的事情要和parser.StartElementHandler、parser.EndElementHandler、parser.CharacterDataHandler这三者的名称相匹配。

这样也可以:

import xml.parsers.expat

# 3 handler functions
def start_element(name,attrs):
    print 'Start element:',attrs
def end_element(name):
    print 'End element:',name
def char_data(data):
    print 'Character data:',repr(data)

p = xml.parsers.expat.ParserCreate()

p.StartElementHandler = start_element
p.EndElementHandler = end_element
p.CharacterDataHandler = char_data

p.Parse("""<?xml version="1.0"?>
<parent id="top"><child1 name="paul">Text goes here</child1>
<child2 name="fred">More text</child2>
</parent>""",1)

二、HTML

Python用HTMLParser来解析HTML。

from HTMLParser import HTMLParser
from htmlentitydefs import name2codepoint

class MyHTMLParser(HTMLParser):

    def handle_starttag(self,tag,attrs):
        print('<%s>' % tag)

    def handle_endtag(self,tag):
        print('</%s>' % tag)

    def handle_startendtag(self,attrs):
        print('<%s/>' % tag)

    def handle_data(self,data):
        print('data')

    def handle_comment(self,data):
        print('<!-- -->')

    def handle_entityref(self,name):
        print('&%s;' % name)

    def handle_charref(self,name):
        print('&#%s;' % name)

parser = MyHTMLParser()
parser.feed('<html><head></head><body><p>Some <a href="#">html</a> tutorial...<br>END</p></body></html>')

注意, 上面定义的函数(方法)名字是固定的,不可更改,这样才能根据HTML的标识调用相应的方法。但是函数里面的内容可自己定制!

An HTMLParser instance is fed HTML data(一个HTMLParser实例填充进HTML数据) and calls handler methods when start tags,end tags,text,comments,and other markup elements are encountered(当遇到这些元素的时候会调用相应的处理方法). The user should subclass HTMLParser and override its methods to implement the desired behavior(用户需要自己定义HTMLParser的子类并重写方法!!!).

另外,

1. 要搞清楚,何为tag,何为attrs。如python docs

>>> parser.feed('<img src="python-logo.png" alt="The Python logo">')
     tag: img
     attr: ('src','python-logo.png')  #后者是attr的形式(冒号后)
     attr: ('alt','The Python logo')
>>>
>>> parser.feed('<h1>Python</h1>')
Start tag: h1
Data     : Python
End tag  : h1  (尖括号括起来,切前面有/)
2. parser.feed() 可以反复调用。

3.特殊字符有两种,一种是英文表示的&nbsp;,一种是数字表示的&#1234;,这两种字符都可以通过Parser解析出来,用handle_entityref 和handle_charref 方法。

4.练习

找一个网页,例如https://www.python.org/events/python-events/,用浏览器查看源码并复制,然后尝试解析一下HTML,输出Python官网发布的会议时间、名称和地点。

from HTMLParser import HTMLParser
import urllib

class MyHTMLParser(HTMLParser):

    def __init__(self):
        HTMLParser.__init__(self)  #python中的派生类不会自动调用基类构造函数,所以要显式调用
        self.key = {'time': None,'event-title': None,'event-location': None}  #self.key是一个字典!!!用来标记是否找到了会议时间、名称和地点

    def handle_starttag(self,attrs):
        if tag == 'time':
            self.key['time'] = True
        elif tag == 'span' and attrs.__contains__(('class','event-location')):  #attrs的形式
            self.key['event-location'] = True
        elif tag == 'h3' and attrs.__contains__(('class','event-title')):
            self.key['event-title'] = True

    def handle_data(self,data):
        if self.key['time']:
            print 'Time:%st|' % data,self.key['time'] = None
        elif self.key['event-title']:
            print 'Title:%st|' % data,self.key['event-title'] = None
        elif self.key['event-location']:
            print 'Location:%st|' % data
            self.key['event-location'] = None

parser = MyHTMLParser()
html = urllib.urlopen('http://www.python.org/events/python-events/').read()
parser.feed(html)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读