Beautiful Soup入门

主要流程:

  • 导入BeautifulSoup类
  • 传递初始化参数,并初始化
  • 获取实例对象,操作对象获取解析、提取数据

1.初始化Beautiful Soup对象

从bs4库导入Beautiful Soup类 实例化一个对象。

from bs4 import BeautifulSoup
soup = BeautifulSoup(markup, features)

在实例化过程中,需要给Beautiful Soup这个类传递两个参数:

第一个参数:markup

  • 参数解析:被解析的HTML字符串或文件内容
  • 使用方式两种

(1)使用字符串变量

#使用第一步的html_str字符串变量
from bs4 import BeautifulSoup
soup = BeautifulSoup(html_str)

(2)使用open()函数打开文件

#假设将html_str字符串写入了index.html中
from bs4 import BeautifulSoup
soup = BeautifulSoup(open(index.html))

第二个参数,features

  • 参数解释:解析器的类型
  • 使用方式:

(1)指定解析器,BeautifulSoup选择指定的解析器来解析文档

#指定lxml作为解析器
from bs4 import BeautifulSoup
soup = BeautifulSoup(html_str, 'lxml')

(2)未指定解析器,BeautifulSoup选择最默认的解析器来解析文档

#解析html_str选择最默认的解析器
from bs4 import BeautifulSoup
soup = BeautifulSoup(html_str)

在初始化对象的时候,需要给BeautifulSoup类传递两个参数。

2.认识选择器

选择器用来查找、定位元素,并获取数据。

选择器的分类

  • 节点选择器
  • 方法选择器
  • CSS选择器

节点选择器是获取数据的基础方法,而方法选择器和CSS选择器则是查找、定位元素的常用选择。

(1)节点选择器

i 选择元素的方法

节点选择器就是使用tag对象来选择节点元素。而tag对象与HTML、XML的原生文档中的Tag相同,即标签。

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

title和a标签及里面的内容成为Tag对象。

  • 格式

获取元素:soup.tag 

#soup为Beautiful Soup4的对象

返回值:节点元素

  • 实例

  • 选取元素只需要在Beautiful Soup对象的后面加上标签名即可,例如:soup.title
  • 获取到的节点是tag对象
  • 当有多个相同节点的时候,只会返回第一个节点 

ii 获取信息的方法

通过选择元素的方式,我们获取到了标签的全部信息,如果我们想要提取标签中的信息,可以使用如下方式:name获取名称、attrs获取属性、string获取内容。

  • 获取名称

格式:soup.tag.name

返回值:字符串

示例:

#获取a标签的名字
soup.a.name

#输出结果
a
  • 获取属性

格式:soup.tag.attrs

返回值:字典

示例:

#获取a标签的属性
soup.a.attrs

#输出结构
{'href':'http://example.com/elsie','class':['sister'],'id':'link1'}
  • 获取内容

格式:soup.tag.string

返回值:字符串

示例:

#获取a标签的内容
soup.a.string

#输出结果
Elsie

iii 嵌套选择的方法

我们可以使用soup.tag获取bs4.element.Tag类型的节点,并获取他们的信息:

<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>

如果提取到的节点还嵌套这其他子节点

<head><title>The Dormouse's story</title></head>

那我们可以通过下面的操作方式来获取子节点的信息。

格式:soup.tag.tag

返回值:节点元素

示例:

#获取title
print(soup.head.title)

#打印获取到的title类型
print(type(soup.head.title))

#获取title的信息
print(soup.head.title.string)

#输出结果
<title>The Dormouse's story</title>
<class 'bs4.element.Tag'>
The Dormouse's story

soup.tag.tag:在Tag类型的基础上再次选择得到的依然是Tag类型,每次返回的结果相同,就可以进行嵌套选择了。

IV 关联选择的方法

在做选择的时候,有时候不能做到一部就选到想要的节点元素,例如示例中的第二个a节点:

<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;

需要先选中某一个节点元素,然后以它为基准再选择它的子节点、父节点、兄弟节点等。

子节点:contents、childeren;子孙节点:descendants;父节点:parent;祖先节点:parents;兄弟节点:next_sblings、previous_sblings、previous_sblings、next_sbling。

  • 子节点

格式:soup.tag.contens

返回值:列表

示例:

#获取p节点的子节点
print(soup.p.contents)

#输出结果
['Once upon a time there were three little sisters; and their names were\n',<...]

格式:soup.tag.children

返回值:生成器(所以需要用for循环依次取出来)

示例:

#获取p节点的每一个子节点
print(soup.p.children)
for i, child in enumerate(soup.p.children):
   print(i,child)
  • 父节点

格式:soup.tag.parent

返回值:节点元素

示例:

#打印选取的a节点
print(soup.a)
#获取a节点的父节点
print(soup.a.parent)

#输出结果
#选取的a节点
<a class="sisier" href="http://example.com/elsie" id="link1"><span>Elsie</span></a>
#所选a节点的父节点
<a class="story">Once upon a time there were three little sister; and their names were.. 
<a class="sisier" href="http://example.com/elsie" id="link1"><span>Elsie</span></a>,
<a class="sisier" href="http://example.com/lacie" id="link2">Lacie</span></a> and
<a class="sisier" href="http://example.com/tillie" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
  • 祖先节点

如果想要获取祖先节点,可以调用parents属性。

格式:soup.tag.parents

返回值:生成器

示例:

  •  兄弟节点

如果想要获取同级的节点,使用sibing获取兄弟节点。

获取后面一个节点

格式:soup.tag.next_sibling

返回值:节点元素

示例:

#获取a节点的后面一个节点
print(soup.a.next_sibling)
#获取类型
print(type(soup.a.next_sibling))

#输出结果
<class 'bs4.element.NavigableString'>
  • 获取后面所有的节点

格式:soup.tag.next_siblings

返回值:生成器

示例:

  •  获取前面一个节点

格式:soup.tag.previous_sibling

返回值:节点元素

示例:

#获取a节点的前一个节点
print(soup.a.previous_sibling)
#获取类型
print(type(soup.a.previous_sibling))

#输出结果
Once upon a time there were three little sisters; and their names were <class 'bs4.element.NavigableString'>
  • 获取前面的所有节点

格式:soup.tag.previous_siblings

返回值:生成器

示例:

#获取a节点前面的所有节点
print(soup.a.previous_siblings)
#获取类型
print(type(soup.a.previous_siblings))
#获取所有的内容
print(list(enumerate(soup.a.previous_siblins)))

#输出结果
<generator object previous_siblings at 0x102334468>
<class 'generator'>
[(0,'Once upon a time there were three little sisters; and their names were\n')]

子节点

  • soup.tag.contents
  • soup.tag.children

子孙节点

  • soup.tag.descendants

父节点

  • soup.tag.parent

祖先节点

  • soup.tag.parents

兄弟节点

  • soup.tag.next_sibling
  • soup.tag.next_siblings
  • soup.tag.previous_sibling
  • soup.tag.previous_siblings

(2)CSS选择器

  • 使用CSS选择器定位元素
  • 嵌套选择
  • 获取属性
  • 获取文本

获取元素

格式:soup.select()

CSS选择器语法

i id选择器

id选择器需要 # 来定位元素,例如:获取第一个ul节点 #list-1

<div class="panel-body">
  <ul class="list" id="list-1">
...

ii 类选择器

类选择器需要使用 . 来定位元素,例如:获取所有的ul.list

<div class="panel-body">
  <ul class="list" id="list-1">
   <li class="element"> Foo<li>
...

  <ul class="list list-small" id="list-2">
...

iii 标签选择器

标签选择器需要使用标签来进行选择,例如:获取h4:h4

<div class="panel-heading">
  <h4>Hello</h4>
<div>

IV 混合使用

获取第一个ul中的li节点,.panel-body #list-1 li

<div class="panel-body">
  <ul class="list" id="list-1">
    <li class="element">Foo</li>
    <li class="element">Bar</li>
    <li class="element">Jay</li>
  </ul>

  <ul class="list list-small" id="list-2">
     <li class="element"> Foo</li>
     <li class="element"> Bar</li>
  </ul>
</div>

示例:

  • 获取class="panel-heading"的div
  • 获取所有的li节点
  • 获取第二个ul的li节点
  • 获取第二个ul节点
html = '''
<div class="panel">
  <div class="panel-heading">
     <h4>Hello</h4>
  </div>
  
  <div class="panel-body">
      <ul class="list" id="list-1">
         <li class="element"> Foo</li>
         <li class="element"> Bar</li>
         <li class="element"> Jay</li>
      </ul>

      <ul class="list list-small" id="list-2">
         <li class="element"> Foo</li>
         <li class="element"> Bar</li>
      </ul>
   </div>
</div>
...

#导入Beautiful Soup类
from bs4 import BeautifulSoup

#传入参数,实例化这个类
soup=BeautifulSoup(html,'lxml')

#获取class="panel-heading"的div
print(soup.select(".panel.panel-heading"))

#获取所有的li节点 标签选择器
print(soup.select("ul li"))

#获取所有的li节点 类选择器
print(soup.select(".list.element"))

#获取第二个ul的li节点 id选择器
print(soup.select("#list-2 li"))

#获取第二个ul的li节点 类选择器
print(soup.select(".list-samll li"))

#获取第二个ul的li节点 列表获取
print(soup.select("ul")[1])

CSS选择器的高级用法:

i 嵌套选择

先选择一个节点,再获取这个节点下面的子节点。

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print(soup.select("ul"))
print(type(soup.select("ul")))
for ul in soup.select("ul"):
    print(ul)
    print(type(ul))
    print(ul.select("li"))   #这里表明可支持嵌套选择的使用

ii 获取属性

使用attrs属性来获取。

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print(soup.select("#list-2 li"))
for li in soup.select("#list-2 li"):
   print(type(li))
   print(li.attrs)
   print(li.attrs['class'])

iii 获取文本

使用string和strings属性来获取

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')
print(soup.select("#list-2 li"))
for li in soup.select("#list-2 li"):
   print(type(li))
   print(li.attrs)
   print(li.attrs['class'])

print(soup.select("#list-2"))
for ul in soup.select("#list-2"):
  print(type(ul))
  print(ul.strings)
  print(list(ul.strings))

(3)方法选择器

前面的选择方法都是通过标签和属性来选择的,这种方法非常快,但是如果在比较复杂的页面中选择元素,无法精准定位到元素。

<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;

在HTML文档中存在多个<a>标签,我们无法使用节点选择器定位到第二个、第三个<a>标签。

因此我们将采用findall()和find()方法,通过传入参数的方法来定位。

获取所有符合条件的元素find_all()
获取符合条件的第一个元素find()
获取所有符合条件的祖先节点find_parents()
获取符合条件的父节点find_parent()
获取后面所有符合条件的兄弟节点find_next_siblings()
获取后面第一个符合条件的兄弟节点find_next_sibling()
获取前面所有符合条件的兄弟节点find_previous_siblings()
获取后面所有符合条件的节点(包括子孙节点)find_all_next()
获取后面第一个符合条件的节点find_next()
获取前面所有符合条件的节点(包括子孙节点)find_all_previous()
获取前面第一个符合条件的节点find_previous()
获取后面第一个符合条件的兄弟节点find_next_sibling()

方法选择器中的find_all()方法

find_all(name,attrs,recursive,text, **kwargs)

  • name参数

作用:查找所有名字为name的节点(tag对象)

参数形式:

  • 字符串

传入字符串参数,即标签名(tag),Beautiful Soup会查找与字符串完全匹配的内容

#寻找所有soup标签
print(soup.find_all('span'))

#输出结果
[<span>Elsie</span>]
  • 正则表达式

传入正则表达式,Beautiful Soup会通过正则表达式的match()函数来匹配内容

#使用正则匹配以b开头的标签
import re

for tag in soup.find_all(re.compile('^b")):
  print(tag.name)

#输出结果
body
  • 列表

传入列表参数,Beautifl Soup会将与列表中任一元素匹配,并返回结果。

#使用列表选择包含a和span的所有标签
print(soup.find_all(['a','span']))

#输出结果
[<a class="sister" href="http://example.com/elsie" id="link1"><span>Elsie</span></a>],
  • True

True可以匹配任何值

#使用True选择文件中所有标签
for tag in soup.find_all(True):
   print(tag.name)

#输出结果
html
head
title
...

  •  attrs参数

作用:查询含有接受的属性值的标签

参数形式:字典类型

#获取id为link1的标签
print(soup.find_all(attrs={id:'link1'}))

#输出结果
[<a class="sister" href="http://example.com/elsie" id="link1"><span>Elsie</span></a>]
  • kwargs参数

作用:接受常用的属性参数,如id何class

参数形式:变量赋值的形式

#获取id为link1的标签
print(soup.find_all(id='link1'))

#输出结果
[<a class="sister" href="http://example.com/elsie" id="link1"><span>Elsie</span></a>]

这里直接传入id='link1',就查询到id为'link1'的节点元素了。而对class来说,它在Python中是一个关键词,需要加一个下划线,即class_='element'

#获取id为link1的标签
print(soup.find_all(class_='story'))
  • text参数

作用:查询含有接收的文本的标签

参数形式:字符串

通过搜索文档中的字符串内容,来确定文件标签

#获取文本中包含Elsie内容
print(soup.find_all(text='Elsie')))

#输出结果
['Elsie']

可以与其他参数混合使用来过滤tag

print(soup.find_all['a',text='Elsie'])
#搜索a标签中含有Elsie的字符串
print(soup.find_all(text='story'))
#只比对story,会发现比对不上,需要把story前面的信息补充上

import re
print(soup.find_all(text=re.compile('.*?story')))
#使用text获取包含story的标签
#且必须写text
  • limit参数

作用:用于限制返回结果的数量

参数形式:整数

#获取前两个a标签
print(soup.find_all('a',limit=2))
  • recursive参数

作用:决定是否获取子孙节点

参数形式:布尔值,默认是True

print(soup.find_all('title'))
print(soup.find_all('title',recursive=False))

find_all()方法的使用:

  1. name参数用来接收tag名称,有四种形式:字符串,正则,列表和True
  2. attrs参数用来接收属性的键值对字典
  3. kwargs参数用来接收常用属性的变量赋值的形式 例如:id='link1',class="sister"
  4. text参数用来接收文本信息
  5. limit参数用来限制返回结果的数量
  6. recursive参数用来决定是否获取子孙节点

方法选择器中find()方法和其他方法

find()方法和find_all()方法区别在于:

  • find_all()方法返回所有符合条件的元素列表,而find()方法就是返回符合条件的第一个元素
  • 除了limit参数不能在find()方法中使用,find()方法的其他参数和find_all()的参数用法一样

find()方法:

作用:查找当前节点,符合条件的一个元素节点

范围:当前节点下的一个元素

  • name参数
#获取a标签
print(soup.find('a'))

#输出结果
<a class="sister" href="http://example.com/elsie" id="link1"><span>Elsie</span></a>
  • attrs参数
#获取class等于sister的标签
print(soup.find(attrs={'class':'sister'))


#输出结果
<a class="sister" href="http://example.com/elsie" id="link1"><span>Elsie</span></a>
  • kwargs参数
#获取class等于sister的标签
print(soup.find(class_='sister'))

#输出结果
<a class="sister" href="http://example.com/elsie" id="link1"><span>Elsie</span></a>
  • text参数
#获取文本中包含story的标签
print(soup.find(text=re.compile('.*?story')))

#输出结果
The Dormouse's story
  • recursive参数
#获取文本中包含story的标签
print(soup.find('a', recursive=False))

#输出结果
None

(以上为学习Python爬虫之Beautiful Soup教程的学习笔记)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Beautiful Soup 是一个Python库,用于从HTML和XML文件提取数据。它提供了一种简单的方式来遍历、搜索和修改解析树,让你能够轻松地从网页提取所需的信息。 以下是 Beautiful Soup 的基础入门步骤: 1. 安装 Beautiful Soup: 你可以使用 pip 来安装 Beautiful Soup。在命令行运行以下命令: ``` pip install beautifulsoup4 ``` 2. 导入 Beautiful Soup: 在你的 Python 脚本导入 Beautiful Soup 模块: ```python from bs4 import BeautifulSoup ``` 3. 创建 Beautiful Soup 对象: 使用 BeautifulSoup 函数,将要解析的 HTML 或 XML 字符串作为参数传入,并指定解析器,例如 'html.parser': ```python soup = BeautifulSoup(html_doc, 'html.parser') ``` 4. 解析 HTML 结构: 你可以使用不同的 Beautiful Soup 方法来遍历解析树,从而提取数据。例如,你可以使用 `find` 方法来查找符合特定条件的单个元素,或者使用 `find_all` 方法来查找所有符合条件的元素。 ```python # 查找第一个 <p> 标签 paragraph = soup.find('p') # 查找所有 <a> 标签 links = soup.find_all('a') ``` 5. 提取数据: 一旦你找到了所需的元素,你可以使用 Beautiful Soup 提供的各种方法来提取其文本或属性。 ```python # 提取 <p> 标签的文本 paragraph_text = paragraph.get_text() # 提取 <a> 标签的 href 属性值 for link in links: href = link['href'] ``` 这只是 Beautiful Soup 的基础入门,它还有更多功能和用法。你可以参考官方文档来深入学习:https://www.crummy.com/software/BeautifulSoup/bs4/doc/

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值