解析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模块进行解析.其 ...
随机推荐
- angularJS1笔记-(14)-自定义指令(scope)
index.html: <!DOCTYPE html> <html lang="en"> <head> <meta charset=&qu ...
- 软工网络15团队作业8——Beta阶段敏捷冲刺(Day3)
提供当天站立式会议照片一张 每个人的工作 1.讨论项目每个成员的昨天进展 赵铭: 还是在学习知晓云数据库怎么用 吴慧婷:这两天进一步进行界面设计,暂时完成了背单词界面的初步设计. 陈敏: 完成了背单词 ...
- [转]让opencv输出人脸检测的得分(置信率)
转自:http://www.cnblogs.com/sciencefans/ 作者:sciencefans 最近项目略多,其中一个需要找出一些和脸比较像但是不是脸的负样本,想用opencv的人脸检测器 ...
- 微信小程序组件 滚动导航
JS data: { // 初始化滑动条数据 menuIndex:0, // 每个菜单的宽度 onlyWidth: 70, // 右侧的margin marginWidth:10, // 菜单总长 m ...
- JS选取DOM元素的方法
摘自JavaScript权威指南(jQuery根据样式选择器查找元素的终极方式是 先用getElementsByTagName(*)获取所有DOM元素,然后根据样式选择器对所有DOM元素进行筛选) 今 ...
- 隐藏基于Dialog的MFC的主窗体
最近需要做一个主窗体常态隐藏的程序,类似360卫士那样,只有托盘图标常显示.本以为隐藏主窗体很简单,但遇到了意想不到的情况. 无效的做法 最初的想法是设置主对话框资源的 Visiable 属性为 fa ...
- ajax异步请求loading
1.找到一张loading图片 2.添加样式 <style> .loadingWrap{ position:fixed; top:; left:; width:100%; height:1 ...
- UVAlive4255_Guess
题目很好很有意思. 告诉你n个序列中,任意一个连续子序列的和与0相比较的结果. 构造一个满足条件的序列. 对于从x->y这一段的和,如果大于0,那么sum[x]>sum[y-1],显然我们 ...
- path变量修改后无法保存
Eclipse启动时出现错误: A Java Runtime Environment (JRE) or Java Development Kit(JDK) must be available in o ...
- 设置快捷键 让word轻松实现无格式粘贴
设置快捷键 让word轻松实现无格式粘贴使用word时,我们经常会遇到需要将网页上的内容复制到word进行编辑的情况,但是通常这样复制进来的内容都是带有格式的,编辑起来非常不便.虽然我们可以利用“记事 ...