zoukankan      html  css  js  c++  java
  • python:解析html(HTMLParser、SGMLParser) 分类: HTMLParser 2013-11-12 18:11 2302人阅读 评论(0) 收藏

    其实python里面有xml.dom模块,但是这次却不能用,为啥呢?因为服务器传回的html从xml角度看不是良构的,没有闭合的标签、没有被注释掉的javascript和css,xml.dom没法处理,这个时候要用sgmllib。

    sgmllib.py 包含一个重要的类: SGMLParser。SGMLParser 将 HTML 分解成有用的片段, 比如开始标记和结束标记。一旦它成功地分解出某个数据为一个有用的片段,它会根据 所发现的数据,调用一个自身内部的方法。为了使用这个分析器,您需要子类化 SGML- Parser类,并且覆盖这些方法。

    SGMLParser类里面包含了很多内部方法,开始读取html后,遇到相应的数据就会调用其对应的方法,最重要的方法有三个:

    • start_tagname(self, attrs)
    • end_tagname(self)
    • handle_data(self, text)

    tagname就是标签名称,比如当遇到<pre>,就会调用start_pre,遇到</pre>,就会调用 end_pre,attrs即为标签的参数,以[(attribute, value), (attribute, value), ...]的形式传回,我们要做的就是在其子类重载自己感兴趣标签对应的函数。

    一个经典的例子:

    1. from sgmllib import SGMLParser
    2. class URLLister(SGMLParser):
    3. self.urls = []
    4. def start_a(self, attrs):
    5. href = [v for k, v in attrs if k=='href']
    6. if href:
    7. self.urls.extend(href)

    顾名思义,这个类的作用就是把html中的所有连接(<a>标签)中的地址(href属性的值)提取出来,放到一个list里面,很实用的功能。^^

    比如处理下面的html:

    <tr>
    <td height="207" colspan="2" align="left" valign="top" class="normal">
    <p>Damien Rice - 《0》 </p>
    <a href="http://galeki.xy568.net/music/Delicate.mp3">1. Delicate</a><br />
    <a href="http://galeki.xy568.net/music/Volcano.mp3">2. Volcano</a><br />
    <a href="http://galeki.xy568.net/music/The Blower's Daughter.mp3">3. The Blower's Daughter</a><br />
    <a href="http://galeki.xy568.net/music/Cannonball.mp3">4. Cannonball </a><br />
    <a href="http://galeki.xy568.net/music/Older Chests.mp3">5. Order Chests</a><br />
    <a href="http://galeki.xy568.net/music/Amie.mp3">6. Amie</a><br />
    <a href="http://galeki.xy568.net/music/Cheers Darlin'.mp3">7. Cheers Darling</a><br />
    <a href="http://galeki.xy568.net/music/Cold Water.mp3">8. Cold water</a><br />
    <a href="http://galeki.xy568.net/music/I Remember.mp3">9. I remember</a><br />
    <a href="http://galeki.xy568.net/music/Eskimo.mp3">10. Eskimo</a></p>
    </td>
    </tr>

    很乱对吧?下面让举个例子利用URLLister提取出上面mp3下载的地址:

    1. date="上面那一堆…………"
    2. lister=URLLister()
    3. lister.feed(date)

    用feed()把要处理的html传递给对象实体,然后我们来看看处理结果:

    1. print lister.urls

    显示:

    ['http://galeki.xy568.net/music/Delicate.mp3',
    'http://galeki.xy568.net/music/Volcano.mp3',
    "http://galeki.xy568.net/music/The Blower's Daughter.mp3",
    'http://galeki.xy568.net/music/Cannonball.mp3',
    'http://galeki.xy568.net/music/Older Chests.mp3',
    'http://galeki.xy568.net/music/Amie.mp3',
    "http://galeki.xy568.net/music/Cheers Darlin'.mp3",
    'http://galeki.xy568.net/music/Cold Water.mp3',
    'http://galeki.xy568.net/music/I Remember.mp3',
    'http://galeki.xy568.net/music/Eskimo.mp3']

    好了,是不是很方便?现在我们知道了如何处理标签中的属性,那么如何处理标签包含的文字呢?就是上面列出的handle_data(self, text),当遇到标签内的内容,就会调用这个函数,传入的text自然就是标签内的内容了,不过,如何筛选出感兴趣标签内的内容呢?比如上面歌曲的列 表,这时候就要配合start_tagname、end_tagname,用做标记的方法来达到这个目的:

    1. class ListName(SGMLParser):
    2. is_a=""
    3. name=[]
    4. def start_a(self, attrs):
    5. self.is_a=1
    6. def end_a(self):
    7. self.is_a=""
    8. def handle_data(self, text):
    9. if self.is_a:
    10. self.name.append(text)

    这里添加了一个is_a标记,再在handle_date中添加一个if,也就是说,仅仅在a标签内,才会把标签里的内容加到name[]里去。

    看看结果:

    1. listname=ListName()
    2. listname.feed(date)
    3. print listname.name

    显示:

    ['1.Delicate', '2.Volcano', "3.The Blower's Daughter",
    '4.Cannonball ', '5.Order Chests', '6.Amie',
    '7.Cheers Darling', '8.Cold water', '9.I remember',
    '10.Eskimo']

    OK,搞定~

    SGMLParser内置的方法不仅仅只有这三个,还有处理注释的handle_comment,还有处理声明的handle_decl等等等等,不过使用方法和上面的基本相同,不再多写了。


    完整代码:

    #-------------------------------------------------------------------------------
    # Name:        模块6
    # Purpose:
    #
    # Author:      lovingJune
    #
    # Created:     12/11/2013
    # Copyright:   (c) lovingJune 2013
    # Licence:     <your licence>
    #-------------------------------------------------------------------------------
    #coding:utf-8
    
    from sgmllib import SGMLParser
    
    class ListName(SGMLParser):
    
        def reset(self):
            #变量标示是否是标签a,或使用self.is_a=True
            self.is_a=""
            self.name=[]
            #继承父类reset方法
            SGMLParser.reset(self)
    
        def start_a(self,attrs):
            #如果是标签a,则设置is_a=1
            self.is_a=1
    
        def end_a(self):
            self.is_a=""
    
        def handle_data(self,data):
            #如果是标签a的数据,则追加
            if self.is_a:
                self.name.append(data)
    
    if __name__ == '__main__':
        urls='''
        <tr>
    <td height="207" colspan="2" align="left" valign="top" class="normal">
    <p>Damien Rice - 《0》 </p>
    <a href="http://galeki.xy568.net/music/Delicate.mp3">1. Delicate</a><br />
    <a href="http://galeki.xy568.net/music/Volcano.mp3">2. Volcano</a><br />
    <a href="http://galeki.xy568.net/music/The Blower's Daughter.mp3">3. The Blower's Daughter</a><br />
    <a href="http://galeki.xy568.net/music/Cannonball.mp3">4. Cannonball </a><br />
    <a href="http://galeki.xy568.net/music/Older Chests.mp3">5. Order Chests</a><br />
    <a href="http://galeki.xy568.net/music/Amie.mp3">6. Amie</a><br />
    <a href="http://galeki.xy568.net/music/Cheers Darlin'.mp3">7. Cheers Darling</a><br />
    <a href="http://galeki.xy568.net/music/Cold Water.mp3">8. Cold water</a><br />
    <a href="http://galeki.xy568.net/music/I Remember.mp3">9. I remember</a><br />
    <a href="http://galeki.xy568.net/music/Eskimo.mp3">10. Eskimo</a></p>
    </td>
    </tr>
        '''
        listname=ListName()
        listname.feed(urls)
        #输出文本的列表结果
        print listname.name
        listname.close()



  • 相关阅读:
    OSX安装nginx和rtmp模块(rtmp直播服务器搭建)
    用runtime来重写Coder和deCode方法 归档解档的时候使用
    Homebrew安装卸载
    Cannot create a new pixel buffer adaptor with an asset writer input that has already started writing'
    OSX下面用ffmpeg抓取桌面以及摄像头推流进行直播
    让nginx支持HLS
    iOS 字典转json字符串
    iOS 七牛多张图片上传
    iOS9UICollectionView自定义布局modifying attributes returned by UICollectionViewFlowLayout without copying them
    Xcode6 iOS7模拟器和Xcode7 iOS8模拟器离线下载
  • 原文地址:https://www.cnblogs.com/think1988/p/4628015.html
Copyright © 2011-2022 走看看