BeautifulSoup入门

BeautifulSoup是一个用来从HTML和XML文件中提取数据的Python库,最近需要爬取一些数据,简单记录一下BeautifulSoup的基本用法。BeautifulSoup的详细用法可以参考文档:https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html

BeautifulSoup的安装

目前BeautifulSoup的版本为第四版,可以直接使用pip进行安装:

pip install beautifulsoup4

之后可以通过pip list检查BeautifulSoup是否安装成功。

BeautifulSoup基本使用方法

将一段文档传入BeautifulSoup的构造方法,可以得到一个文档对象,可以传入一段字符串(比如爬取得到的网页源码)或一个文件句柄。

# 使用BeautifulSoup之前需要先引入
from bs4 import BeautifulSoup
# 传入文件句柄的用法,构造方法返回的便是文档对象
soup = BeautifulSoup(open("index.html"))
html = "<html><body>data</body></html>"
# 传入文档字符串的用法
soup1 = BeautifulSoup(html)

BeatuifulSoup会选择最合适的解析器来解析这段文档,当然也可以手动指定解析器,不同解析器的区别可以参考引言处的官方文档,比如指定lxml为解析器,则可以使用:BeautifulSoup(html,"lxml")

BeautifulSoup对象的种类

BeautifulSoup将HTML文档转换为一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为四种:Tag,NavigableString,BeautifulSoup和Comment。

Tag

当我们使用BeautifulSoup构造方法获取到文档对象之后,Tag对象可以看作HTML中的标签对象,可以使用.操作符获取,获取到Tag对象后可以获取对应HTML标签的属性,使用类似字典的操作方法获取。

soup = BeautifulSoup('<b class="bold">tag</b>')
# 通过.操作符可以获取对应的标签对象
type(soup.b)  # <class 'bs4.element.Tag'>
tag = soup.b
# Tag可以通过.name获取自己的名字
tag.name   # 'b'
# Tag的属性操作方法与字典相同
tag['class']  # 'bold'
# 也可以使用.attrs获取Tag的所有属性
tag.atttrs   # {'class':'bold'}
# 若Tag存在多值属性则会返回list
css_soup = BeautifulSoup('<p class="a b"></p>')
css_soup.p['class'] # ['a','b']

NavigableString

字符串常被包含在标签(Tag)内,NavigableString类用来包装Tag中的字符串。获取到Tag对象后,使用.string即可获取到标签内的字符串。

soup = BeautifulSoup('<b class="bold">string</b>')
tag = soup.b
tag.string   # string
type(tag.string)  # <class 'bs4.element.NavigableString'>

BeautifulSoup

BeautifulSoup对象表示的是一个文档的全部内容,大部分时候可以把它看作Tag对象,支持遍历文档树中的大部分方法,它的name属性有一个特殊值document

Comment

Comment对象是一个特殊的NavigableString对象,表示注释内容。

markup = "<b><!-- a comment --></b>"
soup = BeautifulSoup(markup)
comment = soup.b.string
type(comment)   # <class 'bs4.element.Comment'>
comment   # a comment

BeautifulSoup遍历文档树

通过一个例子说明BeautifulSoup遍历文档树的方法。

html_doc = """
<html>
	<head>
		<title>The Dormouse's story</title>
	</head>
	<body>
		<p class="title">
			<b>The Dormouse's story</b>
		</p>
		<p class="story">
			Once upon a time there were...
		</p>
		<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
		<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
		<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
		</p>
		<p class="story">...</p>
	</body></html>
"""
from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc)
# 使用tag的name获取标签内容
soup.title  # <title>The Dormouse's story</title>
# 通过.属性的方式只能获取当前名字的第一个tag
soup.a # <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>
# 如果tag内还有tag可以继续使用.属性获取内部tag
soup.body.b   # <b>The Dormouse's story</b>
# 如果想得到所有a标签,需要使用搜索文档树中的fing_all()方法
soup.find_all('a')   # 得到所有a标签的列表
# 如果tag只有一个NavigableString类型子节点,那么这个tag可以使用.string得到子节点
soup.title.string   # The Dormouse's story
# 通过.parent属性可以获取某个元素的父节点
soup.title.parent  # <head><title>The Dormouse's story</title></head>

BeautifulSoup搜索文档树

BeautifulSoup定义了多种搜索方法,这里着重介绍find()和find_all()。

# html_doc与遍历文档树使用的一致
from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc)
# find_all()方法可以找到想要查找的文档内容,有多种过滤方式
# 1.使用标签名过滤
# 查找所有<b>标签,返回结果是一个list
soup.find_all('b')  # [<b>The Dormouse's story</b>]
# 2.使用正则表达式过滤
import re
# 查找所有以b开头的标签
for tag in soup.find_all(re.compile("^b")):
	print(tag.name)    # body b
# 3.使用列表过滤
# 查找文档中所有的<a>和<b>标签
soup.find_all(['a','b'])
# 4.使用标签属性过滤
# 查找id为link2的标签
soup.find_all(id="link2")
# 查找所有包含id属性的标签
soup.find_all(id=True)
# 指定CSS类名时需要使用class_参数
# 查找所有类名为sister的<a>标签
soup.find_all("a",class_="sister")

find()方法与find_all()使用方法相似,唯一区别是find_all()方法返回的结果是一个列表,而find()方法只返回搜索到的第一个结果。find_all()方法找不到目标时返回空列表,find()方法找不到目标时返回None。
BeautifulSoup还支持使用大部分的CSS选择器语法进行搜索,在Tag或BeautifulSoup对象的select()方法中可以使用CSS选择器语法找到tag,我举几个常用的例子。

# 1.使用tag标签查找,返回结果也是标签列表
soup.select("a")
# 2.使用tag标签逐层查找
soup.select("html head title")
# 3.找到tag下的直接子标签
soup.select("p > a")
# 4.通过CSS类名查找
soup.select(".sister")
# 5.通过id查找
soup.select("#link1")
# 6.通过是否存在某个属性查找
# 查找所有包含href属性的a标签
soup.select('a[href]')
# 7.通过属性的值来查找
# 精准查找
soup.select('a[href="http://example.com/elsie"]')
# 正则查找
soup.select('a[href^="http://"]')

BeautifulSoup格式化输出

使用prettify()方法可以将BeautifulSoup文档树格式化后以Unicode编码输出,每个XML/HTML标签都独占一行。

markup='<a href="http://example.com/">I linked to <i>example.com</i></a>'
soup = BeautifulSoup(markup)
print(soup.a.prettify())
# <a href="http://example.com/">
# I linked to
# <i>
#   example.com
# </i>
# </a>

get_text()方法

如果只想得到Tag中包含的文本内容,那么可以使用get_text()方法,这个方法获取到Tag中的所有文版内容包括子孙Tag中的内容,并将结果作为Unicode字符串返回。

markup='<a href="http://example.com/">I linked to  <i>example.com</i></a>'
soup = BeautifulSoup(markup)
soup.get_text()   # I linked toexample.com
# 也可以使用.stripped_strings生成器获得文本列表后手动处理列表
[text for text in soup.stripped_strings]
# ['Ilinked to','example.com']

如有错误,欢迎留言指出,我会及时修改,感谢阅读,希望您能有所收获。

猜你喜欢

转载自blog.csdn.net/seeing_Liu/article/details/89040344
今日推荐