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

用 Beautiful Soup 提取 href

当我在 Chrome 中单击检查时,如何让 Beautiful soup html 解析器与显示的代码相同?

Beautiful Soup