Beautiful Soup

Eric讨论 | 贡献2020年9月15日 (二) 06:20的版本 (创建页面,内容为“Beautiful Soup是一个Python库,用于从HTMLXML文件中提取数据。 ==简介== ===时间轴=== ===安装=== 可以通过下面3中方式安…”)
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)

Beautiful Soup是一个Python库,用于从HTMLXML文件中提取数据。

简介

时间轴

安装

可以通过下面3中方式安装Beautiful Soup 4。

通过pip安装

Beautiful Soup 4 通过PyPi发布,所以可以使用pip来安装:

pip install beautifulsoup4
pip3 install beautifulsoup4  #python3中使用pip3安装

通过软件包管理安装

如果你用的是新版的DebainUbuntu,那么可以通过系统的软件包管理来安装:

apt-get install Python-bs4

下载源代码安装

下载BS4的源码,然后通过setup.py来安装。

Python setup.py install

了解更多 >> Beautiful Soup 4 文档:安装Beautiful Soup


基础知识

简单示例

from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen('https://www.baidu.com')
bs = BeautifulSoup(html.read(), 'html.parser')
bs.title

HTML解析器

Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器。

  • Python标准库的HTML解析器,使用方法:BeautifulSoup(markup, "html.parser")
  • lxml HTML解析器,安装pip install lxml,使用方法:BeautifulSoup(markup, "lxml")
  • html5lib HTML解析器,安装pip install html5lib,使用方法:BeautifulSoup(markup, "html5lib")

对象

Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:

  • Tag
  • NavigableString
  • BeautifulSoup
  • Comment。

Tag

Tag对象与XMLHTML原生文档中的tag相同,Tag有很多方法和属性,最重要的两个属性为name和attributes

每个tag都有自己的名字,通过 .name 来获取。

bs = BeautifulSoup('<b class="boldest">Extremely bold</b>')
tag = bs.b
type(tag)
# <class 'bs4.element.Tag'>

#获取该标签的名字
tag.name
#'b'

#如果改变了tag的name,那将影响所有通过当前Beautiful Soup对象生成的HTML文档
tag.name = "blockquote"
tag
# <blockquote class="boldest">Extremely bold</blockquote>

一个tag可能有很多个属性,可以通过.attrs来获取,返回的类型是Python字典,也可以通过某个属性名获取属性值。

#上面tag对象
tag.attrs
# {'class': 'boldest'}
tag['class']
# ['boldest']

#添加,删除,修改操作方法和字典一样。
tag['class'] = 'verybold'
tag['id'] = 1
tag
# <blockquote class="verybold" id="1">Extremely bold</blockquote>
#删除tag的class和id属性
del tag['class']
del tag['id']
tag
# <blockquote>Extremely bold</blockquote>

#可以包含多个值的属性,在Beautiful Soup中多值属性的返回类型是list,最常见的多值属性为class如:
bs2 = BeautifulSoup('<p class="body strikeout"></p>')
bs2.p['class']
# ["body", "strikeout"]
#如果转换的文档是XML格式,那么tag中不包含多值属性
xml_soup = BeautifulSoup('<p class="body strikeout"></p>', 'xml')
xml_soup.p['class']
# u'body strikeout'

NavigableString

字符串常被包含在标签tag内。Beautiful Soup用 NavigableString 类来包装tag中的字符串。使用.string一个 NavigableString 字符串与Python中的Unicode字符串相同,并且还支持包含在遍历文档树和搜索文档树中的一些特性。

from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen('https://www.baidu.com')
bs = BeautifulSoup(html.read(), 'html.parser')
tag = bs.title

tag.string
#'百度一下,你就知道'
type(tag.string)
# <class 'bs4.element.NavigableString'>

BeautifulSoup

BeautifulSoup 对象表示的是一个文档的全部内容。大部分时候,可以把它当作 Tag 对象,它支持 遍历文档树 和 搜索文档树 中描述的大部分的方法。因为 BeautifulSoup 对象并不是真正的HTML或XML的tag,所以它没有name和attribute属性。


Comment

Comment是文档的注释及特殊字符串,Comment 对象是一个特殊类型的 NavigableString 对象。

markup = "<b><!--Hey, buddy. Want to buy a used parser?--></b>"
soup = BeautifulSoup(markup)
comment1 = soup.b.string
type(comment1)
# <class 'bs4.element.Comment'> 
comment1
# u'Hey, buddy. Want to buy a used parser'

遍历文档树

子节点

一个Tag可能包含多个字符串或其它的Tag,这些都是这个Tag的子节点。Beautiful Soup提供了许多操作和遍历子节点的属性。操作文档树最简单的方法就是告诉它你想获取的tag的name。如下:

from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen('https://www.baidu.com')
bs = BeautifulSoup(html.read(), 'html.parser')

#获取 <head> 标签
bs.head
#获取 <body> 标签
bs.body

#获取 <body> 标签中第一个<b>标签
bs.body.b

#通过点取属性的方式只能获得当前名字的第一个tag:
bs.a
#要想取得这个名字标签的全部标签,可以使用find_all()方法
bs.find_all('a')

tag的 .contents 属性可以将tag的子节点以列表的方式输出:

head_tag = bs.head
head_tag.contents
#列表中第一个子节点
head_tag.contents[0]
#子节点个数
#len(head_tag.contents)

#BeautifulSoup 对象本身一定会包含子节点,也就是说<html>标签也是 BeautifulSoup 对象的子节点
bs.contents[0] 
#'html'

.contents 和 .children 属性仅包含tag的直接子节点。而.descendants属性可以对所有tag的子孙节点进行递归循环。

如果tag只有一个 NavigableString 类型子节点,那么这个tag可以使用 .string 得到子节点。但如果tag包含了多个子节点,tag就无法确定 .string 方法应该调用哪个子节点的内容, .string 的输出结果是 None,要使用.strings或.stripped_strings来获取,使用.stripped_strings获取时会自动除去空格和空行,全部是空格的行会被忽略掉,段首和段末的空白会被删除。

bs.title.sting
#'百度一下,你就知道'
bs.body.string
#None

#有多个NavigableString 型子节点使用.strings
for string in bs.body.strings:
    print(repr(string))

#使用.stripped_strings除去空格和空行
for string in bs.stripped_strings:
    print(repr(string))

父节点

搜索文档树

资源

网站

参考文献