搜索文档树里面主要讲find()以及find_all()的用法。在讲这两个用法之前先来说说过滤器,什么过滤器呢?顾名思义,过滤器就是按照条件过滤掉不符合的,留下符合的。那么在Python中这些条件可以是什么呢?我们来依次介绍

1.字符串(这个没什么好讲的)

2.正则表达式(不知道的可以百度一下什么意思)

3.列表:如果传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回.

4.True:True可以匹配任何值

再来说说方法,什么时候用这个方法呢?当你没有合适的过滤器的时候,那便可以定义一个方法,方法只接受一个元素,如果返回True那么表示当前元素与之匹配并且被找到,反之将会返回false

你可以定义一个寻找包含class但是不包含id的标签def has_class_but_no_id(tag):

return tag.has_attr('class') and not tag.has_attr('id')

好了可以来讲讲find_all()和find()了

先来说说.find_all(),它的具体使用规则如下

.find_all(tag,attributes,recursive,text,limit,keywords)

虽然这里有这么多个参数但是其实我们绝大多数时候只使用前两个参数

那么我们一一介绍一下这些参数

tag:就是之前讲的标签名(像

什么之类的),你可以传入一个标签名或者多个 标签组成的列表

attributes:是一个用python字典封装的一个标签的若干属性以及其值,例如:.find_all("span",{"class":{"green","red"}})这就可以找出所有class为green和red的span标签

recursive:是一个递归参数,他是一个布尔变量如果设为True那么会根据要求查找所有子标签以及子标签的子标签,如果设为False那么只会查找文档的一级标签。当然他的默认值是True。一般我们也用不到去修改它。

text:他和attributes有点像但又很是不同,他是用标签里面的文本去匹配而不是标签的属性

limit:只适用于find_all()方法,你可以指定有多少项结果返回过来,要注意的是,设置了limit后返回的是按照顺序返回的,不一定是你想要的结果。

keyword:可以让你选择那些具有指定属性的标签,例如:.find_all(id = "text")这个可以找出所有id=text的标签

但是要记住,不要滥用keyword,keyword只是BeautifulSoup中的一个冗余功能,虽然在有些场景下它显得特别有用,但是任何能够用keyword解决的问题都可以用其他方式解决,

就上一个例子来说

和.find_all("",{"id":"text"})是完全一样的

接下来我们会来说说keyword的一些“缺点”

我们知道class是Python中的一个保留字,是不能当做变量名来使用的。但是HTML标签中经常会有class的属性这时候.find_all(class = "green")就么没有用了。你可以用以下方法解决

.find_all(class_="green")来代替,也就是在class后面加一个_(下划线),但是这个方法显得有点臃肿

我们完全可以用以下方法来代替.find_all("", {"class":"green"})

再顺便说一下,用标签参数将tag以列表的形式传入是或关系的过滤器而keyword的与的选择器

再来说说.find,.find其实就是.find_all()的一种特殊情况,也就是limit = 1的特殊情况。而.find_all()方法是返回一个列表而find方法是直接返回结果

.find_all()和.find只会去搜索子孙节点,如果要搜寻父节点的话那就要用.find_parents()和.find_parent()这个两个的参数和.find_all()和.find()的一样。其中.find_parents()和.parents功效相似,.find_parent()和.parent功效相似。BeautifulSoup还有一些其他的搜索API其中一半是和find()的参数一样一半是和.find_all()的参数一样,

其他的几个分别是(中括号中的是与之功效相似的):

.find_next_siblings()[.next_siblings],.find_next_sibling()[.next_sibling],.find_previous_siblings()[.previous_siblings],.find_previous_sibling()[.previous_sibling],.find_all_next()[.next_elements],.find_next()[.next_element],.find_all_previous()[.previous_elements],.find_previous()[.previous_elements]

CSS选择器

BeautifulSoup对象支持绝大多数CSS选择器,在Tag和BeautifulSoup对象的.select()方法中传入字符串参数就可以找到相应的tag(返回结果一般是列表的形式)那么我们就来说说它的使用方法。

1.可以直接通过标签选择:

例如(还是以第二篇的那个HTML为例子):

soup.select("title")

那么就可以得到以下结果:[

The Dormouse's story],通过这个方法可以得到所有title标签


也可以用这个语法:

soup.select("p:nth-of-type(3)")

那么就可以得到以下的结果:

[
....
]


在这个例子中p:nth-of-type(3)这条语法相当于是选择第三个p标签,相当于soup.select(p)[2])

我们也可以通过tag逐层寻找:

soup.select("body a")这方法可以找到body下所有的a标签

也可以用这个soup.select("body > a")(这里的body和>和a之间一定要有空格)这个方法的话可以得到的是body下属的第一个a标签

也可以来组合一下:

soup.select("p > a:nth-of-type(2)")

当然也会有寻找兄弟节点的方法:

soup.select("#link1 ~ .mysis")这个方法可以找到id = link1后的所有兄弟节点标签

而这个方法soup.select("#link1 + .mysis")是可以得到id = link1的下一个兄弟标签

2.我们也可以通过类名来寻找

例如:

soup.select(".story")这个方法可以找到所有class为story的标签

soup.select("p.sister")这个方法可以找到所有class为story的p标签

3.也可以通过id去查找

例如:

soup.select("#link1")这个方法可以找到所有id = #link的标签

soup.select("a#link2")而这个方法可以得到所有id = #link的a标签

4.也可以通过属性来查找

一、是否存在某种属性:

soup.select('a[href]')寻找存在href属性的标签

二、通过属性的值去寻找:

soup.select('a[href="http://example.com/elsie"]')这条指令可以找到所有href值为http://example.com/elsie的a标签

5.也可以通过语言来设置:

看这个例子:

language = """
Hello
Howdy,y'all
Pip-pip, old fruit
Bonjour mes amis
"""
soup = BeautifulSoup(language,'lxml')
soup.select('p[lang|=en]')这条指令可以得到一下结果:[
Hello
, 
 
Howdy,y'all
, 
 
Pip-pip, old fruit
]