python用 BeautifulSoup 模块解析 HTML

Beautiful Soup 是一个模块,用于从 HTML 页面中提取信息(用于这个目的时,它比正则表达式好很多)。BeautifulSoup 模块的名称是 bs4(表示 Beautiful Soup,第 4 版)。要安装它,需要在命令行中运行 pip install beautifulsoup4)。虽然安装时使用的名字是 beautifulsoup4,但要导入它,就使用 import bs4。在本章中,Beautiful Soup 的例子将解析(即分析并确定其中的一些部分)硬盘上的一个 HTML 文件。在 IDLE 中打开一个新的文件编辑器窗口,输入以下代码,并保存为 example.html。或者,从 http://nostarch.com/automatestuff/下载它。

<!-- This is the example.html file. -->

<html><head><title>The Website Title</title></head>
<body>
<p>Download my <strong>Python</strong> book from <a href="http://inventwithpython.com">my website</a>.</p>
<p class="slogan">Learn Python the easy way!</p>
<p>By <span id="author">Al Sweigart</span></p>
</body></html>

你可以看到,既使一个简单的 HTML 文件,也包含许多不同的标签和属性。对于复杂的网站,事情很快就变得令人困惑。好在,Beautiful Soup 让处理 HTML 变得容易很多。

从 HTML 创建一个 BeautifulSoup 对象

bs4.BeautifulSoup()函数调用时需要一个字符串,其中包含将要解析的 HTML。bs4.BeautifulSoup()函数返回一个 BeautifulSoup 对象。在交互式环境中输入以下代码,同时保持计算机与因特网的连接:

>>> import requests, bs4
>>> res = requests.get('http://nostarch.com')
>>> res.raise_for_status()
>>> noStarchSoup = bs4.BeautifulSoup(res.text)
>>> type(noStarchSoup)
<class 'bs4.BeautifulSoup'>

这段代码利用 requests.get()函数从 No Starch Press 网站下载主页,然后将响应结果的 text 属性传递给 bs4.BeautifulSoup()。它返回的 BeautifulSoup 对象保存在变量 noStarchSoup 中。也可以向 bs4.BeautifulSoup()传递一个 File 对象,从硬盘加载一个 HTML 文件。在交互式环境中输入以下代码(确保 example.html 文件在工作目录中):

>>> exampleFile = open('example.html')
>>> exampleSoup = bs4.BeautifulSoup(exampleFile)
>>> type(exampleSoup)
<class 'bs4.BeautifulSoup'>

有了BeautifulSoup对象之后,就可以利用它的方法,定位HTML文档中的特定部分。

用 select()方法寻找元素

针对你要寻找的元素,调用 method()方法,传入一个字符串作为 CSS“选择器”,这样就可以取得 Web 页面元素。选择器就像正则表达式:它们指定了要寻找的模式,在这个例子中,是在 HTML 页面中寻找,而不是普通的文本字符串。这里有一份选择器的简单介绍。表 11-2 举例展示了大多数常用 CSS 选择器的模式。

不同的选择器模式可以组合起来,形成复杂的匹配。例如,soup.select('p #author')将匹配所有 id 属性为 author 的元素,只要它也在一个<p>元素之内。select()方法将返回一个 Tag 对象的列表,这是 Beautiful Soup 表示一个 HTML元素的方式。针对 BeautifulSoup 对象中的 HTML 的每次匹配,列表中都有一个 Tag对象。Tag 值可以传递给 str()函数,显示它们代表的 HTML 标签。Tag 值也可以有attrs 属性,它将该 Tag 的所有 HTML 属性作为一个字典。利用前面的 example.html文件,在交互式环境中输入以下代码:

>>> import bs4
>>> exampleFile = open('example.html')
>>> exampleSoup = bs4.BeautifulSoup(exampleFile.read())
>>> elems = exampleSoup.select('#author')
>>> type(elems)
<class 'list'>
>>> len(elems)
1
>>> type(elems[0])
<class 'bs4.element.Tag'>
>>> elems[0].getText()
'Al Sweigart'
>>> str(elems[0])
'<span id="author">Al Sweigart</span>'
>>> elems[0].attrs
{'id': 'author'}

这段代码将带有 id="author"的元素,从示例 HTML 中找出来。我们使用select('#author')返回一个列表,其中包含所有带有 id="author"的元素。我们将这个Tag 对象的列表保存在变量中 elems,len(elems)告诉我们列表中只有一个 Tag 对象,只有一次匹配。在该元素上调用 getText()方法,返回该元素的文本,或内部的 HTML。一个元素的文本是在开始和结束标签之间的内容:在这个例子中,就是'Al Sweigart'。将该元素传递给 str(),这将返回一个字符串,其中包含开始和结束标签,以及该元素的文本。最后,attrs给了我们一个字典,包含该元素的属性'id',以及id属性的值'author'。也可以从 BeautifulSoup 对象中找出<p>元素。在交互式环境中输入以下代码:

>>> pElems = exampleSoup.select('p')
>>> str(pElems[0])
'<p>Download my <strong>Python</strong> book from <a href="http://
inventwithpython.com">my website</a>.</p>'
>>> pElems[0].getText()
'Download my Python book from my website.'
>>> str(pElems[1])
'<p class="slogan">Learn Python the easy way!</p>'
>>> pElems[1].getText()
'Learn Python the easy way!'
>>> str(pElems[2])
'<p>By <span id="author">Al Sweigart</span></p>'
>>> pElems[2].getText()
'By Al Sweigart'

这一次,select()给我们一个列表,包含 3 次匹配,我们将它保存在 pElems 中。在 pElems[0]、pElems[1]和 pElems[2]上使用 str(),将每个元素显示为一个字符串,并在每个元素上使用 getText(),显示它的文本。

通过元素的属性获取数据

Tag 对象的 get()方法让我们很容易从元素中获取属性值。向该方法传入一个属性名称的字符串,它将返回该属性的值。利用example.html,在交互式环境中输入以下代码:

>>> import bs4
>>> soup = bs4.BeautifulSoup(open('example.html'))
>>> spanElem = soup.select('span')[0]
>>> str(spanElem)
'<span id="author">Al Sweigart</span>'
>>> spanElem.get('id')
'author'
>>> spanElem.get('some_nonexistent_addr') == None
True
>>> spanElem.attrs
{'id': 'author'}

这里,我们使用 select()来寻找所有<span>元素,然后将第一个匹配的元素保存在 spanElem 中。将属性名'id'传递给 get(),返回该属性的值'author'。


版权声明:本文为dongyu1703原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。