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 基本知识
万维网是我们这个时代最重要的信息传播手段.几乎任何人都可以创建自己的网站,然后把它发布在因特网上.一些网页属于企业,提供销售服务:另一些网页属于个人,用来分享信息.你可以自己决定网页的内容和风格.所有 ...
随机推荐
- 【转】SQL语句面试题
1.一道SQL语句面试题,关于group by表内容:2005-05-09 胜2005-05-09 胜2005-05-09 负2005-05-09 负2005-05-10 胜2005-05-10 负2 ...
- SpringBoot2 整合Nacos组件,环境搭建和入门案例详解
本文源码:GitHub·点这里 || GitEE·点这里 一.Nacos基础简介 1.概念简介 Nacos 是构建以"服务"为中心的现代应用架构,如微服务范式.云原生范式等服务基础 ...
- gradle 不用打开项目直接编译
gradlew :api-client:install 编辑完后点击
- C++数值计算
1.序 (1)程序设计分两种: 1.结构化设计(面向过程)——分解算法为模块,将算法的步骤分解为模块. 2.面向对象程序设计——主要是“类”与“对象”. (2)进制的转换 1.二进制转十进制 整数部分 ...
- scope为provided
以下面dependency为例 1 <dependency> 2 <groupId>javax.servlet</groupId> 3 <artifactId ...
- java Random类(API)
一.过程 1.导包 2.实例化 3.使用(类的成员方法) 二.作用 生成随机数,与python中random 相似 三.常用方法 1.nextInt(),随机生成int数据类型范围的数 2.nextI ...
- 9.Break和Continue
Break直接跳出循环和Continue略过本次循环,循环继续执行: Break在任何循坏语句的主体部分,均可用break控制循环的流程.break用于强制退出循环,不执行循环体中的语句,后边语句继续 ...
- Codeforces940掉分记
掉分经过 难得这次时间比较好,下午17:35开始. 本来还很高兴,心想这回肯定不会犯困,没准排名能再上升一些呢,,可惜事与愿违-- 上来a题,光看懂题就花了一些时间. 然后开始写,结果第一遍CE,第二 ...
- idea中当前模块资源目录上显示属于其他模块
一.错误的2个显示 1.错误显示 src/main目录下的java和resources本来属于cloud-consumer-dept-feign模块 但是在src/main/java却是显示src/m ...
- beta版本发布说明与总结
1.发布说明: 软件介绍: deta版本的发布最终是一个可安装使用的窗体程序,已经由Alpha版本的应用解决方案完成到一个程序: deta版本解决了Alpha版本遗留的软件技术方面错误问题,以及针对有 ...