美文网首页
Beautiful Soup学习笔记

Beautiful Soup学习笔记

作者: mundane | 来源:发表于2017-12-11 13:24 被阅读39次

开始

首先必须要导入 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中的一个个标签, 例如

<title>The Dormouse's story</title>
<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>

验证一下对象类型

print(type(soup.a))
#<class 'bs4.element.Tag'>

对于Tag, 有两个重要的属性, name和attrs

name

例如一个b标签, 那么它的name就是b, 一个p标签的name就是p

soup = BeautifulSoup('<b class="boldest">Extremely bold</b>', '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方法用于得到标签下的属性值, 注意这是一个重要的方法, 在许多场合都能用到, 比如你要得到<img src="#">标签下的图像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")
# [<title>The Dormouse's story</title>]

soup.find_all("p", "title")
# [<p class="title"><b>The Dormouse's story</b></p>]

soup.find_all("a")
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
#  <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
#  <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

soup.find_all(id="link2")
# [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]

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")
# [<title>The Dormouse's story</title>]

传字符串

soup.find_all('b')
# [<b>The Dormouse's story</b>]
print soup.find_all('a')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>...]

传正则表达式

如果传入正则表达式作为参数,Beautiful Soup会通过正则表达式的 match() 来匹配内容.下面例子中找出所有以b开头的标签,这表示<body>和<b>标签都应该被找到:
for tag in soup.find_all(re.compile("^b")):
    print(tag.name)
# body
# b

传列表

如果传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回.下面代码找到文档中所有<a>标签和<b>标签:
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')
# [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]
soup.find_all(href=re.compile("elsie"))
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]

多个指定名字参数同时过滤tag的多个属性

soup.find_all(href=re.compile("elsie"), id='link1')
# [<a class="sister" href="http://example.com/elsie" id="link1">three</a>]

定义一个字典来搜索包含特殊属性的tag

soup.find_all(attrs={"data-foo": "value"})
# [<div data-foo="value">foo!</div>]

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 = '<a href="http://example.com/">\nI linked to <i>example.com</i>\n</a>'
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') 
#[<title>The Dormouse's story</title>]
print soup.select('a')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

通过类名查找

print soup.select('.sister')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

通过id名查找

print soup.select('#link1')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]

组合查找

学过css的都知道css选择器,如p #link1是查找p标签下的id属性为link1的标签

print soup.select('p #link1')    #查找p标签中内容为id属性为link1的标签
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]
print soup.select("head > title")   #直接查找子标签
#[<title>The Dormouse's story</title>]

属性查找

查找时还可以加入属性元素,属性需要用中括号括起来,注意属性和标签属于同一节点,所以中间不能加空格,否则会无法匹配到。

print soup.select('a[class="sister"]')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
print soup.select('a[href="http://example.com/elsie"]')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]

同样,属性仍然可以与上述查找方式组合,不在同一节点的空格隔开,同一节点的不加空格,代码如下:

print soup.select('p a[href="http://example.com/elsie"]')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]

以上的 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()

相关文章

网友评论

      本文标题:Beautiful Soup学习笔记

      本文链接:https://www.haomeiwen.com/subject/wfsiixtx.html