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

[python] view plaincopy
  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 >> .

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

[python] view plaincopy
  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的用法。

[python] view plaincopy
  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,如需转载请自行联系原博主。

用python解析html相关推荐

  1. python解析response_python:解析requests返回的response(json格式)说明

    我就废话不多说了,大家还是直接看代码吧! import requests, json r = requests.get("http://192.168.207.160:9000/api/qu ...

  2. python解析json_python解析json文件

    概念 序列化(Serialization):将对象的状态信息转换为可以存储或可以通过网络传输的过程,传输的格式可以是JSON.XML等.反序列化就是从存储区域(JSON,XML)读取反序列化对象的状态 ...

  3. python 解析xml

    在工作中很多时候都要用到xml,使用这个时候难免会设计到解析他,然后就研究了一下python解析xml问题,看了很多东西,python有很多解析xml的包,但是也折腾我好一段时间,最后选择了这个方法. ...

  4. python 读取文件读出来是什么格式-深入学习python解析并读取PDF文件内容的方法...

    这篇文章主要学习了python解析并读取PDF文件内容的方法,包括对学习库的应用,python2.7和python3.6中python解析PDF文件内容库的更新,包括对pdfminer库的详细解释和应 ...

  5. python中读取文件内容-深入学习python解析并读取PDF文件内容的方法

    这篇文章主要学习了python解析并读取PDF文件内容的方法,包括对学习库的应用,python2.7和python3.6中python解析PDF文件内容库的更新,包括对pdfminer库的详细解释和应 ...

  6. python 命令-python解析命令行参数的三种方法详解

    这篇文章主要介绍了python解析命令行参数的三种方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 python解析命令行参数主要有三种方法: ...

  7. 【Android 逆向】使用 Python 解析 ELF 文件 ( Capstone 反汇编 ELF 文件中的机器码数据 | 完整代码示例 ) ★★★

    文章目录 一.完整代码示例 二.执行结果 三.博客资源 一.完整代码示例 使用 Python 解析 ELF 文件完整代码示例 : # coding=utf-8 # 解析 elf 文件需要导入的依赖库 ...

  8. python 解析xml格式_Python解析XML文件

    1.概述 Python有三种方法解析XML:SAX,DOM,以及ElementTree: 1.SAX (simple API for XML ) python 标准库包含SAX解析器,SAX用事件驱动 ...

  9. python解析log文件_python解析基于xml格式的日志文件

    大家中午好,由于过年一直还没回到状态,好久没分享一波小知识了,今天,继续给大家分享一波Python解析日志的小脚本. 首先,同样的先看看日志是个啥样. 都是xml格式的,是不是看着就头晕了??没事,我 ...

  10. [系统安全] 四十一.APT系列(6)Python解析PE文件并获取时间戳判断来源区域

    您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列.因此,我重新开设了这个专栏,准备系统整理和深入学习系统安全.逆向分 ...

最新文章

  1. CMakeLists
  2. Linux 终端显示 Git 当前所在分支
  3. 《LeetCode力扣练习》第206题 反转链表 Java
  4. Linux环境下安装jenkins
  5. linux之ps命令详解
  6. 前端学习(2751):uni-app目录设置
  7. Hbase1.2数据导入2.0
  8. CUBLAS变量解释(1)
  9. leetcode971. Flip Binary Tree To Match Preorder Traversal
  10. 对聚集表查询的时候,未显式指定排序列的时候,默认查询结果的顺序一定是按照聚集索引顺序排序的吗...
  11. Sublime text的必要配置
  12. 夜,依旧寂寞心照不宣!
  13. 全面了解风控策略体系
  14. Jenkins 与 Gitlab 之间非交互拉取代码并进行代码部署
  15. 搬家公司怎么收费 搬家收费标准
  16. uniapp之登录(短信验证码,账号密码,第三方登录)
  17. 中国家庭收入调查(CHIP)数据88-13年
  18. 小程序开发问题之textarea层次问题
  19. 在 iOS 平台开发应用并发布到 App Store 上销售,要走哪些流程
  20. Semantic UI 之 菜单 menu

热门文章

  1. nginx集群报错“upstream”directive is not allow here 错误 [
  2. 命令行中,变量 date time 格式化设定
  3. 服务器端口映射到公网不通解决方法
  4. R+markdown+LaTeX 中文编译解决方案
  5. 有未经处理的异常(在 xx.exe 中): 堆栈 Cookie 检测代码检测到基于堆栈的缓冲区溢出。
  6. error Microsoft Visual C++ 14.0 is required 解决方案
  7. wepy一些问题和解决方案
  8. 在Vim中上下移动整条线
  9. 你如何在PowerShell中注释掉代码?
  10. sqlserver的存储过程mysql_mysql,sqlserver存储过程的创建及执行