博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
用python解析html[SGMLParser]
阅读量:6304 次
发布时间:2019-06-22

本文共 3294 字,大约阅读时间需要 10 分钟。

因为要用python做学校网络的认证程序,需要解析服务器传回的html,本以为会像javascript里操作DOM那样简单,结果发现并不是 这样,被搞了一下。

其实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:


 height="207" colspan="2" align="left" valign="top" class="normal">

Damien Rice - 《0》 
</p>

 href="http://galeki.xy568.net/music/Delicate.mp3">1. Delicate
</a>
 />

 href="http://galeki.xy568.net/music/Volcano.mp3">2. Volcano
</a>
 />

 href="http://galeki.xy568.net/music/The Blower's Daughter.mp3">3. The Blower's Daughter
</a>
 />

 href="http://galeki.xy568.net/music/Cannonball.mp3">4. Cannonball 
</a>
 />

 href="http://galeki.xy568.net/music/Older Chests.mp3">5. Order Chests
</a>
 />

 href="http://galeki.xy568.net/music/Amie.mp3">6. Amie
</a>
 />

 href="http://galeki.xy568.net/music/Cheers Darlin'.mp3">7. Cheers Darling
</a>
 />

 href="http://galeki.xy568.net/music/Cold Water.mp3">8. Cold water
</a>
 />

 href="http://galeki.xy568.net/music/I Remember.mp3">9. I remember
</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等等等等, 不过使用方法和上面的基本相同,不再多写了。

本文转sinojelly51CTO博客,原文链接:http://blog.51cto.com/pnig0s1992/412049,如需转载请自行联系原作者

你可能感兴趣的文章
SpringBoot之集成swagger2
查看>>
Mysql之Centos7下yum安装mysql5.6
查看>>
转 字符串模式匹配算法——BM、Horspool、Sunday、KMP、KR、AC算法
查看>>
一种基于云存储架构的开放电子病历平台
查看>>
陶哲轩实分析习题9.8.5 : 在有理点间断,无理点连续的严格单调函数
查看>>
五本珍稀数学电子书出售
查看>>
公司项目git开发流程规范
查看>>
Google今日更新了全球排名前100名的网站排行版
查看>>
传奇世界RollBall设计
查看>>
JS-元素大小深入学习-offset、client、scroll等学习研究笔记
查看>>
shell script中引号的用法
查看>>
实验3
查看>>
脚本执行策略设置
查看>>
接口和抽象类是否继承了Object
查看>>
Angular.js+Bootstrap实现表格分页
查看>>
面试题10-二进制中1的个数
查看>>
ahjesus 让Boot Camp支持创建win7 u盘安装盘
查看>>
(3)合并列值与分拆列值
查看>>
C# 核心编程结构Ⅱ 笔记
查看>>
OCP最新题库052考题解析及答案-第37题
查看>>