第13单元 处理 HTML 文件
本章介绍的第一种结构化文本文档是HTML——一种通常在Web上用于表示人类可读信息的标记语言。HTML文档包含文本以及用于控制文本的显示和释义的预定义标签(包含在尖括号<>中)。标签可以具有属性,下表显示了一些HTML标签及其属性。
表3 一些常用的HTML标签和属性
标签 | 属性 | 用途 |
HTML | 整个HTML文档 | |
HEAD | 文档头 | |
TITLE | 文档标题 | |
BODY | background、bgcolor | 文档主体内容 |
H1、H2、H3等 | 小节头 | |
I,EM | 斜体强调样式 | |
B,STRONG | 加粗强调样式 | |
PRE | 格式化文本 | |
P,SPAN,DIV | 段落,块元素,行内元素 | |
BR | 换行 | |
A | href | 超链接 |
IMG | src,width,height | 图片 |
TABLE | width,border | 表格 |
TR | 表格中的一行 | |
TH,TD | 表头/单元格 | |
OL,UL | 有序/无序列表 | |
LI | 列表 | |
DL | 描述列表 | |
DT,DD | 描述主题,描述定义 | |
INPUT | name | 用户输入域 |
SELECT | name | 下拉菜单 |
HTML是XML的前身,人们发明它的初衷是使机器处理可读文档,它算不上是一门编程语言,只是一系列具有相似结构的标记语言。用户可以根据需要定义XML标签及其属性。
XML ≠ HTML
虽然XML和HTML看上去很相似,但一个典型的HTML文档通常不会是一个有效的XML文档。反过来,XML文档也不是HTML文档。
XML标签依赖于所使用的应用程序。只要遵循一些简单的规则(例如,包含在尖括号中),任何字母和数字组成的字符串都可以作为标签。XML标签只起到对文本进行解释描述的作用,而不控制文本的显示,因此常在不需要人类直接阅读的文档中使用。使用可扩展样式表语言转换(XSLT),能将XML转换为HTML,而使用级联样式表(CSS),可以给HTML文档添加样式。
BeautifulSoup模块可用于解析、访问以及修改HTML和XML文档。可以使用一个标记字符串、一个标记文件或一个标记文档的网址,来构建一个BeautifulSoup对象:
from bs4 import BeautifulSoup from urllib.request import urlopen # 使用字符串构建soup soup1 = BeautifulSoup("<HTML><HEAD> «headers» </HEAD> «body» </HTML>") # 使用本地文件构建soup soup2 = BeautifulSoup(open("myDoc.html")) # 使用Web文档构建soup # 记住urlopen()不会添加"http://"! soup3 = BeautifulSoup(urlopen("http://www.networksciencelab.com/"))
BeautifulSoup对象构造函数的第二个可选参数是标记解析器——负责提取HTML标签和实体的Python组件。BeautifulSoup附带四个预先安装好的解析器:
"html.parser"(默认的解析器,解析速度非常快,但是规则较为严格,多用于“简单的”HTML文档)
"lxml"(解析速度非常快,规则较宽松)
"xml"(仅适用于XML文件)
"html5lib"(解析速度非常慢,规则也非常宽松,用于处理具有复杂结构的HTML文档,而如果不考虑解析速度,可用于所有HTML文档)
soup准备就绪后,可以使用函数soup.prettify()完美地打印出原始标记文档。
函数soup.get_text()返回标记文档中去除了所有标签的文本部分。当我们感兴趣的内容是纯文本时,就可以使用这个函数实现标记文本向纯文本的转换。
htmlString = ''' <HTML> <HEAD><TITLE>My document</TITLE></HEAD> <BODY>Main text.</BODY></HTML> ''' soup = BeautifulSoup(htmlString) soup.get_text() ➾ 'nMy document\nMain text.n'
标签通常用于定位某些文件片段。例如,我们所感兴趣的部分可能是第一个表的第一行这样具体的片段。使用标签可以实现诸如此类的定位功能,尤其是当标签具有class或id属性时,而使用纯文本是不可能实现这个功能的。
BeautifulSoup对标签之间的垂直和水平关系使用统一的实现方法。类似于文件系统的层次结构,这种位置关系被表示为标签对象的属性。例如,soup的标题soup.title就是soup的对象属性。标题父元素的name对象的值是soup.title.parent.name.string,而第一个表第一行中的第一个单元格大概能表示为soup.body.table.tr.td。
任何标签t都有一个名称t.name、一个字符串值(t.string表示原始内容,t.stripped_strings表示删除空白后的列表)、父标签t.parent、下一个标签t.next和前一个标签t.prev,以及零个或多个子标签t.children(标签中的标签)。
BeautifulSoup通过Python字典接口实现对HTML标签属性的访问。如果标签对象t表示超链接(例如<a href="foobar.html">),则超链接目标的字符串值为t["href"].string。HTML标签是不区分大小写的,这一点应引起注意。
soup最有用的函数应该就是soup.find()和soup.find_all()了,二者分别用于找到某个标签的第一个实例和所有实例。下面的例子说明了如何使用soup查询所需的内容。
标签<H2>的所有实例:
level2headers = soup.find_all("H2")
所有粗体或斜体格式:
formats = soup.find_all(["i", "b", "em", "strong"])
具有某个属性(例如id="link3")的所有标签:
soup.find(id="link3")
使用字典符号或tag.get()函数,找出所有超链接以及第一个链接的目标网址:
links = soup.find_all("a") firstLink = links[0]["href"] # Or: firstLink = links[0].get("href")
顺便提一下,如果标签不具备所查询的属性,则上面示例中的两种表达式都无法使用。鉴于可能遇到这样的情况,必须先使用tag.has_attr()函数检查属性是否存在,然后才能提取它。以下示例结合了BeautifulSoup和列表推导功能,来提取所有链接及其各自的网址和标签(这在用递归的方式抓取网页时非常有用):
with urlopen("http://www.networksciencelab.com/") as doc: soup = BeautifulSoup(doc) links = [(link.string, link["href"]) for link in soup.find_all("a") if link.has_attr("href")]
链接的值是一个由元组对象构成的列表:
➾ [('Network Science Workshop', ➾ '<http://www.slideshare.net/DmitryZinoviev/workshop-20212296'), ➾ «...»,('Academia.edu', ➾ '<https://suffolk.academia.edu/DmitryZinoviev'),('ResearchGate', ➾ '<https://www.researchgate.net/profile/Dmitry_Zinoviev')]
HTML/XML之所以强大,是因为它多样化的功能,但这种多功能性也未尝不是它的魔咒,尤其是涉及表格数据时。幸运的是,你可以在较为严谨但易于处理的CSV文件中存储表格数据,更多的内容请阅读下一个单元。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论