是什么
Beautiful Soup 是一个可以从HTML
或XML
文件中提取数据的 Python 库.它能够通过你喜欢的解析器实现文档导航,查找,修改文档.
安装
仅列出 MAC 的情况
- beautifulsoup4
pip install beautifulsoup4
解析器
- lxml
需要先安装 command line tools ,C语言库
xcode-select --install
Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,其中一个是 lxml .
如果不指定解析器,Beautiful Soup会自动选择最合适的解析器来解析文档,如果手动指定解析器,那么Beautiful Soup会用指定的解析器来解析文档.
解析网页
使用 beautifulsoup4 解析网页
解析一个文件,需要被解析的文件,以及解析用的解析器
soup = BeautifulSoup(open("index.html"), "lxml")
使用 request 向服务器请求网页
wb_data = requests.get("http://www.baidu.com") # 获得完整的 HTTP response
使用 beautifulsoup 解析网页
soup = Beautifulsoup(wb_data.text,'lxml') # 用`.text`提取 HTTP 体,即 HTML 文档
搜索文档树
描述要爬取的元素在哪儿,获取元素/标签列表
过滤器类型
字符串
re
列表
如果传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回.下面代码找到文档中所有标签和标签:
soup.find_all(["a", "b"])
# [The Dormouse's story,
# Elsie,
# Lacie,
# Tillie]
True
方法
CSS选择器
Beautiful Soup
支持大部分CSS选择器 ,在 Tag 或 BeautifulSoup 对象的 .select() 方法中传入字符串参数,即可使用CSS选择器的语法找到tag。
xx = Soup.select()
填入描述元素所在位置的路径,获取标签列表
查找tab标签:
soup.select("title")
# [The Dormouse's story ]
通过tag标签逐层查找,遍历子标签
:
soup.select("body a")
# [Elsie,
# Lacie,
# Tillie]
找到某个tag标签下的直接子标签
:
soup.select("head > title")
# [The Dormouse's story ]
soup.select("p > a")
# [Elsie,
# Lacie,
# Tillie]
通过CSS的类名
查找:
soup.select(".sister")
# [Elsie,
# Lacie,
# Tillie]
soup.select("[class~=sister]")
# [Elsie,
# Lacie,
# Tillie]
通过tag的id
查找:
soup.select("#link1")
# [Elsie]
soup.select("a#link2")
# [Lacie]
通过是否存在某个属性
来查找:
soup.select('a[href]')
# [Elsie,
# Lacie,
# Tillie]
通过属性的值
来查找:
soup.select('a[href="http://example.com/elsie"]')
# [Elsie]
soup.select('a[href^="http://example.com/"]')
# [Elsie,
# Lacie,
# Tillie]
soup.select('a[href$="tillie"]')
# [Tillie]
soup.select('a[href*=".com/el"]')
# [Elsie]
find_all
- find_all( name , attrs , recursive , text , **kwargs )
元素名称,元素属性, 是否搜索当前tag 的所有子节点(默认 True) , 搜文档中的字符串内容, limit=2, ...
find_all() 方法搜索当前tag的所有tag子节点,并判断是否符合过滤器的条件
soup.find_all("title")
# [The Dormouse's story ]
soup.find_all("p", "title")
# [The Dormouse's story
]
soup.find_all("a")
# [Elsie,
# Lacie,
# Tillie]
soup.find_all(id="link2")
# [Lacie]
获取信息
从获取的元素/标签中获取需要的信息
对象
Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种: Tag
, NavigableString
, BeautifulSoup
, Comment
.
tag
Tag 对象与XML或HTML原生文档中的tag相同:
soup = BeautifulSoup('Extremely bold')
tag = soup.b # 获取 tag 对象,就是标签
>>> soup.b
Extremely bold
type(tag)
#
- name
每个tag都有自己的名字,通过 .name 来获取:
tag.name
# u'b'
如果改变了tag的name,那将影响所有通过当前Beautiful Soup对象生成的HTML文档:
tag.name = "blockquote"
tag
# Extremely bold
- Attributes
一个tag可能有很多个属性. tag 有一个 “class” 的属性,值为 “boldest”。tag的属性的操作方法与字典相同:
tag[""]
ortag.get("")
,不同点是,前者如果属性不存在会报错,后者仅返回None
tag['class']
# u'boldest'
也可以直接”点”取属性, 比如: .attrs :
tag.attrs
# {u'class': u'boldest'}
tag的属性可以被添加,删除或修改. 再说一次, tag的属性操作方法与字典一样
tag['class'] = 'verybold'
tag['id'] = 1
tag
# Extremely bold
del tag['class']
del tag['id']
tag
# Extremely bold
tag['class']
# KeyError: 'class'
print(tag.get('class'))
# None
- 多值属性
最常见的多值的属性是 class (一个tag可以有多个CSS的class). 还有一些属性 rel , rev , accept-charset , headers , accesskey . 在Beautiful Soup中,对于可能多值的属性,返回类型是list:
css_soup = BeautifulSoup('')
css_soup.p['class']
# ["body", "strikeout"]
css_soup = BeautifulSoup('')
css_soup.p['class']
# ["body"]
可以遍历的字符串
字符串常被包含在tag内.
Beautiful Soup用 NavigableString 类来包装tag中的字符串:
soup = BeautifulSoup('Extremely bold')
tag = soup.b
tag.string
# u'Extremely bold'
BeautifulSoup
BeautifulSoup 对象表示的是一个文档的全部内容.大部分时候,可以把它当作 Tag 对象,它支持 遍历文档树 和 搜索文档树 中描述的大部分的方法.
因为 BeautifulSoup 对象并不是真正的HTML或XML的tag,所以它没有name和attribute属性.但有时查看它的 .name 属性是很方便的,所以 BeautifulSoup 对象包含了一个值为 “[document]” 的特殊属性 .name
>>> from bs4 import BeautifulSoup
>>> import requests
>>>
>>> url = "http://bj.xiaozhu.com/search-duanzufang-p1-0/"
>>>
>>> detail_data = requests.get(url)
>>>
>>> detail_soup = BeautifulSoup(detail_data.text, 'lxml')
>>> detail_soup.name
u'[document]'
>>> type(detail_soup)
>>> soup = BeautifulSoup('Extremely bold', 'lxml')
>>> soup
Extremely bold
>>> type(soup)
注释及特殊字符串
markup = ""
soup = BeautifulSoup(markup)
comment = soup.b.string
type(comment)
#
Comment 对象是一个特殊类型的 NavigableString 对象:
comment
# u'Hey, buddy. Want to buy a used parser'
get_text()
get_text() 方法,这个方法获取到tag中包含的所有文本内容,包括子孙tag中的内容,并将结果作为Unicode字符串返回:
markup = '\nI linked to example.com\n'
soup = BeautifulSoup(markup,'lxml')
soup.get_text()
u'\nI linked to example.com\n'
soup.i.get_text()
u'example.com'
可以通过参数指定tag的文本内容的分隔符:
# soup.get_text("|")
u'\nI linked to |example.com|\n'
还可以去除获得文本内容的前后空白:
# soup.get_text("|", strip=True)
u'I linked to|example.com'
.stripped_strings
生成器
获取一个父级标签下所有子标签内的文本信息,是处理多个文本的高级的get_text
产生生成器
>>> soup.stripped_strings
列表化:
>>> list(soup.stripped_strings)
[u'I linked to', u'example.com']
或
>>> [text for text in soup.stripped_strings]
[u'I linked to', u'example.com']
参考资料
Beautiful Soup 4.2.0 文档