Html / XHtml 解析 - Parsing Html and XHtml
Html / XHtml 解析 - Parsing Html and XHtml
HTMLParser 模块
通过 HTMLParser 模块来解析 html 文件通常的做法是, 建立一个 HTMLParser 子类,
然后子类中实现处理的标签(<.>)的方法, 其实现是通过 '重写' 父类(HTMLParser)的
handle_starttag(), handle_data(), handle_endtag() 等方法. 例子,
解析 htmlsample.html 中 <head> 标签,
<-- htmlsample.html --> -> 文件内容,
'
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.12.2</center>
</body>
</html>
'
from html.parser import HTMLParser
class ParsingHeadT(HTMLParser):
def __init__(self):
self.headtag =''
self.parsesemaphore = False
HTMLParser.__init__(self) def handle_starttag(self, tag, attrs): # enable semaphore
if tag == 'head':
self.parsesemaphore = True def handle_data(self, data): # tag process as requirement
if self.parsesemaphore:
self.headtag = data def handle_endtag(self, tag):
if tag == 'head':
self.parsesemaphore = False def getheadtag(self):
return self.headtag if __name__ == "__main__":
with open('htmlsample.html') as FH:
pht = ParsingHeadT()
pht.feed(FH.read()) # HTMLParser will invoke the replaced methods
# handle_starttag, handle_data and handle_endtag
print("Head Tag : %s" % pht.getheadtag()) output,
Head Tag : 404 Not Found 上例是一个简单完成的 html 文本, 然而在实际生产中是有一些实现情况要考虑和处理的,
比如 html 中的特殊字符 © (copyright 符号), &(& 逻辑与符号) 等,
对于这种情况, 之前的做法是需要重写父类的 handle_entityref() 来处理,
HTMLParser.handle_entityref(name)¶
This method is called to process a named character reference of the form
&name; (e.g. >), where name is a general entity reference (e.g. 'gt').
This method is never called if convert_charrefs is True. 字符转换 也是一种需要注意的情况, 比如 十进制 decimal 和 十六进制 hexadecimal 字符的转换.
HTMLParser.handle_charref(name)
This method is called to process decimal and hexadecimal numeric character
references of the form &#NNN; and &#xNNN;. For example, the decimal equivalent
for > is >, whereas the hexadecimal is > in this case the method
will receive '' or 'x3E'. This method is never called if convert_charrefs is True. Note,
幸运的是,以上情况在 python 3 已经能很好得帮我们处理了. 还是使用上例, 现在我们在 htmlsample.html
<head> tag 中加入一些特殊字符来看看.
<-- htmlsample.html -->
<html>
<head><title>> > 404 © Not > Found & </title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.12.2</center>
</body>
</html> 上例 Output,
Head Tag : > > 404 © Not > Found &
从运行结果可以看出, 在 python 3 中上例能够很好的处理特殊字符的情况. 然而, 在 html 的代码中存在一类 '非对称'的标签, 如 <p>, <li> 等, 当我们试图使用上面的例子
去处理这类非对称标签的时候发现, 这类标签并不能被上例正确解析. 这时我们需要扩展上例的 code 使
其能够正确解析这些'非对称'标签.
先扩展一下儿 htmlsample.html, 以 <li> 标签为例,
<-- htmlsample.html -->
<html>
<head><title>> > 404 © Not > Found &</title>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.12.2</center>
<ul>
<li> First Reason
<li> Second Reason
</body>
</html> htmlsample.html 文件是可以被浏览器渲染的, 然而 htmlsample.html 中 <head> 和 <ul> 标签
没有对应的结束 tag, <li> 为非对称的 tag. 现在来向之前的例子添加一些逻辑来处理这些问题. 例,
from html.parser import HTMLParser
class Parser(HTMLParser):
def __init__(self):
self.taglevels = [] # track anchor
self.tags =['head','ul','li']
self.parsesemaphore = False
self.data = ''
HTMLParser.__init__(self) def handle_starttag(self, tag, attrs): # enable semaphore
if len(self.taglevels) and self.taglevels[-1] == tag:
self.handle_endtag(tag)
self.taglevels.append(tag) if tag in self.tags:
self.parsesemaphore = True def handle_data(self, data): # tag process as requirement
if self.parsesemaphore:
self.data += data def handle_endtag(self, tag):
self.parsesemaphore = False def gettag(self):
return self.data if __name__ == "__main__":
with open('htmlsample.html') as FH:
pht = Parser()
pht.feed(FH.read()) # HTMLParser will invoke the replaced methods
# handle_starttag, handle_data and handle_endtag
print("Head Tag : %s" % pht.gettag()) Output,
Head Tag : > > 404 © Not > Found &
First Reason
Second Reason Reference,
https://docs.python.org/3.6/library/html.parser.html?highlight=htmlparse#html.parser.HTMLParser.handle_entityref Appendix,
The example given by python Doc,
from html.parser import HTMLParser
from html.entities import name2codepoint class MyHTMLParser(HTMLParser):
def handle_starttag(self, tag, attrs):
print("Start tag:", tag)
for attr in attrs:
print(" attr:", attr) def handle_endtag(self, tag):
print("End tag :", tag) def handle_data(self, data):
print("Data :", data) def handle_comment(self, data):
print("Comment :", data) def handle_entityref(self, name):
c = chr(name2codepoint[name])
print("Named ent:", c) def handle_charref(self, name):
if name.startswith('x'):
c = chr(int(name[1:], 16))
else:
c = chr(int(name))
print("Num ent :", c) def handle_decl(self, data):
print("Decl :", data) parser = MyHTMLParser() Output,
Parsing a doctype: # >>> parser.feed('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" '
... '"http://www.w3.org/TR/html4/strict.dtd">')
Decl : DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"
Parsing an element with a few attributes and a title: # >>> parser.feed('<img src="python-logo.png" alt="The Python logo">')
Start tag: img
attr: ('src', 'python-logo.png')
attr: ('alt', 'The Python logo') # >>> parser.feed('<h1>Python</h1>')
Start tag: h1
Data : Python
End tag : h1
The content of script and style elements is returned as is, without further parsing: # >>> parser.feed('<style type="text/css">#python { color: green }</style>')
Start tag: style
attr: ('type', 'text/css')
Data : #python { color: green }
End tag : style # >>> parser.feed('<script type="text/javascript">'
... 'alert("<strong>hello!</strong>");</script>')
Start tag: script
attr: ('type', 'text/javascript')
Data : alert("<strong>hello!</strong>");
End tag : script
Parsing comments: # >>> parser.feed('<!-- a comment -->'
... '<!--[if IE 9]>IE-specific content<![endif]-->')
Comment : a comment
Comment : [if IE 9]>IE-specific content<![endif]
Parsing named and numeric character references and converting them to the correct
char (note: these 3 references are all equivalent to '>'): # >>> parser.feed('>>>')
Named ent: >
Num ent : >
Num ent : >
Feeding incomplete chunks to feed() works, but handle_data() might be called more
than once (unless convert_charrefs is set to True): # >>> for chunk in ['<sp', 'an>buff', 'ered ', 'text</s', 'pan>']:
... parser.feed(chunk)
Start tag: span
Data : buff
Data : ered
Data : text
End tag : span
Parsing invalid HTML (e.g. unquoted attributes) also works: # >>> parser.feed('<p><a class=link href=#main>tag soup</p ></a>')
Start tag: p
Start tag: a
attr: ('class', 'link')
attr: ('href', '#main')
Data : tag soup
End tag : p
End tag : a
Html / XHtml 解析 - Parsing Html and XHtml的更多相关文章
- python模块介绍- HTMLParser 简单的HTML和XHTML解析器
python模块介绍- HTMLParser 简单的HTML和XHTML解析器 2013-09-11 磁针石 #承接软件自动化实施与培训等gtalk:ouyangchongwu#gmail.comqq ...
- HTMLParser-简单HTML和XHTML解析
使用HTMLParser模块解析HTML页面 HTMLParser是python用来解析html和xhtml文件格式的模块.它可以分析出html里面的标签.数据等等,是一种处理html的简便途径.HT ...
- XHTML 结构化:使用 XHTML 重构网站
http://www.w3school.com.cn/xhtml/xhtml_structural_01.asp 我们曾经为本节撰写的标题是:"XHTML : 简单的规则,容易的方针.&qu ...
- XHTML 结构化:使用 XHTML 重构网站 分类: C1_HTML/JS/JQUERY 2014-07-31 15:58 249人阅读 评论(0) 收藏
http://www.w3school.com.cn/xhtml/xhtml_structural_01.asp 我们曾经为本节撰写的标题是:"XHTML : 简单的规则,容易的方针.&qu ...
- Sharepoint的网页(Page),网页解析(Parsing)与解析安全处理(Security)
转:http://www.chawenti.com/articles/8592.html Microsoft SharePoint Foundation 中主要有两种类型的页面,分别是应用程序页(Ap ...
- 解析html与xhtml的神器——HTMLParser与SGMLParser
有时候你要把抓回来的数据进行提取,过大篇幅的html标签,你若使用正则表达式进行匹配的话,显然是低效的,这时使用python的HTMLParser模块会显得非常方便.据说还有个比较好用的解析器叫:Be ...
- XHTML代码规则&手工html转换xhtml
XHTML规则 XHTML是XML得一个应用,它遵守XML得规范和要求.从技术角度上讲.这些语法规则是由XML规范定义的. XML文档必须遵守的规则使得生成工具以解析文档变得更容易.这些规则也使得XM ...
- HTML和XHTML区别
HTML和XHTML 可扩展超文本标记语言XHTML(eXtensible HyperText Markup Language)是将超文本标记语言HTML(HyperText Markup Langu ...
- 1; XHTML 基本知识
万维网是我们这个时代最重要的信息传播手段.几乎任何人都可以创建自己的网站,然后把它发布在因特网上.一些网页属于企业,提供销售服务:另一些网页属于个人,用来分享信息.你可以自己决定网页的内容和风格.所有 ...
随机推荐
- MariaDB的备份与主从、高可用实践
1.编写脚本,支持让用户自主选择,使用mysqldump还是xtraback全量备份. [root@test-centos7-node1 scripts]# cat chose_backup_mysq ...
- MAVEN配置及Spring Tool Suite的Maven配置
1.下载Maven http://maven.apache.org/download.cgi 如图点击下载即可 2.Maven配置 2.1配置本地仓库 创建目录maven-repository如图所示 ...
- mysql索引创建和使用细节
最近困扰自己很久的膝盖积液手术终于做完,在家养伤,逛技术博客看到easyswoole开发组成员仙士可博客有关mysql索引方面的知识,自己打算重温下. 正常业务起步数据表数据量较少,不用考虑使用索引, ...
- vim添加多行注释的几种方式
最近需要在阿里云上部署项目,不可避免地会遇到vim这个工具,查了一些资料,总结了一下使用vim多行注释的方法 块操作 多行注释: 首先按esc进入命令行模式下,按下Ctrl + v,进入列(也叫区块) ...
- pinpoint实现告警推送至钉钉和微信群
前言 在前面的文章中,我们学习了如何通过java实现将消息发送到钉钉.和将消息发送到微信群聊. 基于上述基础,我们今天来接入pinpoint的告警,发送到钉钉群. 实操前准备 开始之前,推荐阅读一下, ...
- 权限认证基础:区分Authentication,Authorization以及Cookie、Session、Token
1. 认证 (Authentication) 和授权 (Authorization)的区别是什么? 这是一个绝大多数人都会混淆的问题.首先先从读音上来认识这两个名词,很多人都会把它俩的读音搞混,所以我 ...
- element-ui input 组件 回车事件
直接在el-input 标签上添加@keyup.enter="funName" 是不起作用的,在组件中使用需要加上.native. <el-input v-model = & ...
- Oracle安装连接常见错误
oracle安装注意:安装路径url不能带中文C:\app\59428\product\11.2.0\dbhome_1\sqldeveloper打开sqldeveloper的时候,需要输入java.e ...
- 网站 cache control 最佳实践
推荐阅读: 2020年软件开发趋势 高并发案例 - 库存超发问题 负载均衡的分类及算法 异地多活架构 Postman 的替代品来了 有时,当第二次访问网站时,看起来比较怪,样式不正常. 通常,是因为 ...
- 【杂项】各类文件头结合winhex使用-转载
———常用文件头——— JPEG (jpg),文件头:FFD8FFE1 PNG (png),文件头:89504E47 (0D0A1A0A) GIF (gif),文件头:47494638 ZIP Arc ...