解析html与xhtml的神器——HTMLParser与SGMLParser
有时候你要把抓回来的数据进行提取,过大篇幅的html标签,你若使用正则表达式进行匹配的话,显然是低效的,这时使用python的HTMLParser模块会显得非常方便。据说还有个比较好用的解析器叫:Beautiful Soup,这个以后有机会再说吧,现在本渣连实习都找不到,再搞这个东西估计没法生活了。。。。。。
事先说明:我们要解析的html和xhtml的语法是规范的那一种,如果遇到不规范的就gg了,得自己手写正则提取。还有,对于那些转义字符没转义就先不考虑了。。。。。。。
关于HTMLParser与SGMLParser:
网上看很多大牛说HTMLParser对中文字符的提取很不好,推荐使用SGMLParser,但是python的官方文档的Demo是用HTMLParser写的。那就学HTMLParser,反正据说两者是继承关系。
先上文档的Demo:
#!/usr/bin/env python
#-*-coding:utf-8-*- from HTMLParser import HTMLParser
from htmlentitydefs 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 = unichr(name2codepoint[name])
print "Named ent:",c
#处理转义的数字字符(ACSII)
def handle_charref(self,name):
if name.startswith('x'):
c = unichr(int(name[1:],16)) #十六进制
else:
c = unichr(int(name))
print "Num ent :",c
#匹配HTML头
def handle_decl(self,data):
print "Decl :",data parser = MyHTMLParser() parser.feed('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML4.01//EN"''"http://www.w3.org/TR/html4/strict.dtd">')
#Decl : DOCTYPE HTML PUBLIC "-//W3C//DTD HTML4.01//EN""http://www.w3.org/TR/html4/strict.dtd" 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('<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 parser.feed('<!-- a comment --><!--[if IE 9]>IE-specific content<![endif]-->')
#Comment : a comment
#Comment : [if IE 9]>IE-specific content<![endif] parser.feed('>>>')
#Named ent: >
#Num ent : >
#Num ent : > 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文件中的信息只有3个主要的用途:
- 提取标题和段落;
- 提取img的图片,另存为文件;
- 提取href中的链接
1.提取标题和段落:
#!/usr/bin/env python
#-*-coding:utf-8-*- from htmlentitydefs import entitydefs
from HTMLParser import HTMLParser class TitleParser(HTMLParser): def __init__(self):
#定义要搜寻的标签
self.handledtags = ['title','p'] #提出标签,理论上可以提取所有标签的内容
self.processing = None
HTMLParser.__init__(self) #继承父类的构造函数 def handle_starttag(self,tag,attrs):
#判断是否在要搜寻的标签内
if tag in self.handledtags:
self.data = ''
self.processing = tag def handle_data(self,data):
if self.processing:
self.data += data def handle_endtag(self,tag):
if tag == self.processing:
print str(tag)+' : '+str(self.data)
self.processing = None #下面两个函数都是对html实体做的转码,没有深究
def handle_entityref(self,name):
if entitydefs.has_key(name):
self.handle_data(entitydefs[name])
else:
self.handle_data('&'+name+';') def handle_charref(self,name):
try:
charnum=int(name)
except ValueError:
return
if charnum<1 or charnum>255:
return
self.handle_data(chr(charnum)) parser = TitleParser()
html1 = """
<html>
<head>
<title> XHTML 与 HTML 4.01 标准没有太多的不同</title>
</head>
<body>
<p>i love you</p>
</body>
</html>
""" html2 = """
<html>
<head>
<title> XHTML 与" HTML 4.01 "标准没有太多的不同</title>
</head>
<body>
<p>i love÷ you×</p>
</body>
</html>
"""
parser.feed(html2)
2.提取img的图片,另存为文件
#!/usr/bin/env python
#-*-coding:utf-8-*- from htmlentitydefs import entitydefs
from HTMLParser import HTMLParser
import urllib
import time class ImgParser(HTMLParser): num = 1 def __init__(self):
#定义要搜寻的标签
self.processing = None
HTMLParser.__init__(self) #继承父类的构造函数
self.addr='' def handle_starttag(self,tag,attrs):
#判断是否在要搜寻的标签内
if tag == 'img':
print 'pic'+str(self.num) + " : " + tag
self.num += 1
for key,value in attrs:
if key == 'src':
self.addr = value
#在类的成员函数中,使用类中的另一个成员函数,前面必须要指定类名
ImgParser.getImage(self) #合法
print key + " : " + value
if key == 'alt':
print key + " : " + value def getImage(self):
u = urllib.urlopen(self.addr)
data = u.read()
filename = self.addr.split('/')[-1]
timestr = time.strftime('%Y%m%d%S',time.localtime(time.time()))
f = open('/home/dzhwen/python文件/Homework/urllib/pic/'+timestr+filename,'wb')
f.write(data)
f.close() parser = ImgParser()
f = urllib.urlopen('http://www.sina.com.cn/') #抓取新浪网上以img标签开头的图片
parser.feed(f.read())
3.提取href中的链接
#!/usr/bin/env python
#-*-coding:utf-8-*- from htmlentitydefs import entitydefs
from HTMLParser import HTMLParser
import urllib class LinkParser(HTMLParser): def __init__(self):
#定义要搜寻的标签
self.handledtags = ['a'] #提出标签,理论上可以提取所有标签的内容
self.processing = None
self.linkstr = '' #定义链接的标题
self.linkaddr = '' #定义链接的地址
HTMLParser.__init__(self) #继承父类的构造函数 def handle_starttag(self,tag,attrs):
#判断是否在要搜寻的标签内
if tag in self.handledtags:
for name,value in attrs:
if name == 'href':
self.linkaddr = value
self.processing = tag
self.linkstr = '' def handle_data(self,data):
if self.processing:
self.linkstr += data def handle_endtag(self,tag):
if tag == self.processing:
print self.linkstr.decode('utf-8') + ' : ' + self.linkaddr.decode('utf-8')
self.processing = None #下面两个函数都是对html实体做的转码,没有深究
def handle_entityref(self,name):
if entitydefs.has_key(name):
self.handle_data(entitydefs[name])
else:
self.handle_data('&'+name+';') def handle_charref(self,name):
try:
charnum=int(name)
except ValueError:
return
if charnum<1 or charnum>255:
return
self.handle_data(chr(charnum)) parser = LinkParser()
f = urllib.urlopen('http://www.csdn.net/') #解析csdn主页的链接
parser.feed(f.read())
不过很多网站的数据都用js来包装,这样就不能单纯用HTMLParser来解析了,需要用到别的工具,还是回去好好练级吧。。。。
搞到这里,基本的爬虫能掌握思路了,解析来就剩下Beautiful Soup ,Scrapy 和 异步编程还没学(用来进行大幅度的下载和抓取)。。。。。。迫于生活压力,估计没那么快更了,被迫进军java后台了(谁叫外面的世界都是java的天下呢?)唉。。。。。。
解析html与xhtml的神器——HTMLParser与SGMLParser的更多相关文章
- HTMLParser-简单HTML和XHTML解析
使用HTMLParser模块解析HTML页面 HTMLParser是python用来解析html和xhtml文件格式的模块.它可以分析出html里面的标签.数据等等,是一种处理html的简便途径.HT ...
- 使用Python中的HTMLParser、cookielib抓取和解析网页、从HTML文档中提取链接、图像、文本、Cookies(二)(转)
对搜索引擎.文件索引.文档转换.数据检索.站点备份或迁移等应用程序来说,经常用到对网页(即HTML文件)的解析处理.事实上,通过 Python语言提供的各种模块,我们无需借助Web服务器或者Web浏览 ...
- Python中的HTMLParser、cookielib抓取和解析网页、从HTML文档中提取链接、图像、文本、Cookies(二)
对搜索引擎.文件索引.文档转换.数据检索.站点备份或迁移等应用程序来说,经常用到对网页(即HTML文件)的解析处理.事实上,通过 Python语言提供的各种模块,我们无需借助Web服务器或者Web浏览 ...
- 将HTML转成XHTML并清除一些无用的标签和属性
介绍 这是一个能帮你从HTML生成有效XHTML的经典库.它还提供对标签以及属性过滤的支持.你可以指定允许哪些标签和属性可在出现在输出中,而其他的标签过滤掉.你也可以使用这个库清理Microsoft ...
- Python3 内建模块 hashlib、itertools、HTMLParser、urllib
Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等. 什么是摘要算法呢?摘要算法又称哈希算法.散列算法.它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制 ...
- 精通 Oracle+Python,第 3 部分:数据解析
进行数据解析的理由不计其数,相关的工具和技巧也同样如此.但是,当您需要用这些数据做一些新的事情时,即使有“合适的”工具可能也是不够的.这一担心对于异类数据源的集成同样存在.用来做这项工作的合适工具迟早 ...
- ASP.NET 动态查找数据 并且生成xml文档 同时使用xslt转换为xhtml
前言 xsl是一门标签解析语言,很适合做动态网页的前台标签 www.bamn.cn 1 首先是aspx页面 添加一个输入框 按钮 还有一个用来显示解析后的xhtml代码的控件 <form id= ...
- Python学习笔记(四十)— 内置模块(9)HTMLParser
摘抄自:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001432002312 ...
- Python的Web编程[0] -> Web客户端[1] -> Web 页面解析
Web页面解析 / Web page parsing 1 HTMLParser解析 下面介绍一种基本的Web页面HTML解析的方式,主要是利用Python自带的html.parser模块进行解析.其 ...
随机推荐
- 开放地址法散列表ADT
数据结构定义如下: typedef unsigned int Index; typedef Index Position; struct HashTbl; typedef struct HashTbl ...
- matlab的应用
MATLAB在信号与系统中的应用 一: 看到MATLAB在信号与系统中的应用,对这部分我比较熟悉,在此举一个小例子. impulse(sys)表示求连续系统sys的冲击响应 subplot ...
- Sql Server自增ID与序号的使用
SQL 自增ID alter table a add id int identity(1,1) not null 这里为 a 表增加一个 id 字段,其中identity(1,1)代表自增,第一个1代 ...
- 解决将easyui里的combobox里的输入框下拉列表变为空值
jQuery easyui官网上有一个方法是 :clear方法,这个方法说是能清除数据,但我测试了,结果它确实清楚了(但他清除的只是输入框显示的数据,没有清除所有的数据),在这里巧妙的用 它加载数据的 ...
- MiniUI合并单元格
function onload(e){ var grid = e.sender; var len = grid.data.length; var data= grid.data; ,num=; var ...
- SSH框架面试题集锦
Hibernate工作原理及为什么要使用Hibernate? 工作原理: 1.读取并解析配置文件 2.读取并解析映射信息,创建SessionFactory 3.打开Session 4.创建事务Tran ...
- 【bzoj5084】hashit 广义后缀自动机+树链的并+STL-set
题目描述 你有一个字符串S,一开始为空串,要求支持两种操作 在S后面加入字母C 删除S最后一个字母 问每次操作后S有多少个两两不同的连续子串 输入 一行一个字符串Q,表示对S的操作 如果第i个字母是小 ...
- List、Set、Map
List:1.可以允许重复的对象. 2.可以插入多个null元素. 3.是一个有序容器,保持了每个元素的插入顺序,输出的顺序就是插入的顺序. 4.常用的实现类有 ArrayList.LinkedLi ...
- Common Substrings POJ - 3415(长度不小于k的公共子串的个数)
题意: 给定两个字符串A 和 B, 求长度不小于 k 的公共子串的个数(可以相同) 分两部分求和sa[i-1] > len1 sa[i] < len1 和 sa[i-1] < ...
- Letter Combinations of a Phone Number - LeetCode
目录 题目链接 注意点 解法 小结 题目链接 Letter Combinations of a Phone Number - LeetCode 注意点 可以不用按字典序排序 解法 解法一:输入的数字逐 ...