Beatiful Soup
Posted 爱码适
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Beatiful Soup相关的知识,希望对你有一定的参考价值。
一、简介
Beautiful Soup 自动将输入文档转换为Unicode编码,输出文档转换为“uft-8”编码。
Beautiful Soup 提供一些简单的,python函数来处理导航、探索、修改分析树等功能。
二、基本用法
案列
from bs4 import BeautifulSoup
html='''
<html><head><title> 豆瓣电影 </title></head>
<body>
<dd>
<i class="board-index board-index-1">1</i>
<a href="/films/1200486" title="我不是药神" class="image-link" data-act="boarditem-click" data-val="movieId:1200486">
<img src="//s3plus.meituan.net/v1/mss_e2821d7f0cfe4ac1bf9202ecf9590e67/cdn-prod/file:5788b470/image/loading_2.e3d934bf.png" alt="" class="poster-default" />
<img data-src="https://p0.meituan.net/movie/414176cfa3fea8bed9b579e9f42766b9686649.jpg@160w_220h_1e_1c" alt="我不是药神" class="board-img" />
</a>
<div class="board-item-main">
<div class="board-item-content">
<div class="movie-item-info">
<p class="name"><a href="/films/1200486" title="我不是药神" data-act="boarditem-click" data-val="movieId:1200486">我不是药神</a></p>
<p class="star">
主演:徐峥,周一围,王传君
</p>
<p class="releasetime">上映时间:2018-07-05</p> </div>
<div class="movie-item-number score-num">
<p class="score"><i class="integer">9.</i><i class="fraction">6</i></p>
</div>
</div>
</div>
</dd>'''
soup=BeautifulSoup(html,'lxml') # 将第一参数传递给BeautifulSoup解析对象,该对象的第二参数为解析器的类型(这里使用lxml类型),此时完成了BeautifulSoup的对象的初始化。字符串不完整,初始化的时候就可以补全。
print(soup.prettify()) # 调用prittify()方法,这个方法将要解析的字符串以标准的缩进格式输出。
print(soup.title.string) # soup.title可以选出HTML中的title节点,再调用string属性就可以得到节点内的文本了
补充:string是字符串的意思
三、节点选择器
(一).选择元素
节点选择器就是用来选择节点的元素。选择速度快,如果节点的结构非常清晰,用节点选择器非常简单。
html='''
<html><head><title> 豆瓣电影 </title></head>
<body>
<dd>
<i class="board-index board-index-1">1</i>
<a href="/films/1200486" title="我不是药神" class="image-link" data-act="boarditem-click" data-val="movieId:1200486">
<img src="//s3plus.meituan.net/v1/mss_e2821d7f0cfe4ac1bf9202ecf9590e67/cdn-prod/file:5788b470/image/loading_2.e3d934bf.png" alt="" class="poster-default" />
<img data-src="https://p0.meituan.net/movie/414176cfa3fea8bed9b579e9f42766b9686649.jpg@160w_220h_1e_1c" alt="我不是药神" class="board-img" />
</a>
<div class="board-item-main">
<div class="board-item-content">
<div class="movie-item-info">
<p class="name"><a href="/films/1200486" title="我不是药神" data-act="boarditem-click" data-val="movieId:1200486">我不是药神</a></p>
<p class="star">
主演:徐峥,周一围,王传君
</p>
<p class="releasetime">上映时间:2018-07-05</p> </div>
<div class="movie-item-number score-num">
<p class="score"><i class="integer">9.</i><i class="fraction">6</i></p>
</div>
</div>
</div>
</dd>'''
from bs4 import BeautifulSoup
soup=BeautifulSoup(html,'lxml') # 将第一个参数传给BeautifulSoup对象,第二个参数为解析器的类型。
print(soup.title)
print(type(soup.title))
print(soup.title.string)
print(soup.head)
print(soup.p)
运行结果为:
bs4解析出来的类型是tag类型。tag具有一些属性,比如string属性,调用该属性,就可以得到该节点文本的内容。
最后选择p节点时,打印出来的是第一个节点内容,后面的p节点没有打印出来,也就说,当有多个节点时,只会匹配第一个节点,剩下的节点不会匹配。
(二).提取元素
1.获取名称
可以利用name属性获取节点的名称。以上面的文本为例,选取title的节点,然后调用name属性就可以得到该节点的名称。代码如下:
print(soup.title.name)
运行结果如下:
2.获取属性
每个节点可能有多个属性,比如id,class等,选择这个节点元素后,可以调用attrs获取所有属性,代码如下:
print(soup.p.attrs)
print(soup.p.attrs['class'])
运行结果如下:
soup.p.attrs获取节点p所有的属性和属性值,attrs返回的属性和属性值是字典形式。
如果想获取属性值,不调用attrs也可以,直接在节点后面用中括号加属性名就可以获取。如soup.p['class'],.
注意:如果节点有多个属性,返回的是列表,如果节点只有一个属性,返回的是字符串,在实际处理过程中,要注意判断类型。
3.内容获取
利用string属性来获取文本内容。代码如下:
print(soup.title.string)
运行结果:
(三)嵌套选择
不管怎样嵌套,返回的结果也是tag类型,所以照样可以用string属性。
(四)关联选择
选择节点的时候,有些节点不可能一步到位,必须以某一节点为基础,再选择它的子节点、父节点、兄弟节点等等。
1.子节点和子孙节点
获取直接子节点:soup.节点.contents,获取所有子孙节点:soup.节点.descendants。
2.父节点和祖先节点
获取某个节点的父节点,调用parent属性。soup.节点.parent。获取祖先节点用parents.
3.兄弟节点
4.提取信息
如何返回的是单个节点,调用string、attrs等属性获取文本和属性;如果返回的是多个节点,则可以转为列表后提取某个元素,然后再调用string、attrs等属性获取文本或属性。
(五)方法选择器
1.findall_all(),通过传入参数,查询所有符合条件的元素。
API如下:
find_all(name,attrs,recursive,text,**kwargs)
name 根据名称节点来选取元素。代码如下
html=''' +<i class="board-index board-index-1">1</i>
<a href="/films/1200486" title="我不是药神" class="image-link" data-act="boarditem-click" data-val="movieId:1200486">
<img src="//s3plus.meituan.net/v1/mss_e2821d7f0cfe4ac1bf9202ecf9590e67/cdn-prod/file:5788b470/image/loading_2.e3d934bf.png" alt="" class="poster-default" />
<img data-src="https://p0.meituan.net/movie/414176cfa3fea8bed9b579e9f42766b9686649.jpg@160w_220h_1e_1c" alt="我不是药神" class="board-img" />
</a>
<div class="board-item-main">
<div class="board-item-content">
<div class="movie-item-info">
<p class="name"><a href="/films/1200486" title="我不是药神" data-act="boarditem-click" data-val="movieId:1200486">我不是药神</a></p>
<p class="star">
主演:徐峥,周一围,王传君
</p>
<p class="releasetime">上映时间:2018-07-05</p> </div>
<div class="movie-item-number score-num">
<p class="score"><i class="integer">9.</i><i class="fraction">6</i></p>
</div>
</div>
</div>
'''
from bs4 import BeautifulSoup
soup=BeautifulSoup(html,'lxml')
a=soup.find_all(name='div')[0] # 查找所有div标签,然后赋值给变量a
for i in a:
print(a.find_all(name='p')[0]) # 获取div里面的p节点
for b in a.find_all(name='p')[0]:
print(b.string)[1] # 获取p节点的文本
运行结果如下:
attrs:用属性来查询,获取节点。语法:attrs="属性":"值"。参数的类型是字典类型,得到的结果是列表类型。代码如下
html=''' +<i class="board-index board-index-1">1</i>
<a href="/films/1200486" title="我不是药神" class="image-link" data-act="boarditem-click" data-val="movieId:1200486">
<img src="//s3plus.meituan.net/v1/mss_e2821d7f0cfe4ac1bf9202ecf9590e67/cdn-prod/file:5788b470/image/loading_2.e3d934bf.png" alt="" class="poster-default" />
<img data-src="https://p0.meituan.net/movie/414176cfa3fea8bed9b579e9f42766b9686649.jpg@160w_220h_1e_1c" alt="我不是药神" class="board-img" />
</a>
<div class="board-item-main">
<div class="board-item-content">
<div class="movie-item-info">
<p class="name"><a href="/films/1200486" title="我不是药神" data-act="boarditem-click" data-val="movieId:1200486">我不是药神</a></p>
<p class="star">
主演:徐峥,周一围,王传君
</p>
<p class="releasetime">上映时间:2018-07-05</p> </div>
<div class="movie-item-number score-num">
<p class="score"><i class="integer">9.</i><i class="fraction">6</i></p>
</div>
</div>
</div>
'''
from bs4 import BeautifulSoup
soup=BeautifulSoup(html,'lxml')
a=soup.find_all(attrs='class':'name') # 用attrs来提取属性为class:name的节点
for i in a:
print(i.string) # 获取i节点的文本
运行结果如下:
text参数用来匹配节点的文本,传入的形式可以是字符串,可以是正则表达式。代码如下:
import re
html=''' +<i class="board-index board-index-1">1</i>
<a href="/films/1200486" title="我不是药神" class="image-link" data-act="boarditem-click" data-val="movieId:1200486">
<img src="//s3plus.meituan.net/v1/mss_e2821d7f0cfe4ac1bf9202ecf9590e67/cdn-prod/file:5788b470/image/loading_2.e3d934bf.png" alt="" class="poster-default" />
<img data-src="https://p0.meituan.net/movie/414176cfa3fea8bed9b579e9f42766b9686649.jpg@160w_220h_1e_1c" alt="我不是药神" class="board-img" />
</a>
<div class="board-item-main">
<div class="board-item-content">
<div class="movie-item-info">
<p class="name"><a href="/films/1200486" title="我不是药神" data-act="boarditem-click" data-val="movieId:1200486">我不是药神</a></p>
<p class="star">
主演:徐峥,周一围,王传君
</p>
<p class="releasetime">上映时间:2018-07-05</p> </div>
<div class="movie-item-number score-num">
<p class="score"><i class="integer">9.</i><i class="fraction">6</i></p>
</div>
</div>
</div>
'''
from bs4 import BeautifulSoup
soup=BeautifulSoup(html,'lxml')
print(soup.find_all(text=re.compile('上映时间'))) # compile将正则表达字符串编译成正则表达对象,要提取哪个信息,把参数放到compile里就可以。
运行结果如下:
2.find(),返回的是单个元素,也就是第一个匹配的元素,而find_all()返回的是所有匹配的元素组成的列表。
(六)css选择器
使用css选择器时,只需调用select()方法即可。语法:soup.select(),括号里面放节点名称。代码如下:
html=''' +<i class="board-index board-index-1">1</i>
<a href="/films/1200486" title="我不是药神" class="image-link" data-act="boarditem-click" data-val="movieId:1200486">
<img src="//s3plus.meituan.net/v1/mss_e2821d7f0cfe4ac1bf9202ecf9590e67/cdn-prod/file:5788b470/image/loading_2.e3d934bf.png" alt="" class="poster-default" />
<img data-src="https://p0.meituan.net/movie/414176cfa3fea8bed9b579e9f42766b9686649.jpg@160w_220h_1e_1c" alt="我不是药神" class="board-img" />
</a>
<div class="board-item-main">
<div class="board-item-content">
<div class="movie-item-info">
<p class="name"><a href="/films/1200486" title="我不是药神" data-act="boarditem-click" data-val="movieId:1200486">我不是药神</a></p>
<p class="star">
主演:徐峥,周一围,王传君
</p>
<p class="releasetime">上映时间:2018-07-05</p> </div>
<div class="movie-item-number score-num">
<p class="score"><i class="integer">9.</i><i class="fraction">6</i></p>
</div>
</div>
</div>
'''
from bs4 import BeautifulSoup
soup=BeautifulSoup(html,'lxml')
# a=soup.find_all(name="div")[0]
# print(a)
b=soup.select("div")[0] # 调用select获取节点div
print(b)
运行结果:
获取属性:语句:节点['属性名'] 代码如下:
html=''' +<i class="board-index board-index-1">1</i>
<a href="/films/1200486" title="我不是药神" class="image-link" data-act="boarditem-click" data-val="movieId:1200486">
<img src="//s3plus.meituan.net/v1/mss_e2821d7f0cfe4ac1bf9202ecf9590e67/cdn-prod/file:5788b470/image/loading_2.e3d934bf.png" alt="" class="poster-default" />
<img data-src="https://p0.meituan.net/movie/414176cfa3fea8bed9b579e9f42766b9686649.jpg@160w_220h_1e_1c" alt="我不是药神" class="board-img" />
</a>
<div class="board-item-main">
<div class="board-item-content">
<div class="movie-item-info">
<p class="name"><a href="/films/1200486" title="我不是药神" data-act="boarditem-click" data-val="movieId:1200486">我不是药神</a></p>
<p class="star">
主演:徐峥,周一围,王传君
</p>
<p class="releasetime">上映时间:2018-07-05</p> </div>
<div class="movie-item-number score-num">
<p class="score"><i class="integer">9.</i><i class="fraction">6</i></p>
</div>
</div>
</div>
'''
from bs4 import BeautifulSoup
soup=BeautifulSoup(html,'lxml')
a=soup.select("div")[0] # 获取div节点的属性
for i in a:
print(a['class'])
运行结果如下:
以上是关于Beatiful Soup的主要内容,如果未能解决你的问题,请参考以下文章
启用以使用 Beautiful Soup 获取特定网站的 img 标签
Codeforces Round #471 (Div. 2)B. Not simply beatiful strings
试图通过使用soup.select和soup.find_all来提取URL