python中,有三个库可以解析html文本,HTMLParser,sgmllib,htmllib。他们的实现方法不通,但功能差不多。这三个库中 提供解析html的类都是基类,本身并不做具体的工作。他们在发现的元件后(如标签、注释、声名等),会调用相应的函数,这些函数必须重载,因为基类中不 作处理。

比如:

"""<html><head><title>Advice</title></head><body>
<p>The <a href="http://ietf.org">IETF admonishes:
<i>Be strict in what you <b>send</b>.</i></a></p>
<form>
<input type=submit >  <input type=text name=start size=4></form>
</body></html>
"""

如果对这个数据做处理,当检测到<html>标签时,对于HTMLParser,会调用handle_starttag函数。

下面具体介绍下几个库

1、HTMLParser

  1. #------------------ HTMLParser_stack.py ------------------#
  2. #-- coding: GBK --
  3. import HTMLParser,sys,os,string
  4. html = """<html><head><title>Advice</title></head><body>
  5. <p>The <a href="http://ietf.org" mce_href="http://ietf.org">IETF admonishes:
  6. <i>Be strict in what you <b>send</b>.</i></a></p>
  7. <form>
  8. <input type=submit >  <input type=text name=start size=4></form>
  9. </body></html>
  10. """
  11. tagstack = []
  12. class ShowStructure(HTMLParser.HTMLParser):
  13. def handle_starttag(self, tag, attrs): tagstack.append(tag)
  14. def handle_endtag(self, tag): tagstack.pop()
  15. def handle_data(self, data):
  16. if data.strip():
  17. for tag in tagstack: sys.stdout.write('/'+tag)
  18. sys.stdout.write(' >> %s/n' % data[:40].strip())
  19. ShowStructure().feed(html)

此函数的输出:

/html/body/p >> The
/html/body/p/a >> IETF admonishes:
/html/body/p/a/i >> Be strict in what you
/html/body/p/a/i/b >> send
/html/body/p/a/i >> .

对于一些网页,可能并没有严格的开始结束标签对,这时,我们可以去忽略一些标签。可以自己写个堆栈来处理这些标签。

  1. #*--------------- TagStack class example -----------------#
  2. class TagStack:
  3. def __init__(self, lst=[]): self.lst = lst
  4. def __getitem__(self, pos): return self.lst[pos]
  5. def append(self, tag):
  6. # Remove every paragraph-level tag if this is one
  7. if tag.lower() in ('p','blockquote'):
  8. self.lst = [t for t in self.lst
  9. if t not in ('p','blockquote')]
  10. self.lst.append(tag)
  11. def pop(self, tag):
  12. # "Pop" by tag from nearest pos, not only last item
  13. self.lst.reverse()
  14. try:
  15. pos = self.lst.index(tag)
  16. except ValueError:
  17. raise HTMLParser.HTMLParseError, "Tag not on stack"
  18. del self.lst[pos]
  19. self.lst.reverse()
  20. tagstack = TagStack()

HTMLParser有个bug,就是不能处理中文属性,比如说,如果网页里有这么一段:

<input type=submit value=跳转到>

那么解析到这一行时就会出错。

错误原因还是正则表达式惹的祸。
 
attrfind = re.compile(
    r'/s*([a-zA-Z_][-.:a-zA-Z_0-9]*)(/s*=/s*'
    r'(/'[^/']*/'|"[^"]*"|[-a-zA-Z0-9./,:;+*%?!&$/(/)_#=~@]*))?') 
attrfind 没有匹配中文字符。

可以更改这个匹配已修正这个错误。sgmllib则不存在这种错误。

2、sgmllib

html格式为sgml格式的一个子集,所以sgml可以处理跟多的东西,下面通过一段代码来示例sgmllib的用法。

  1. #------------------ HTMLParser_stack.py ------------------#
  2. #-- coding: GBK --
  3. import sgmllib,sys,os,string
  4. html = """<lala><head><title>Advice</title></head><body>
  5. <p>The <a href="http://ietf.org" mce_href="http://ietf.org">IETF admonishes:
  6. <i>Be strict in what you <b>send</b>.</i></a></p>
  7. <form>
  8. <input type=submit name='我'> 我 <input type=text name=start size=4></form>
  9. </body></lala>
  10. """
  11. os.chdir('d://python')
  12. f=file('testboard.txt','r')
  13. contest=f.read()
  14. tagstack = []
  15. class ShowStructure(sgmllib.SGMLParser):
  16. def handle_starttag(self, tag, method,attrs): tagstack.append(tag)
  17. def handle_endtag(self, tag): tagstack.pop()
  18. def handle_data(self, data):
  19. if data.strip():
  20. for tag in tagstack: sys.stdout.write('/'+tag)
  21. sys.stdout.write(' >> %s/n' % data[:40].strip())
  22. def unknown_starttag(self,tag,attrs):
  23. print 'start tag:<'+tag+'>'
  24. def unknown_endtag(self,tag):
  25. print 'end tag:</'+tag+'>'
  26. def start_lala(self,attr):
  27. print 'lala tag found'
  28. ShowStructure().feed(html)

输出:

start tag:<head>
start tag:<title>
/lala >> Advice
end tag:</title>
end tag:</head>
start tag:<body>
start tag:<p>
/lala >> The
start tag:<a>
/lala >> IETF admonishes:
start tag:<i>
/lala >> Be strict in what you
start tag:<b>
/lala >> send
end tag:</b>
/lala >> .
end tag:</i>
end tag:</a>
end tag:</p>
start tag:<form>
start tag:<input>
/lala >> ϒ
start tag:<input>
end tag:</form>
end tag:</body>
end tag:</lala>

和HTMLParser一样,如果要用sgmllib解析html,则要继承sgmllib.SGMLParser类,此类里的函数都是空的,用户需要重载它。这个类提供的功能是在特定情况下调用相应的函数。

比如当发现<html>标签时,如果并没有定义 start_html(self,attr)函数,则会调用unknown_starttag函数,具体怎么处理则更具用户。

sgml的标签是可以自定义的,比如自己定义了一个start_lala函数,则就会处理<lala>标签。

有 个地方要说明下,如果定义了start_tagname函数,有定义了handle_starttag函数,则函数只会运行 handle_starttag函数,start_tagname为空函数都没有问题,如果没有定义handle_starttag函数,则遇 到<tagname>标签时,会运行start_tagname函数。如果没有定义tagname的start函数,则此标签为未知标签,调 用unknown_starttag函数

用python解析html的更多相关文章

  1. 使用Python解析JSON数据

    使用Python解析百度API返回的JSON格式的数据 # coding:utf-8 # !/usr/bin/env python import matplotlib.pyplot as plt fr ...

  2. 使用Python解析JSON数据的基本方法

    这篇文章主要介绍了使用Python解析JSON数据的基本方法,是Python入门学习中的基础知识,需要的朋友可以参考下:     ----------------------------------- ...

  3. python解析robot framework的output.xml,并生成html

    一.背景 Jenkins自动构建RF脚本,生成的RF特有HTML报告不能正常打开. 需求:用Python解析测试报告的xml数据,放在普通HTML文件中打开 二.output.xml数据 三.用pyh ...

  4. python 解析json loads dumps

    认识 引用模块 重要函数 案例 排序 缩进参数 压缩 参考 认识 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.它基于JavaScript(Standa ...

  5. Python解析器源码加密系列之(二):一次使用标准c的FILE*访问内存块的尝试

    摘要:由于近期打算修改Python解释器以实现pyc文件的加密/解密,出于保密的要求,解密之后的数据只能放在内存中,不能写入到文件中.但是后续的解析pyc文件的代码又只能接受FILE*作为入参,所以就 ...

  6. python 解析XML python模块xml.dom解析xml实例代码

    分享下python中使用模块xml.dom解析xml文件的实例代码,学习下python解析xml文件的方法. 原文转自:http://www.jbxue.com/article/16587.html ...

  7. python解析xml模块封装代码

    在python中解析xml文件的模块用法,以及对模块封装的方法.原文转自:http://www.jbxue.com/article/16586.html 有如下的xml文件:<?xml vers ...

  8. python解析xml之lxml

    虽然python解析xml的库很多,但是,由于lxml在底层是用C语言实现的,所以lxml在速度上有明显优势.除了速度上的优势,lxml在使用方面,易用性也非常好.这里将以下面的xml数据为例,介绍l ...

  9. Python解析生成XML-ElementTree VS minidom

    OS:Windows 7 关键字:Python3.4,XML,ElementTree,minidom 本文介绍用Python解析生成以下XML: <Persons> <Person& ...

  10. python解析xml

    python解析xml import xml.dom.minidom as minidom dom = minidom.parse("aa.xml") root = dom.get ...

随机推荐

  1. Windows 8.1 IIS 8.5 远程管理 Windows 2008 R2 IIS 7.0

    案例: Windows 8.1 x64 IIS 8.5 inetmgr_amd64_v1.1_en-US.msi Windows 2008 R2  x64 IIS  7.0 在Win8.1 通过IIS ...

  2. zookeeper集群搭建设置

    zookeeper 官网:http://zookeeper.apache.org/ 现在最新版本是 3.4.6 ,但是这个版本我没有运行起来,可能是那配置出现问题了,现在我用的是3.4.5 http: ...

  3. 再探java基础——break和continue的用法

    再探java基础——break和continue的用法 break break可用于循环和switch...case...语句中. 用于switch...case中: 执行完满足case条件的内容内后 ...

  4. Hello China操作系统STM32移植指南(一)

    Hello China操作系统移植指南 首先说明一下,为了适应更多的文化背景,对Hello China操作系统的名字做了修改,修改为"Hello X",或者连接在一起,写为&quo ...

  5. 将文件从数据库(MySQL)中进行读取

    package com.play; import java.io.FileOutputStream; import java.io.OutputStream; import java.sql.Blob ...

  6. Linux命令压缩与解压缩

    zip格式的文件:zip和unzip zip 命令: # zip test.zip test.txt 它会将 test.txt 文件压缩为 test.zip ,当然也可以指定压缩包的目录,例如 /ro ...

  7. 部署django - Apache + mod_wsgi + windows

    部署django - Apache + mod_wsgi + windows 1.环境 django 1.6.2 python 3.3 32位 apache 2.4.7 32位 一个可以使用的djan ...

  8. ligh@local-host$ ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.0.3

    ligh@local-host$ ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.0.3

  9. 戴尔CEO:我们将专注于企业 而非手机业务

    9月13日消息,据国外媒体报道,戴尔公司董事长兼首席执行官迈克尔·戴尔(Michael Dell)周五接受了CNBC采访,谈了他对戴尔未来的打算.此前一天,迈克尔·戴尔提出的以250亿美元将戴尔私有化 ...

  10. cocos2D(二)---- cocos2D文档的使用

    在使用cocos2d进行游戏开发的过程中,难免要查阅cocos2d的API文档.搞清楚怎么使用某个类或者某个方法.幸运的是,cocos2d的作者已经在源码里面加入了文档凝视,我们仅仅须要使用文档生成工 ...