第三关:爬虫库BeautifulSoup - 0入门到进阶(附练习题) | Python爬虫

Python爬虫 - 专栏链接

手把手教你如何入门,如何进阶。

目录

1.  BeautifulSoup是什么?

2.  BeautifulSoup怎么用?

2.1  解析数据

2.2  提取数据

2.3  find() 方法 和  find_all() 方法

2.4  Tag标签 和 css 选择器

练习题

联系我们,一起学Python吧


1.  BeautifulSoup是什么?

我们先熟悉下爬虫的四个步骤1、获取数据。2、解析数据。3、提取数据。4、储存数据。

第1关的requests库帮我们搞定了爬虫第1步——获取数据;第2关的HTML知识,是进行爬虫必不可少的背景知识,能辅助我们解析和提取数据。

而本关学习目标:学会使用 BeautifulSoup 解析提取网页中的数据。

使用 BeautifulSoup 库 前需要先安装,可以通过在命令行中输入:

pip install beautifulsoup4

2.  BeautifulSoup怎么用?

2.1  解析数据

我们以豆瓣读书 Top250 为例,它的网址是:https://book.douban.com/top250。

我们来看看如何将其网页源代码解析成 BeautifulSoup 对象

import requests
from bs4 import BeautifulSoup

# 反爬策略之一,下一关重点说明反爬
headers = {
  'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0'
}
res = requests.get('https://book.douban.com/top250', headers=headers)
soup = BeautifulSoup(res.text, 'html.parser')

注意:这里代码中多了一串代码,headers数组,这是反爬策略中的一种,下一关重点说明,如果不加这个数据,爬取不到我们要的数据。headers的作用是:伪装成浏览器,去访问该网页地址,这个数据可以通用的,可以去网上任意找个别人的,也可以自己打开浏览器查看,如下图:

我们通过 from bs4 import BeautifulSoup 语句导入 BeautifulSoup,然后使用 BeautifulSoup(res.text, 'html.parser') 语句将网页源代码的字符串形式解析成了 BeautifulSoup 对象

创建 BeautifulSoup 对象时需要传入两个参数,第一个参数是要解析的 HTML 文本,即网站源代码的字符串形式(res.text)。第二个参数是解析 HTML 的解析器,html.parser 是 Python 中内置的解析器,较为简单方便,本课程中都将使用它。

2.2  提取数据

res = requests.get('https://book.douban.com/top250', headers=headers)
print(type(res.text))
# 输出:<class 'str'>  字符串

# 转为 BeautifulSoup 对象
soup = BeautifulSoup(res.text, 'html.parser')
print(type(soup))
# 输出:<class 'bs4.BeautifulSoup'> 对象

为什么我们要把网页的源代码转换为 BeautifulSoup 对象 呢?

因为 BeautifulSoup 对象 里的方法和属性有很多,我们只学习其中最常用的一些,这些足以应付大多数场景。等真正的入门后,可以自学那些更高阶的知识去解决更复杂的问题。

2.3  find() 方法 和  find_all() 方法

find() find_all() BeautifulSoup 对象的两个方法,它们可以匹配html的标签和属性,把BeautifulSoup对象里符合要求的数据都提取出来。

它俩的用法基本是一样的,区别在于,find()只提取首个满足要求的数据,而find_all()提取出的是所有满足要求的数据。

假设一个场景:爬取出豆瓣top250第一页的25本书的标题。

找数据技巧:鼠标右键标题红楼梦检查元素(火狐是检查,谷歌是审查),右侧查看红楼梦所在的html标签结构,因为有25本书,再看第二个标题活着检查元素,这个时候右侧的html结果都展开一下,把离数据最近的几个标签展开,如果有相同的div的class的值相同的,那么这个就是我们需要的元素结构。

find_all() 的场景:找到了数据所在的元素结构,直接看代码:

import requests
from bs4 import BeautifulSoup

headers = {
  'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0'
}
res = requests.get('https://book.douban.com/top250', headers=headers)
soup = BeautifulSoup(res.text, 'html.parser')
# 前面的代码补上下列代码,注意这里用的是 find_all方法,获取多个元素结构
items = soup.find_all('div',class_='pl2')    # 提取所有div标签满足 class属性值为pl2的标签,注意语法的class_ 有个下横杠,为了和class区别开
print(items)

打印结果是这样的(这里的数据是div的类属性class等于pl2的标签数据,下一步我们可以去除这些标签数据):

仔细看红框处,这里获取的数据是列表形式的,find_all()提取出的是所有满足要求的数据。

find() 的场景:直接看代码:

import requests
from bs4 import BeautifulSoup

headers = {
  'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0'
}
res = requests.get('https://book.douban.com/top250', headers=headers)
soup = BeautifulSoup(res.text, 'html.parser')
# find_all方法换成find方法后打印查看数据
items = soup.find('div',class_='pl2')
print(items)

打印结果是这样的:

打印的结果是字符串形式的,而且只有一条数据。

find_all() 方法 和 find() 方法的区别就是这样,根据实际数据用哪种方法。(我们这里需要用 find_all() 方法,因为要获取25本书的标题,而不是首个标题)

2.4  Tag标签 和 css 选择器

我们接着上面的代码继续往下,拿到我们要的25本书的标题数据。

因为我们用 find_all() 方法获得到的是列表,那么我们就循环:(第二行我们用到了 find() 方法了,因为数据在div属性class='pl2'下的首个a标签内)

for i in items:
    tag = i.find('a')
    print(tag)

# <a href="https://book.douban.com/subject/1007305/"onclick="&quot;moreurl(this,{i:'0'})&quot;"title="红楼梦">红楼梦</a>
# <a href="https://book.douban.com/subject/4913064/"onclick="&quot;moreurl(this,{i:'1'})&quot;"title="活着">活着</a>
# <a href="https://book.douban.com/subject/6082808/"onclick="&quot;moreurl(this,{i:'2'})&quot;"title="百年孤独">百年孤独</a>
# ...

这样,我们就找到了所有书名的数据。此时返回的还是 Tag 对象。如果我们只想要书名和对应的链接呢?这就用到了 Tag 对象text 属性和 HTML 属性名取值

for i in items:
    tag = i.find('a')
    name = tag.text
    link = tag['href']
    print(name,link)
# 红楼梦 https://book.douban.com/subject/1007305/
# 活着 https://book.douban.com/subject/4913064/
# 百年孤独 https://book.douban.com/subject/6082808/
# ...

我们通过 Tag 对象text 属性拿到了 a 标签里的文字内容,即 追风筝的人 等。然后我们通过和字典取值一样的方式,将 HTML 属性名 作为键,得到了对应属性的值。这里是以 href 属性为例,其他的 HTML 属性也同样可以。

我们通过多次调用 find()find_all() 方法一层层地找到了我们需要的数据。你可能会问,有没有什么方法可以直接就找到我们需要的数据,而不用多次查找吗?

答案是肯定的,需要用到 CSS 选择器,这里简单介绍一下。

来看个例子感受一下它们的区别:

from bs4 import BeautifulSoup

html = '''
<div class="item">
  <p class="book">红楼梦</p>
  <div class="hot">
    <p class="book">百年孤独</p>
  </div>
</div>'''

soup = BeautifulSoup(html, 'html.parser')

print(soup.select('.item.book'))    # 两个类选择器要有空格分开
# 输出:[]

print(soup.select('.item .book'))    # 表示类item下的所有 类值为book的元素
# 输出:[<p class="book">红楼梦</p>, <p class="book">百年孤独</p>]

print(soup.select('.item > .book'))    # 表示item下的第一个 类值为book的元素
# 输出:[<p class="book">红楼梦</p>]

CSS 选择器的语法还有很多,这里只介绍了些常用的,你如果对此感兴趣,可以自行深入了解。

了解了 CSS 选择器的基本语法后,我们来看看如何在 BeautifulSoup 中使用。

BeautifulSoup 对象 有一个 select() 方法,我们将 CSS 选择器 传进去即可直接找到我们需要的元素。上面查找在 class="pl2"div 标签 里的 a 标签 的代码就可以这样写:

# items = soup.find_all('div',class_='pl2')
items = soup.select('.pl2 > a')    # 类值为pl2下的第一个a标签
for i in items:
    # tag = i.find('a')
    # name = tag.text
    name = i.text
    # link = tag['href']
    link = i['href']
    print(name,link)
# 红楼梦 https://book.douban.com/subject/1007305/
# 活着 https://book.douban.com/subject/4913064/
# 百年孤独 https://book.douban.com/subject/6082808/

可以看到,我们一次性就将所有符合条件的 a 元素找了出来,同样的功能,代码变得更加简洁了。

对于对 CSS 选择器较为了解的人来说,使用 CSS 选择器的方法十分方便简洁。但即使不了解 CSS 选择器也没关系,我们还有简单好用的 find()find_all() 方法,不是吗?

我们来总结一下 Tag 对象 的常用属性和方法:

知识点拓展:获取的数据存在换行,空格时,我们可以使用:1   .strip()去除首尾空格。2  .replace('\n','')去除换行为空白,.replace(' ','')去除所有字符串中的空格。

练习题

同学们,先自觉练习,答案在公众号,公众号回复暗号【答案】即可。

1. 用来解析网页的 Python 库是?

A.requests
B.BeautifulSoup
C.range
D.html

2. 下列代码的运行结果是?

from bs4 import BeautifulSoup

html = '''
<div class="wrapper">
  <p class="title">Python家庭</p>
  <p class="desc">带你打开编程世界的大门</p>
</div>
'''
soup = BeautifulSoup(html, 'html.parser')
tag = soup.find('p')
print(tag)

A.<p class="title">Python家庭</p>
B.<p class="desc">带你打开扇贝世界的大门</p>
C.[<p class="title">Python家庭</p>, <p class="desc">带你打开编程世界的大门</p>]

3. 下列代码的运行结果是?

from bs4 import BeautifulSoup

html = '''
<div class="wrapper">
  <p class="title">Python家庭</p>
  <p class="desc">带你打开编程世界的大门</p>
</div>'''
soup = BeautifulSoup(html, 'html.parser')
tags = soup.find_all('p')
print(tags)

A.<p class="title">Python家庭</p>
B.<p class="desc">带你打开扇贝世界的大门</p>
C.[<p class="title">Python家庭</p>, <p class="desc">带你打开编程世界的大门</p>]

4. 下列代码的运行结果是?

from bs4 import BeautifulSoup

html = '''
<div class="wrapper">
  <p class="title">Python家庭</p>
  <p class="desc">带你打开编程世界的大门</p>
</div>'''
soup = BeautifulSoup(html, 'html.parser')
tag = soup.find(class_="title")
print(tag.text)

A.Python家庭
B.带你打开编程世界的大门
C.<p class="title">Python家庭</p>
D.<p class="desc">带你打开编程世界的大门</p>

5.  代码实操:爬取 https://book.douban.com/top250  豆瓣书籍该页面下的书籍全部数据,如下图:

练习知识点:

方法1:find_all() 和 find() 方法搭配使用。

方法2:css选择器select()的使用。

先要自己动手练习喔,再去查看答案代码,答案代码两种方法都有。

联系我们,一起学Python吧

每周每日,分享Python实战代码,入门资料,进阶资料,基础语法,爬虫,数据分析,web网站,机器学习,深度学习等等。


​微信群(关注「Python家庭」一起轻松学Python吧)

​QQ 群(983031854

猜你喜欢

转载自blog.csdn.net/qq_34409973/article/details/105754241
今日推荐