开始
首先必须要导入 bs4 库
from bs4 import BeautifulSoup
我自己常用的两种解析器
soup = BeautifulSoup(markup, "html.parser")
soup = BeautifulSoup(markup, "lxml")
如果要使用lxml必须先安装
pip install lxml
四大对象种类
- Tag
- NavigableString
- BeautifulSoup
- Comment
Tag
Tag就是HTML中的一个个标签, 例如
The Dormouse's story
Elsie
验证一下对象类型
print(type(soup.a))
#
对于Tag, 有两个重要的属性, name和attrs
name
例如一个b标签, 那么它的name就是b, 一个p标签的name就是p
soup = BeautifulSoup('Extremely bold', 'lxml')
tag = soup.b
print(tag.name)
#b
attrs
attrs是一个字典类型的, 对应的是属性-值, 如print soup.p.attrs,输出的就是{'class': ['title'], 'name': 'dromouse'}, 当然你也可以得到具体的值, 如print(soup.p.attrs['class']),输出的就是[title]是一个列表的类型,因为一个属性可能对应多个值,当然你也可以通过get方法得到属性的, 如:print(soup.p.get('class')). 还可以直接使用print(soup.p['class'])
print(soup.p.attrs)
#{'class':['title'], 'name':'dromouse'}
get
get方法用于得到标签下的属性值, 注意这是一个重要的方法, 在许多场合都能用到, 比如你要得到标签下的图像url, 那么就可以用soup.img.get('src'), 具体解析如下:
print soup.p.get("src") #得到第一个p标签下的src属性
单独获取某个属性
print(soup.p['class']
#['title']
也可以像下面这样
print(soup.p.get('class')
#['title']
或者下面那样
print(soup.p.attrs['class']
#['title']
find_all()
find_all(name , attrs , recursive , text , **kwargs)
find_all() 方法搜索当前tag的所有tag子节点, 并判断是否符合过滤器的条件
注意:如果一个指定名字的参数不是搜索内置的参数名, 搜索时会把该参数当作指定名字tag的属性来搜索, 如果包含一个名字为 id 的参数,Beautiful Soup会搜索每个tag的”id”属性
find_all() 的返回值是一个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]
import re
soup.find(text=re.compile("sisters"))
# u'Once upon a time there were three little sisters; and their names were\n'
name 参数
name 参数可以查找所有名字为 name 的tag,字符串对象会被自动忽略掉
soup.find_all("title")
# [The Dormouse's story ]
传字符串
soup.find_all('b')
# [The Dormouse's story]
print soup.find_all('a')
#[...]
传正则表达式
如果传入正则表达式作为参数,Beautiful Soup会通过正则表达式的 match() 来匹配内容.下面例子中找出所有以b开头的标签,这表示和标签都应该被找到:
for tag in soup.find_all(re.compile("^b")):
print(tag.name)
# body
# b
传列表
如果传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回.下面代码找到文档中所有标签和标签:
soup.find_all(["a", "b"])
attrs参数
find_all()中第二个参数是标签的class属性值
soup.find_all("a", class_="sister")
等效于
soup.find_all("p", "sister") # p指定了tag的name, sister指定了所有tag的class属性如果是'sister'就会被返回
keyword参数
如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜索,如果包含一个名字为 id 的参数, Beautiful Soup会搜索每个tag的”id”属性
soup.find_all(id='link2')
# [Lacie]
soup.find_all(href=re.compile("elsie"))
# [Elsie]
多个指定名字参数同时过滤tag的多个属性
soup.find_all(href=re.compile("elsie"), id='link1')
# [three]
定义一个字典来搜索包含特殊属性的tag
soup.find_all(attrs={"data-foo": "value"})
# [foo!]
text参数
soup.find_all(text="Elsie")
# 'Elsie'
soup.find_all(text=["Tillie", "Elsie"])
['Elsie', 'Tillie']
soup.find_all(text=re.compile("Dormouse"))
['The Dormouse's story]
find()方法
find( name , attrs , recursive , text , **kwargs )
它与 find_all() 方法唯一的区别是 find_all() 方法的返回结果是值包含一个元素的列表,而 find() 方法直接返回结果
get_text()
如果只想得到tag中包含的文本内容,那么可以使用 get_text() 方法, 这个方法获取到tag中包含的所有文版内容包括子孙tag中的内容, 并将结果作为Unicode字符串返回:
markup = '\nI linked to example.com\n'
soup = BeautifulSoup(markup)
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 生成器,获得文本列表后手动处理列表:
[text for text in soup.stripped_strings]
# [u'I linked to', u'example.com']
css选择器
我们在写 CSS 时,标签名不加任何修饰,类名前加点,id名前加#,在这里我们也可以利用类似的方法来筛选元素,用到的方法是 soup.select(),返回类型是 list
通过标签名查找
print soup.select('title')
#[The Dormouse's story ]
print soup.select('a')
#[, Lacie, Tillie]
通过类名查找
print soup.select('.sister')
#[, Lacie, Tillie]
通过id名查找
print soup.select('#link1')
#[]
组合查找
学过css的都知道css选择器,如p #link1是查找p标签下的id属性为link1的标签
print soup.select('p #link1') #查找p标签中内容为id属性为link1的标签
#[]
print soup.select("head > title") #直接查找子标签
#[The Dormouse's story ]
属性查找
查找时还可以加入属性元素,属性需要用中括号括起来,注意属性和标签属于同一节点,所以中间不能加空格,否则会无法匹配到。
print soup.select('a[class="sister"]')
#[, Lacie, Tillie]
print soup.select('a[href="http://example.com/elsie"]')
#[]
同样,属性仍然可以与上述查找方式组合,不在同一节点的空格隔开,同一节点的不加空格,代码如下:
print soup.select('p a[href="http://example.com/elsie"]')
#[]
以上的 select 方法返回的结果都是列表形式,可以遍历形式输出,然后用 get_text() 方法来获取它的内容
soup = BeautifulSoup(html, 'lxml')
print type(soup.select('title'))
print soup.select('title')[0].get_text()
for title in soup.select('title'):
print title.get_text()