BeautifulSoup4库
和 lxml 一样,Beautiful Soup 也是一个HTML/XML的解析器,主要的功能也是如何解析和提取 HTML/XML 数据。
lxml 只会局部遍历,而Beautiful Soup 是基于HTML DOM(Document Object Model)的,会载入整个文档,解析整个DOM树,因此时间和内存开销都会大很多,所以性能要低于lxml。
BeautifulSoup 用来解析 HTML 比较简单,API非常人性化,支持CSS选择器、Python标准库中的HTML解析器,也支持 lxml 的 XML解析器。
Beautiful Soup 3 目前已经停止开发,推荐现在的项目使用Beautiful Soup 4。
安装和文档:
- 安装:
pip install bs4。 - 中文文档:https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html
几大解析工具对比:
| 解析工具 | 解析速度 | 使用难度 |
|---|---|---|
| BeautifulSoup | 最慢 | 最简单 |
| lxml | 快 | 简单 |
| 正则 | 最快 | 最难 |
简单使用:
1 | from bs4 import BeautifulSoup |
四个常用的对象:
Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:
- Tag
- NavigatableString
- BeautifulSoup
- Comment
1. Tag:
Tag 通俗点讲就是 HTML 中的一个个标签。示例代码如下:
1 | (from bs4 import BeautifulSoup) |
我们可以利用 soup 加标签名轻松地获取这些标签的内容,这些对象的类型是bs4.element.Tag。但是注意,它查找的是在所有内容中的第一个符合要求的标签。如果要查询所有的标签,后面会进行介绍。
对于Tag,它有两个重要的属性,分别是name和attrs。示例代码如下:
1 | print soup.name |
2. NavigableString:
如果拿到标签后,还想获取标签中的内容。那么可以通过tag.string获取标签中的文字。示例代码如下:
1 | print (soup.p.string) |
3. BeautifulSoup:
BeautifulSoup 对象表示的是一个文档的全部内容.大部分时候,可以把它当作 Tag 对象,它支持 遍历文档树 和 搜索文档树 中描述的大部分的方法.
因为 BeautifulSoup 对象并不是真正的HTML或XML的tag,所以它没有name和attribute属性.但有时查看它的 .name 属性是很方便的,所以 BeautifulSoup 对象包含了一个值为 “[document]” 的特殊属性 .name
1 | soup.name |
4. Comment:
Tag , NavigableString , BeautifulSoup 几乎覆盖了html和xml中的所有内容,但是还有一些特殊对象.容易让人担心的内容是文档的注释部分:
1 | markup = "" |
Comment 对象是一个特殊类型的 NavigableString 对象:
1 | comment |
遍历文档树:
1. contents和children:
1 | html_doc = """ |
2. strings 和 stripped_strings
如果tag中包含多个字符串 [2] ,可以使用 .strings 来循环获取:
1 | for string in soup.strings: |
输出的字符串中可能包含了很多空格或空行,使用 .stripped_strings 可以去除多余空白内容:
1 | for string in soup.stripped_strings: |
获取标签属性
1.通过下标获取
1 | href = a['href'] |
2.通过attrs属性获取
1 | href=a.attrs['href'] |
小结
- string: 获取某个标签下的非标签字符串。返回来的是个字符串。
- strings: 获取某个标签下的子孙非标签字符串。返回来的是个生成器。
- stripped_strings:获取某个标签下的子孙非标签字符串,会去掉空白字符。返回来的
是个生成器。 - get_ _text:获取某个标签下的子孙非标签字符串。不是以列表的形式返回,是以普通字
符串返回。
搜索文档树:
1. find和find_all方法:
搜索文档树,一般用得比较多的就是两个方法,一个是find,一个是find_all。find方法是找到第一个满足条件的标签后就立即返回,只返回一个元素。find_all方法是把所有满足条件的标签都选到,然后返回回去。使用这两个方法,最常用的用法是出入name以及attr参数找出符合要求的标签。
1 | soup.find_all("a",attrs={"id":"link2"}) |
或者是直接传入属性的的名字作为关键字参数:
1 | soup.find_all("a",id='link2') |
2. select方法:
使用以上方法可以方便的找出元素。但有时候使用css选择器的方式可以更加的方便。使用css选择器的语法,应该使用select方法。以下列出几种常用的css选择器方法:
(1)通过标签名查找:
1 | print(soup.select('a')) |
(2)通过类名查找:
通过类名,则应该在类的前面加一个.。比如要查找class=sister的标签。示例代码如下:
1 | print(soup.select('.sister')) |
(3)通过id查找:
通过id查找,应该在id的名字前面加一个#号。示例代码如下:
1 | print(soup.select("#link1")) |
(4)组合查找:
组合查找即和写 class 文件时,标签名与类名、id名进行的组合原理是一样的,例如查找 p 标签中,id 等于 link1的内容,二者需要用空格分开:
1 | print(soup.select("p #link1")) |
直接子标签查找,则使用 > 分隔:
1 | print(soup.select("head > title")) |
(5)通过属性查找:
查找时还可以加入属性元素,属性需要用中括号括起来,注意属性和标签属于同一节点,所以中间不能加空格,否则会无法匹配到。示例代码如下:
1 | print(soup.select('a[href="http://example.com/elsie"]')) |
(6)获取内容
以上的 select 方法返回的结果都是列表形式,可以遍历形式输出,然后用 get_text() 方法来获取它的内容。
1 | soup = BeautifulSoup(html, 'lxml') |
祝祖国繁荣昌盛……