设为首页 收藏本站
查看: 1006|回复: 0

[经验分享] 用python解析html[SGMLParser]

[复制链接]

尚未签到

发表于 2018-8-4 13:49:48 | 显示全部楼层 |阅读模式
  因为要用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),  ...]的形式传回,我们要做的就是在其子类重载自己感兴趣标签对应的函数。
  一个经典的例子:

  • from sgmllib import SGMLParser
  • class URLLister(SGMLParser):
  •     self.urls = []
  •     def start_a(self,  attrs):
  •         href = [v for k, v in attrs if k=='href']
  •         if href:
  •             self.urls.extend(href)
  顾名思义,这个类的作用就是把html中的所有连接(<a>标签)中的地址(href属性的值)提取出来,放到一个list里面,很实 用的功能。^^
  比如处理下面的html:
<tr>
  <td>  <p>Damien Rice  - 《0》 </p>
  <a href=&quot;http://galeki.xy568.net/music/Delicate.mp3&quot;>1.  Delicate</a><br />
  <a href=&quot;http://galeki.xy568.net/music/Volcano.mp3&quot;>2.  Volcano</a><br />
  <a href=&quot;http://galeki.xy568.net/music/The  Blower's Daughter.mp3&quot;>3. The Blower's Daughter</a><br />
  <a href=&quot;http://galeki.xy568.net/music/Cannonball.mp3&quot;>4.  Cannonball </a><br />
  <a href=&quot;http://galeki.xy568.net/music/Older  Chests.mp3&quot;>5.  Order Chests</a><br />
  <a href=&quot;http://galeki.xy568.net/music/Amie.mp3&quot;>6.  Amie</a><br />
  <a href=&quot;http://galeki.xy568.net/music/Cheers  Darlin'.mp3&quot;>7. Cheers Darling</a><br />
  <a href=&quot;http://galeki.xy568.net/music/Cold  Water.mp3&quot;>8.  Cold water</a><br />
  <a href=&quot;http://galeki.xy568.net/music/I  Remember.mp3&quot;>9. I remember</a><br />
  <a href=&quot;http://galeki.xy568.net/music/Eskimo.mp3&quot;>10.  Eskimo</a></p>
  </td>
  </tr>
  很乱对吧?下面让举个例子利用URLLister提取出上面mp3下载的地址:

  • date=&quot;上面那一堆…………&quot;
  • lister=URLLister()
  • lister.feed(date)
  用feed()把要处理的html传递给对象实体,然后我们来看看处理结果:

  • print lister.urls
  显示:
['http://galeki.xy568.net/music/Delicate.mp3',  'http://galeki.xy568.net/music/Volcano.mp3',
  &quot;http://galeki.xy568.net/music/The  Blower's Daughter.mp3&quot;,
  'http://galeki.xy568.net/music/Cannonball.mp3',
  'http://galeki.xy568.net/music/Older  Chests.mp3',
  'http://galeki.xy568.net/music/Amie.mp3',
  &quot;http://galeki.xy568.net/music/Cheers  Darlin'.mp3&quot;,
  '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,用做标记的方法来达到这个目的:

  • class ListName(SGMLParser):
  •     is_a=&quot;&quot;
  •     name=[]
  •     def start_a(self,  attrs):
  •         self.is_a=1
  •     def end_a(self):
  •         self.is_a=&quot;&quot;
  •     def handle_data(self,  text):
  •         if self.is_a:
  •                 self.name.append(text)
  这里添加了一个is_a标记,再在handle_date中添加一个if,也就是说,仅仅在a标签内,才会把标签里的内容加到name[]里去。
  看看结果:

  • listname=ListName()
  • listname.feed(date)
  • print listname.name
  显示:
['1.Delicate',  '2.Volcano', &quot;3.The Blower's Daughter&quot;,  '4.Cannonball ', '5.Order Chests', '6.Amie',
  '7.Cheers Darling', '8.Cold water', '9.I remember',
  '10.Eskimo']
  OK,搞定~
  SGMLParser内置的方法不仅仅只有这三个,还有处理注释的handle_comment,还有处理声明的handle_decl等等等等, 不过使用方法和上面的基本相同,不再多写了。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-546542-1-1.html 上篇帖子: Installing Odoo 8 on CentOS 6 with Python 2.7-Permanent 下篇帖子: Python八荣八耻
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表