html.parser是一个非常简单和实用的库,它的核心是HTMLParser类。

工作的流程是:当你feed给它一个类似HTML格式的字符串时,它会调用goahead方法向前迭代各个标签,并调用对应的parse_xxxx方法提取start_tag, tag, attrs data comment和end_tag等等标签信息和数据,然后调用对应的方法对这些抽取出来的内容进行处理。整个HTMLParser的大致结构如下图所示:

可以发现,处理开始标签(handle_starttag)、结束标签(handle_endtag)和处理数据(handle_data)等处理函数在HTMLParser里是没有实现的(pass),这需要我们继承HTMLParser这个类的并覆盖这些方法。详细可以参阅python文档,https://docs.python.org/3/library/html.parser.html?highlight=htmlparser

一、常用方法介绍

l feed(data):主要用于接受带html标签的str,当调用这个方法时并提供相应的data时,整个实例(instance)开始执行,结束执行close()。

l handle_starttag(tag, attrs): 这个方法接收Parse_starttag返回的tag和attrs,并进行处理,处理方式通常由使用者进行覆盖,本身为空。

例如,连接的start tag是<a>,那么对应的参数tag=’a’(小写)。attrs是start tag <>中的属性,以元组形式(name, value)返回(所有这些内容都是小写)。

例如,对于<A HREF="http://www.baidu.com“>,那么内部调用形式为:handle_starttag(’a’,[(‘href’,’http://www.baidu.com)]).

l handle_endtag(tag):跟上述一样,只是处理的是结束标签,也就是以</开头的标签。

l handle_data(data):处理的是网页的数据,也就是开始标签和结束标签之间的内容。例如:<script>...</script>的省略号内容

l handle_comment(data) ,处理注释,<!-- -->之间的文本

l reset():将实例重置,包括作为参数输入的数据进行清空。

二、基本使用

from html.parser import HTMLParser

class MyHTMLParser(HTMLParser):
def handle_starttag(self, tag, attrs):
"""
recognize start tag, like <div>
:param tag:
:param attrs:
:return:
"""
print("Encountered a start tag:", tag) def handle_endtag(self, tag):
"""
recognize end tag, like </div>
:param tag:
:return:
"""
print("Encountered an end tag :", tag) def handle_data(self, data):
"""
recognize data, html content string
:param data:
:return:
"""
print("Encountered some data :", data) def handle_startendtag(self, tag, attrs):
"""
recognize tag that without endtag, like <img />
:param tag:
:param attrs:
:return:
"""
print("Encountered startendtag :", tag) def handle_comment(self,data):
"""
:param data:
:return:
"""
print("Encountered comment :", data) parser = MyHTMLParser()
parser.feed('<html><head><title>Test</title></head>'
'<body><h1>Parse me!</h1><img src = "" />'
'<!-- comment --></body></html>')

以上是根据python手册写的基本使用,解析了一个简单的html。可以运行看看,主要用于了解各个函数负责解析的部分,以及解析顺序

Encountered a start tag: html
Encountered a start tag: head
Encountered a start tag: title
Encountered some data : Test
Encountered an end tag : title
Encountered an end tag : head
Encountered a start tag: body
Encountered a start tag: h1
Encountered some data : Parse me!
Encountered an end tag : h1
Encountered startendtag : img
Encountered comment : comment
Encountered an end tag : body
Encountered an end tag : html

三、实用案例

以下的实用案例均在上面的代码中修改对应函数,每个实例都是单独的。

解析的html如下

<html>
<head>
<title>Test</title>
</head>
<body>
<h1>Parse me!</h1>
<img src = "" />
<p class='123'>A paragraph.</p>
<p class = "p_font">A paragraph with class.</p>
<!-- comment -->
<div>
<p>A paragraph in div.</p>
</div>
</body>
</html>

1.获取所有p标签的文本,最简单方法只修改handle_data

def handle_data(self, data):
if self.lasttag == 'p':
print("Encountered p data :", data)

2.获取css样式(class)为p_font的p标签的文本,使用了案例1,增加一个实例属性作为标志,选取需要的标签

def __init__(self):
HTMLParser.__init__(self)
self.flag = False def handle_starttag(self, tag, attrs):
for attr in attrs:
if tag == 'p' and attr[1]=='"p_font":
self.flag = True def handle_data(self, data):
if self.flag == True:
print("Encountered p data :", data)

3.获取p标签的属性列表

def handle_starttag(self, tag, attrs):
if tag == 'p':
print("Encountered p attrs :", attrs)

4.获取p标签的class属性

def handle_starttag(self, tag, attrs):
for attr in attrs:
If tag == 'p' and attr[0]= 'class'):
print("Encountered p class :", attr[1])

5.获取div下的p标签的文本

def __init__(self):
HTMLParser.__init__(self)
self.in_div = False def handle_starttag(self, tag, attrs):
if tag == 'div':
self.in_div = True def handle_data(self, data):
if self.in_div == True and self.lasttag == 'p':
print("Encountered p data :", data)
self.in_div = False

6.处理注释中的标签,若需要的数据在注释中,使用一般函数解析不到

处理方法为,写两个类,继承HTMLParser。在其中一个类的handle_comment里实例化解析类,和其他标签一样解析

def __init__(self):
HTMLParser.__init__(self) def handle_comment(self,data):
print(("Encountered comment:",data)

完整实例

例如:我们有以下一堆带HTML标签的数据

html = '''<h3 class="tb-main-title" data-title="Xiaomi/小米">
【金冠现货/全色/顶配版】Xiaomi/小米 小米note移动联通4G手机
</h3>
<p class="tb-subtitle">
【购机即送布丁套+高清贴膜+线控耳机+剪卡器+电影支架等等,套餐更多豪礼更优惠】
</p>
<div id="J_TEditItem" class="tb-editor-menu"></div>
</div>
<h3 class="tb-main-title" data-title="MIUI/小米">
【现货增强/标准】MIUI/小米 红米手机2红米2移动联通电信4G双卡
</h3>
<p class="tb-subtitle">
[红米手机2代颜色版本较多,请亲们阅读购买说明按需选购---感谢光临]
<div id="J_TEditItem" class="tb-editor-menu"></div>
</div>'''

很明显,这里面包含了两台手机,我们的目标是提取两个手机的名字出来。

由于当我们feed这个html到HTMLParser中后,他们所有的标签都迭代,如果需要它只提取我们需要的数据时,我们需要设置当handle_starttag遇到那个标签和属性时,才调用handle_data并print出我们的结果,这个时候我们可以使用一个flag作为判定,代码如下:

#定义一个MyParser继承自HTMLParser
class MyParser(HTMLParser):
re=[]#放置结果
flag=0#标志,用以标记是否找到我们需要的标签
def handle_starttag(self, tag, attrs):
if tag=='p':#目标标签
for attr in attrs:
if attr[0]=='class' and attr[1]=='tb-subtitle':#目标标签具有的属性
self.flag=1#符合条件则将标志设置为1
break
else:
pass def handle_data(self, data):
if self.flag==1:
self.re.append(data.strip())#如果标志为我们设置的,则将数据添加到列表中
self.flag=0#重置标志,进行下次迭代
else:
pass my=MyParser()
my.feed(html)
my.re

运行结果如下,达到了我们的预期:

['【购机即送布丁套+高清贴膜+线控耳机+剪卡器+电影支架等等,套餐更多豪礼更优惠】',

'[红米手机2代颜色版本较多,请亲们阅读购买说明按需选购---感谢光临]']

python模块之HTMLParser简介的更多相关文章

  1. python模块介绍- HTMLParser 简单的HTML和XHTML解析器

    python模块介绍- HTMLParser 简单的HTML和XHTML解析器 2013-09-11 磁针石 #承接软件自动化实施与培训等gtalk:ouyangchongwu#gmail.comqq ...

  2. python模块之HTMLParser(原理很大程度上就是对类构造的熟练运用)

    # -*- coding: utf-8 -*- #python 27 #xiaodeng #python模块之HTMLParser(原理很大程度上就是对类构造的熟练运用) import HTMLPar ...

  3. python模块之HTMLParser之穆雪峰的案例(理解其用法原理)

    # -*- coding: utf-8 -*- #python 27 #xiaodeng #python模块之HTMLParser之穆雪峰的案例(理解其用法原理) #http://www.cnblog ...

  4. python模块之HTMLParser抓页面上的所有URL链接

    # -*- coding: utf-8 -*- #python 27 #xiaodeng #python模块之HTMLParser抓页面上的所有URL链接 import urllib #MyParse ...

  5. python模块之HTMLParser解析出URL链接

    # -*- coding: utf-8 -*- #python 27 #xiaodeng #python模块之HTMLParser解析出URL链接 #http://www.cnblogs.com/mf ...

  6. python模块之HTMLParser

    HTMLParser是python用来解析html的模块.它可以分析出html里面的标签.数据等等,是一种处理html的简便途径. HTMLParser采用的是一种事件驱动的模式,当HTMLParse ...

  7. python模块学习---HTMLParser(解析HTML文档元素)

    HTMLParser是Python自带的模块,使用简单,能够很容易的实现HTML文件的分析. 本文主要简单讲一下HTMLParser的用法. 使用时需要定义一个从类HTMLParser继承的类,重定义 ...

  8. python模块——PrettyTable

    python模块——PrettyTable 一. 简介 Python通过prettytable模块将输出内容如表格方式整齐输出,可用来生成美观的ASCII格式的表格,十分实用. python本身并不内 ...

  9. 6.文件所有权和权限----免费设置匿名----Windows键盘记录器----简介和python模块

    文件所有权和权限 touch --help cd Desktop mkdir Folder cd Folder clear touch Test1 Test2 Test3 Test4 ls ls -l ...

随机推荐

  1. 窗体控件JFrame的使用

    ---------------siwuxie095 工程名:TestUI 包名:com.siwuxie095.ui 类名:MyFrame.java 工程结构目录如下: 在 Source 界面和 Des ...

  2. 2015年阿里实习生面试Java研发工程师 小记

    5月5日,广州,阿里实习生面试,Java研发工程师,完全被虐orz 几乎没有Java项目开发经验,接近零基础,去水了一发,毫无悬念的被刷了..RP也是杠杠的,准备过的题目一个都没被问到,算法题也是一条 ...

  3. STL-- vector中resize()和reserve()区别

    最近写了一个小型的STL--TinySTL.发现有一些基础的东西需要记录下来,所以我打算多写一些东西,方便以后查看. 先看看<C++ Primer>中对resize()函数两种用法的介绍: ...

  4. 《Effective Java》第11章 序列化

    "将一个对象编码成一个字节流",称作将该对象序列化(serializing); 相反的处理过程被称作反序列化(deserializing),一旦对象被序列化后,它的编码就可以从一台 ...

  5. excel导入工具

    1 介绍 excel导入工具 整个项目的代码结构如下 \---excelExport # 导出工具包 | AsyncExportExcel.java #多线程导出 | ExcelImport.java ...

  6. java eclipse导出可运行jar包(java服务)和导入

    java   eclipse导出可运行jar包(java服务)和导入 二.导出可运行包步骤: 1.选择要导出的项目:  2.右键项目-单击export:  3.选择导出类型:(Runnable JAR ...

  7. OC 语言新特性

    前言 相对于 Java,OC 语言是一门古老的语言了,而它又是一门不断发展完善的语言.一些新的编译特性,为 OC 语言带来了许多新的活力. 在 Xcode7 中,iOS9 的 SDK 已经全面兼容了 ...

  8. utf-8-BOM删除bom

    utf-8  bom,去除bom //开始 function file_bom($wenjian,$remove = true) { //读取文件,将文件写入字符串    $contents = fi ...

  9. loj #2044. 「CQOI2016」手机号码

    #2044. 「CQOI2016」手机号码 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据   题目描述 ...

  10. loj#6363. 「地底蔷薇」(拉格朗日反演+多项式全家桶)

    题面 传送门 题解 肝了一个下午--我老是忘了拉格朗日反演计算的时候多项式要除以一个\(x\)--结果看它推倒简直一脸懵逼-- 做这题首先你得知道拉格朗日反演是个什么东西->这里 请坐稳,接下来 ...