使用HTMLParser模块解析HTML页面

 

    HTMLParser是python用来解析html和xhtml文件格式的模块。它可以分析出html里面的标签、数据等等,是一种处理html的简便途径。HTMLParser采用的是一种事件驱动的模式,当HTMLParser找到一个特定的标记时,它会去调用一个用户定义的函数,以此来通知程序处理。它主要的回调函数的命名都是以handler_开头的,都HTMLParser的成员函数。当我们使用时,就从HTMLParser派生出新的类,然后重新定义这几个以handler_开头的函数即可。和在htmllib中的解析器不同,这个解析器并不是基于sgmllib模块的SGML解析器。 

 htmllib模块和sgmllib模块从Python2.6开始不鼓励使用,3.0以后的版本中被移除~~~

HTMLParser 

class HTMLParser.HTMLParser

The HTMLParser class is instantiated without arguments.

HTMLParser类不需要参数进行实例化。

An HTMLParser instance is fed HTML data and calls handler functions when tags begin and end. The HTMLParser class is meant to be overridden by the user to provide a desired behavior.

一个HTMLParser实例传入HTML数据并且当传入开始和结束的tags参数时调用handler函数。HTMLParser类通过被用户重写方法来提供所需要的行为。

Unlike the parser in htmllib, this parser does not check that end tags match start tags or call the end-tag handler for elements which are closed implicitly by closing an outer element.

与htmllib中的解析器不同的是,这个解析器不检查结尾标签与开始标签的匹配或者对由关闭外部元素表明是关闭的元素调用结束标签handler

An exception is defined as well:

异常也被定义了:

exception HTMLParser.HTMLParseError
Exception raised by the HTMLParser class when it encounters an error while parsing. This exception provides three attributes: msg is a brief message explaining the error, lineno is the number of the line on which the broken construct was detected, and offset is the number of characters into the line at which the construct starts.
当遇到解析遇到错误时,该类将产生一个异常。该异常提供了三个属性:msg是用来解释错误的消息,lineno是检测到打断构造的行数,offset则是该行产生该构造的字符数。

HTMLParser instances have the following methods:

HTMLParser实例有以下方法:

HTMLParser.reset()
Reset the instance. Loses all unprocessed data. This is called implicitly at instantiation time.
重置该实例。失去所有未处理的数据。这个在实例化对象时被隐含地调用。
HTMLParser.feed(data)
Feed some text to the parser. It is processed insofar as it consists of complete elements; incomplete data is buffered until more data is fed or close() is called.
提供一些文本给解析器。在由完整元素组成的限度内进行处理,不完整的数据被缓冲直到更多的数据提供或者close()被调用。
HTMLParser.close()
Force processing of all buffered data as if it were followed by an end-of-file mark. This method may be redefined by a derived class to define additional processing at the end of the input, but the redefined version should always call theHTMLParser base class method close().
强制将所有的缓冲数据按跟在结束标记的数据一样进行处理。该方法可以通过派生类定义对输入结尾的额外处理来进行重定义,但是重定义的版本应该总是调用HTMLParser基类方法close()
HTMLParser.getpos()
Return current line number and offset.
返回当前行数和位移值。
HTMLParser.get_starttag_text()
Return the text of the most recently opened start tag. This should not normally be needed for structured processing, but may be useful in dealing with HTML “as deployed” or for re-generating input with minimal changes (whitespace between attributes can be preserved, etc.).
返回文本最近的开放标签。
HTMLParser.handle_starttag(tag, attrs)

This method is called to handle the start of a tag. It is intended to be overridden by a derived class; the base class implementation does nothing.

The tag argument is the name of the tag converted to lower case. The attrs argument is a list of (name, value) pairs containing the attributes found inside the tag’s <> brackets. The name will be translated to lower case, and quotes in the value have been removed, and character and entity references have been replaced. For instance, for the tag <A HREF="http://www.cwi.nl/">, this method would be called as handle_starttag('a', [('href', 'http://www.cwi.nl/')]).

该方法用来处理开始标签。其目的是被派生类重写;基类什么也不实现。tag参数是转换成小写的标签名称。attrs参数是一个(name,value)对包含了在标签<>中得属性。name将会转换成小写,并且value中得引号会被引出,并且字符串和实体引用将会被替代。

例如,对于标签<A HREF="http://www.cwi.nl/">,该方法将会调用为handle_starttag('a', [('href', 'http://www.cwi.nl/')])

Changed in version 2.6: All entity references from htmlentitydefs are now replaced in the attribute values.

2.6的版本变动:所有来自htmlentitydefs的实体引用现在在属性值中被替代了。

HTMLParser.handle_startendtag(tag, attrs)
Similar to handle_starttag(), but called when the parser encounters an XHTML-style empty tag (<a .../>). This method may be overridden by subclasses which require this particular lexical information; the default implementation simple calls handle_starttag() and handle_endtag().
类似于handle_starttag(),不过用来处理遇到XHTML风格的空标签(<a .../>)。
HTMLParser.handle_endtag(tag)
This method is called to handle the end tag of an element. It is intended to be overridden by a derived class; the base class implementation does nothing. The tag argument is the name of the tag converted to lower case.
该方法用来处理元素的结束标签。
HTMLParser.handle_data(data)
This method is called to process arbitrary data. It is intended to be overridden by a derived class; the base class implementation does nothing.
该方法用来处理任意的数据。
HTMLParser.handle_charref(name)
This method is called to process a character reference of the form &#ref;. It is intended to be overridden by a derived class; the base class implementation does nothing.
该方法用来处理&#ref;形式的字符引用。
HTMLParser.handle_entityref(name)
This method is called to process a general entity reference of the form &name; where name is an general entity reference. It is intended to be overridden by a derived class; the base class implementation does nothing.
该方法用来处理形式&name;的一般实体引用,参数name是一般的实体引用。
HTMLParser.handle_comment(data)
This method is called when a comment is encountered. The comment argument is a string containing the text between the --and -- delimiters, but not the delimiters themselves. For example, the comment <!--text--> will cause this method to be called with the argument 'text'. It is intended to be overridden by a derived class; the base class implementation does nothing.
该方法用来处理遇到的评论。
HTMLParser.handle_decl(decl)
Method called when an SGML doctype declaration is read by the parser. The decl parameter will be the entire contents of the declaration inside the <!...> markup. It is intended to be overridden by a derived class; the base class implementation does nothing.
当解析器读到一个SGML的doctype声明该方法被调用。
HTMLParser.unknown_decl(data)
Method called when an unrecognized SGML declaration is read by the parser. The data parameter will be the entire contents of the declaration inside the <!...> markup. It is sometimes useful to be overridden by a derived class; the base class implementation throws an HTMLParseError.
当解析器读到一个未被识别SGML声明时将调用该方法。
HTMLParser.handle_pi(data)

Method called when a processing instruction is encountered. The data parameter will contain the entire processing instruction. For example, for the processing instruction <?proc color='red'>, this method would be called as handle_pi("proccolor='red'"). It is intended to be overridden by a derived class; the base class implementation does nothing.

当遇到一个处理指令时将调用该方法。

Note

 

The HTMLParser class uses the SGML syntactic rules for processing instructions. An XHTML processing instruction using the trailing '?' will cause the '?' to be included in data.

实际运用

以网络爬虫的抓取url为例,我们需要抓取网易首页上的所有链接。首先得介绍一点HTML的知识,以下内容来自于w3cshool

什么是HTML 超链接

超链接可以是一个字,一个词,或者一组词,也可以是一幅图像,您可以点击这些内容来跳转到新的文档或者当前文档中的某个部分。

当您把鼠标指针移动到网页中的某个链接上时,箭头会变为一只小手。

我们通过使用 <a> 标签在 HTML 中创建链接。

有两种使用 <a> 标签的方式:

  1. 通过使用 href 属性 - 创建指向另一个文档的链接
  2. 通过使用 name 属性 - 创建文档内的书签

HTML 链接语法

链接的 HTML 代码很简单。它类似这样:

<a href="url">Link text</a>

href 属性规定链接的目标。

开始标签和结束标签之间的文字被作为超级链接来显示。

实例

<a href="http://www.w3school.com.cn/">Visit W3School</a>

编写代码

      从上面我们得知链接在起始标签<a>中,href属性指向我们需要解析的链接。那么重写handle_startag()方法来实现这个目的。

 

# -*- coding: utf-8 -*-
"""
Created on Tue Aug 30 09:46:45 2011

@author: Nupta
"""
import urllib2
import HTMLParser

class MyParser(HTMLParser.HTMLParser):
       
    
def handle_starttag(self, tag, attrs):
        
if tag == 'a':
            
for name,value in attrs:
                
if name == 'href' and value.startswith('http'):
                    
print value


if __name__ == '__main__':
    url
=raw_input(u'输入地址:'.encode('cp936'))
    f
=urllib2.urlopen(url).read()
    my
=MyParser()
    
try:
        my.feed(content)
    
except HTMLParser.HTMLParseError,e:
        
print e

问题分析

      输出地链接很多,先省略大部分,注意看最后一行:

http://www.hd315.gov.cn/beian/view.asp?bianhao=0102000102300012
http:
//www.itrust.org.cn/yz/pjwx.asp?wm=2012043533
http:
//www.bj.cyberpolice.cn/index.htm
malformed start tag, at line 
3339, column 44

 

      在读取的html文件中,第3339行的第44列读到一个有缺陷的开始标签,发生HTMLParseError异常。从给出的信息来看也就是html文件中的第3338行的43个元素。因为前面使用的是read()方法,这里我们需要使用readlines()把html文件读入一个列表中。

    print f[3338][34:67]

      看看结果就明白为什么了:

<a href=\'http://mail.163.com/\'

      这两个转义字符导致了解析器的解析异常,要是不知道如何判断html代码的正确性,请点击W3C的传送门,输入代码即可获得分析结果:

   Line 1, Column 9an attribute value must be a literal unless it contains only name characters

 <a href=\'http://mail.163.com/\'

You have used a character that is not considered a "name character" in an attribute value. Which characters are considered "name characters" varies between the different document types, but a good rule of thumb is that unless the value contains only lower or upper case letters in the range a-z you must put quotation marks around the value. In fact, unless you have extremefile size requirements it is a very very good idea to always put quote marks around your attribute values. It is never wrong to do so, and very often it is absolutely necessary.

 

从下面126邮箱的登录页面的检测结果可以看到,目前HTML要符合XHTML规范仍有很长的路要走。

 

寻求解决办法

      等待别人修补HTML代码那是不靠谱的,如果能将HTML代码转换为规范的格式,那该多好啊。下一篇将介绍使用Beautiful Soup来解决这个问题。

 

转载于:https://www.cnblogs.com/yuxc/archive/2011/08/30/2159307.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/422786.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端学习(294):rem小实例

altz转换为rem <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta http-equiv"X-UA-Compatible"…

【C语言进阶深度学习记录】三十二 函数指针与使用函数指针实现回调函数

回调函数是非常重要的概念 文章目录1 函数的类型2 函数指针2.1 函数指针的使用2.2 使用函数指针实现回调函数3 总结1 函数的类型 跟以前学数组的时候是一样的&#xff0c;C语言中的数组是有自己的类型的。函数也是有自己的类型的。 函数的类型由返回值、参数的类型、参数的个…

【C语言进阶深度学习记录】三十三 C语言中动态内存分配

如何在程序运行的时候动态给程序分配内存&#xff1f; 文章目录1 动态内存分配的意义1.1 C语言中如何动态申请内存空间1.2 malloc和free的用法1.3 calloc与realloc1.31 calloc和realloc的代码案例分析2 总结1 动态内存分配的意义 在C语言中&#xff0c;一切操作都是基于内存的…

java并发实战

推荐一个Java并发编程实战的学习专栏。此专栏为极客时间收费专栏。 学习交流加 个人qq&#xff1a; 1126137994个人微信&#xff1a; liu1126137994学习交流资源分享qq群 &#xff1a; 962535112 对于一个 Java 程序员而言&#xff0c; 能否熟练掌握并发编程是判断他优秀与否的…

a critical review of preetham skylight model 笔记

也是为了试用下Xmind。 上图是我用Xmind作的某篇文章的笔记。 感想&#xff1a; 1. 之以一直觉得这种东西没多大用处&#xff0c;回想起来大概是因为那时没有太多应用场景。 2. 如果留心&#xff0c;可以把许多事情做得更漂亮、更容易&#xff0c;这也是工具的用途。 贴一下软件…

【C语言进阶深度学习记录】三十四 C语言实现内存泄漏检测模块

上一篇文章学习了malloc系列的三个函数的使用。众所周知malloc的使用很容易导致内存泄漏。本文的目的就是使用C语言来实现内存泄漏检测模块&#xff0c;来帮忙自动检测我们写的程序中是否出现内存泄露。 文章目录1 内存泄露检测模块的实现原理1.1 各个函数模块的设计1.2 模块整…

重学前端----前端知识系统学习推荐专栏

推荐一个前端知识学习专栏。此专栏为极客时间收费专栏。 学习交流加 个人qq&#xff1a; 1126137994个人微信&#xff1a; liu1126137994学习交流资源分享qq群&#xff1a; 962535112 文章目录1 概述2 专栏内容2.1 模块一&#xff0c;JavaScript2.2 模块二&#xff0c;HTML 和 …

【C语言进阶深度学习记录】三十五 程序中的堆、栈以及静态存储区(数据区)

学习交流加 个人qq&#xff1a; 1126137994个人微信&#xff1a; liu1126137994学习交流资源分享qq群&#xff1a; 962535112 在我之前学习底层的知识的时候&#xff0c;也写过相关的内容。可以对比的学习&#xff1a;【软件开发底层知识修炼】二十 深入理解可执行程序的结构&a…

【C语言进阶深度学习记录】三十六 程序与进程的区别(程序的内存布局)

上一篇文章学了堆&#xff0c;栈以及静态存储区。它们实际上都是针对进程来说的。那么程序与进程有什么区别呢&#xff1f; 本文不细讲程序与进程。 1 程序与进程 1.1 什么是程序 写完的.c文件是源文件。也叫源代码。 将源代码编译后&#xff0c;会生成可执行文件程序&#…

使用Cucumber+Rspec玩转BDD(2)——邮件激活

使用CucumberRspec玩转BDD(2)——邮件激活 2009年3月2日 星期一 ### 温故知新 ###前面我们已经完成了新用户注册功能的开发&#xff0c;为了方便我们后面的开发工作且不扰乱之前的工作成果&#xff0c;我们先将这份源代码归档并做个标记。为了获得更好的阅读体验&#xff0c;读…

【C语言进阶深度学习记录】三十七 C/C++中造成程序内存错误的原因(野指针)

什么是野指针&#xff1f; 指针变量存的地址是一块非法内存地址。进而形成野指针。但是需要注意一点&#xff0c;野指针不是NULL指针。 文章目录1 野指针的概念1.1 野指针代码案例初探2 如何避免野指针2.1 野指针代码案例分析进阶3 总结1 野指针的概念 野指针变量中的值是非法…

算法补充 2011-9-12

设计一个算法将顺序表L中所有小于0的整数放前半部分&#xff0c;大于等于0的整数放在后半部分二叉树的删除设计一个算法将顺序表L中所有小于0的整数放前半部分&#xff0c;大于等于0的整数放在后半部分 思路:从左侧找出>0的元素&#xff0c;从右侧找出<0的元素,然后进行交…

【C语言进阶深度学习记录】三十八 C/C++语言中的函数声明与函数定义

文章目录1 函数的声明和定义1.1 代码分析2 总结1 函数的声明和定义 声明的意义在于告诉编译器程序单元的存在。只是告诉编译器它存在但是不在声明这里定义&#xff0c;有可能在当前文件中的其他地方或者其他文件中定义。如果在它还没有被定义之前就使用它&#xff0c;会导致编…

ASP.NET MVC3 系列教程 - 部署你的WEB应用到IIS 6.0

I:ASP.NET MVC3 部署的前期工作 1.确认部署的服务器操作系统环境 首先我们确认服务器的操作系统版本可以从系统命令行工具里输入: systeminfo 获取相关操作系统信息例如然后再确认IIS版本信息 -> 打开IIS管理工具即可接着确认.NET Framework的版本可以在系统命令行工具执行:…

【C语言进阶深度学习记录】三十九 C语言中的可变参数(参数可变的函数)

用过printf()函数的热都知道&#xff0c;printf的参数可以有多个&#xff0c;它是可变的&#xff0c;根据我们输出参数的类型以及个数的不同来确定参数。今天来学习C语言中参数可变的函数是如何实现的。 文章目录1 可变参数2 总结1 可变参数 首先我们要明白一点&#xff0c;在…

【离散数学中的数据结构与算法】一 最大公约数与最小公倍数之间的关系

文章目录1 算数基本定理2 最大公约数3 最小公倍数4 性质5 推论1 算数基本定理 设正整数 n>1&#xff0c; 则 n 可唯一地表示为&#xff1a; 其中 p1<p2<,…, <ps 是 s 个相异的素数&#xff0c; 指数ki都是正整数。 此定理又称作唯一析因定理&#xff08;unique f…

【离散数学中的数据结构与算法】二 欧几里得算法与裴蜀等式

欧几里得算法是计算两个数最大公因子算法。又称辗转相除法。本文将学习为什么辗转相除法可以求得两个数的最大公因子。同时也可以根据最大公因子计算两个数的最小公倍数。 文章目录1 欧几里得算法的理论基础1.1 欧几里得算法&#xff08;辗转相除法&#xff09;2 裴蜀等式&…

【离散数学中的数据结构与算法】四 加法法则与乘法法则

文章目录1 加法法则2 乘法法则3 例子3.1 例一3.2 例二3.3 例三4 总结1 加法法则 加法法则&#xff1a; 设事件 A 有 m 种产生方式&#xff0c; 事件 B 有n 种产生方式&#xff0c;则当 A 与 B 产生的方式不重叠时&#xff0c;“事件 A 或 B 之一” 有 mn 种产生方式。 加法法…