第八章 HTML 处理
1、sgmllib.py 介绍
HTML 处理分成三步:将 HTML 分解成它的组成片段,对片段进行加工,接着将片段再重新合成 HTML
SGMLParser 将 HTML 分解成有用的片段,将 HTML 分析成 8 类数据,然后对每一类调用单独的方法:
1)开始标记 (Start tag)
是开始一个块的 HTML 标记,像 等,或是一个独一的标记,像
等
使用这个标记的属性列表来调用start_tagname 或 do_tagname 的方法;否则,它用这个标记的名字和属性列表来调用 unknown_starttag 方法
2)结束标记 (End tag)
是结束一个块的 HTML 标记,像 等
调用 end_tagname 方法,否则它使用标记的名字来调用 unknown_endtag
3)字符引用 (Character reference)
用字符的十进制或等同的十六进制来表示的转义字符,像 。当找到,SGMLParser 使用十进制或等同的十六进制字符文本来调用 handle_charref
4)实体引用 (Entity reference)
HTML 实体,像 ©。当找到,SGMLParser 使用 HTML 实体的名字来调用 handle_entityref
5)注释 (Comment)
HTML 注释,包括在 之间。当找到,SGMLParser 用注释内容来调用 handle_comment
6)处理指令 (Processing instruction)
HTML 处理指令,包括在 ... > 之间。当找到,SGMLParser 用处理指令内容来调用 handle_pi
7)声明 (Declaration)
HTML 声明,如 DOCTYPE,包括在 之间。当找到,SGMLParser 用声明内容来调用 handle_decl
8)文本数据 (Text data)
文本块。不满足其它 7 种类别的任何东西。当找到,SGMLParser 用文本来调用 handle_data
2、从 HTML 文档中提取数据
urllib 介绍
>>> import urllib #urllib 模块可以从基于互联网的 URL (主要指网页) 来获取信息并且真正取回数据
>>> sock = urllib.urlopen("http://diveintopython.org/") #提取用 urlopen 函数取回的网页的整个文本,返回值是像文件一样的对象
>>> htmlSource = sock.read() # read 可以将网页的整个 HTML 读到一个字符串中
>>> sock.close()
>>> print htmlSource
3、locals 和 globals
locals 和 globals,它们提供了基于 dictionary 的访问局部和全局变量的方式
1)调用顺序
Python 会到所有可用的名字空间去查找变量,按照如下顺序:
局部名字空间――特指当前函数或类的方法。如果函数定义了一个局部变量 x,或一个参数 x,Python 将使用它,然后停止搜索。
全局名字空间――特指当前的模块。如果模块定义了一个名为 x 的变量,函数或类,Python 将使用它然后停止搜索。
内置名字空间――对每个模块都是全局的。作为最后的尝试,Python 将假设 x 是内置函数或变量。
2)locals
>>> def foo(arg):
... x = 1
... print locals()
...
>>> foo(7) #locals 返回一个名字/值对的 dictionary,键字是字符串形式的变量名字,dictionary 的值是变量的实际值
{'arg': 7, 'x': 1}
>>> foo('bar')
{'arg': 'bar', 'x': 1}
3)globals
if __name__ == "__main__":
for k, v in globals().items(): #globals 函数返回一个 dictionary,我们使用 items 方法和多变量赋值来遍历 dictionary
print k, "=", v
4)locals 是只读的,globals 不是
def foo(arg):
x = 1
print locals() #使用 3 来调用 foo,会打印出 {'arg': 3, 'x': 1}
locals()["x"] = 2 #locals 实际上没有返回局部名字空间,它返回的是一个拷贝
print "x=",x
z = 7
print "z=",z
foo(3)
globals()["z"] = 8 #globals 返回实际的全局名字空间,而不是一个拷贝
print "z=",z
4、基于 dictionary 的字符串格式化
>>> params = {"server":"mpilgrim", "database":"master", "uid":"sa", "pwd":"secret"}
>>> "%(pwd)s is not a good password for %(uid)s" % params # %(pwd)s 标记被替换成相应的值 secret
'secret is not a good password for sa'
5、给属性值加引号
BaseHTMLProcessor 消费 (consume) HTML (因为它是从 SGMLParser 派生来的) 并生成等价的 HTML
1)标记和属性名最终会转化为小写字母,即使它们可能以大写字母开始或是大小写的混合形式
2)属性值将被双引号引起来,即使它们原来可能是用单引号括起来的或根本没有括起来