【python爬虫】3.爬虫初体验(BeautifulSoup解析)
文章目录
- 前言
- BeautifulSoup是什么
- BeautifulSoup怎么用
- 解析数据
- 提取数据
- 对象的变化过程
- 总结
前言
上一关,我们学习了HTML基础知识,知道了HTML是一种用来描述网页的语言,又了解了HTML的基本结构。
认识了HTML中的常见标签和常见属性:
根据这些知识,我们成功修改了这个网页上原来所显示标题——“这个书苑不太冷”,改成了“蜘蛛侠大战网页”。
最后,还写了这样一段代码:即通过调用requests库,获取到了网页源代码,并将它写入到本地:
# 调用requests模块
import requests
# 获取网页源代码,得到的res是response对象。
res = requests.get('https://localprod.pandateacher.com/python-manuscript/crawler-html/spider-men5.0.html')
# 检测请求是否正确响应
print(res.status_code) # 新建一个名为book的html文档,你看到这里的文件没加路径,它会被保存在程序运行的当前目录下。
# 字符串需要以w读写。你在学习open()函数时接触过它。
file = open('book.html','w')
# res.text是字符串格式,把它写入文件内。
file.write(res.text)
# 关闭文件
file.close()
今天这一关,如果用一句话来概括我们要学习的内容,那就是“品尝”一道美味的“浓汤” —— BeautifulSoup模块。
BeautifulSoup到底在爬虫中发挥着怎样的作用,能让我们单独拿出一个课程来学?一起来看看。
BeautifulSoup是什么
我们得先来回忆一下爬虫的四个步骤:
第0关的requests库帮我们搞定了爬虫第0步——获取数据;第1关的HTML知识,是进行爬虫必不可少的背景知识,能辅助我们解析和提取数据。
接下来,解析和提取的部分就交给灵活又方便的网页解析库BeautifulSoup。
那么,本关学习目标:学会使用BeautifulSoup解析和提取网页中的数据。
【解析数据】是什么意思呢?
我们平时使用浏览器上网,浏览器会把服务器返回来的HTML源代码翻译为我们能看懂的样子,之后我们才能在网页上做各种操作。
而在爬虫中,也要使用能读懂html的工具,才能提取到想要的数据。
这就是解析数据。
【提取数据】是指把我们需要的数据从众多数据中挑选出来。
我还想提醒一下:解析与提取数据在爬虫中,既是一个重点,也是难点。因为这一关要讲两步,信息量会比之前两关大,所以希望你在学习的时候,能做好一定的心理准备,投入更多精力。
不过,我对你有信心。O(∩_∩)O
那么接下来,我们就来正式学习BeautifulSoup是如何解析和提取数据的吧~
BeautifulSoup怎么用
BeautifulSoup库目前已经进阶到第4版(Beautiful Soup 4),由于它不是Python标准库,而是第三方库,需要单独安装它,不过,我们的学习系统已经安装好了。
如果你是在自己的电脑上运行,需要在终端输入一行代码运行:pip install BeautifulSoup4。(Mac电脑需要输入pip3 install BeautifulSoup4)
安装好之后,就可以使用了。
解析数据
BeautifulSoup解析数据的用法很简单,请看下图:
在括号中,要输入两个参数,第1个参数是要被解析的文本,注意了,它必须必须必须是字符串。
括号中的第2个参数用来标识解析器,我们要用的是一个Python内置库:html.parser。(它不是唯一的解析器,却是简单的那个)
我们看看具体的用法。仍然以网站这个书苑不太冷为例(url:https://localprod.pandateacher.com/python-manuscript/crawler-html/spider-men5.0.html),假设我们想爬取网页中的书籍类型、书名、链接、和书籍介绍。
根据之前所学的requests.get(),我们可以先获取到一个Response对象,并确认自己获取成功:
# 调用requests库
import requests
# 获取网页源代码,得到的res是response对象
res = requests.get('https://localprod.pandateacher.com/python-manuscript/crawler-html/spider-men5.0.html')
# 检查请求是否正确响应
print(res.status_code)
# 把res的内容以字符串的形式返回
html = res.text
# 打印html
print(html)
上面的代码是之前学过的内容,好,接下来就轮到BeautifulSoup登场解析数据了,请特别留意第3行和第6行新增的代码。
import requests
# 引入BS库,下面的bs4就是beautifulsoup4
from bs4 import BeautifulSoup
res = requests.get('https://localprod.pandateacher.com/python-manuscript/crawler-html/spider-men5.0.html')
# 把网页解析为BeautifulSoup对象
soup = BeautifulSoup(res.text,'html.parser')
第3行是引入BeautifulSoup库。
第6行中的第0个参数,必须是字符串类型;括号中的第1个参数是解析器。
这就是解析数据的用法。
接下来,我们来打印看看soup的数据类型,和soup本身(第5行开始为新增代码)。
import requests
from bs4 import BeautifulSoup
res = requests.get('https://localprod.pandateacher.com/python-manuscript/crawler-html/spider-men5.0.html')
soup = BeautifulSoup( res.text,'html.parser')
# 查看soup的类型
print(type(soup))
# 打印soup
print(soup)
运行结果:
import requests
from bs4 import BeautifulSoup
res = requests.get('https://localprod.pandateacher.com/python-manuscript/crawler-html/spider-men5.0.html')
soup = BeautifulSoup( res.text,'html.parser')
# 查看soup的类型
print(type(soup))
# 打印soup
print(soup)
看看运行结果,soup的数据类型是<class ‘bs4.BeautifulSoup’>,说明soup是一个BeautifulSoup对象。
下一行开始,就是我们打印的soup,它是我们所请求网页的完整HTML源代码。我们所要提取的书名、链接、书籍内容这些数据都在这里面。
可是疑点来了:如果有非常细心的同学,也许会发现,打印soup出来的源代码和我们之前使用response.text打印出来的源代码是完全一样的。
也就是说,我们好不容易用BeautifulSoup写了一些代码来解析数据,但解析出的结果,竟然和没解析之前一样。
你听我解释,事情是这样的:虽然response.text和soup打印出的内容表面上看长得一模一样,却有着不同的内心,它们属于不同的类:<class ‘str’> 与<class ‘bs4.BeautifulSoup’>。前者是字符串,后者是已经被解析过的BeautifulSoup对象。之所以打印出来的是一样的文本,是因为BeautifulSoup对象在直接打印它的时候会调用该对象内的str方法,所以直接打印 bs 对象显示字符串是str的返回结果。
我们之后还会用BeautifulSoup库来提取数据,如果这不是一个BeautifulSoup对象,我们是没法调用相关的属性和方法的,所以,我们刚才写的代码是非常有用的,并不是重复劳动。
到这里,你就学会了使用BeautifulSoup去解析数据:
from bs4 import BeautifulSoup
soup = BeautifulSoup(字符串,'html.parser')
完成了爬虫的第1步:解析数据,下面就是爬虫的第2步:提取数据。
提取数据
我们仍然使用BeautifulSoup来提取数据。
这一步,又可以分为两部分知识:find()与find_all(),以及Tag对象(标签对象)。
先看find()与find_all()。
find()与find_all()是BeautifulSoup对象的两个方法,它们可以匹配html的标签和属性,把BeautifulSoup对象里符合要求的数据都提取出来。
它俩的用法是一样的,区别在于它们工作量。
find()只提取首个满足要求的数据。find()方法将代码从上往下找,找到符合条件的第一个数据,不管后面还有没有满足条件的其他数据,停止寻找,立即返回。
而find_all()顾名思义(find all:查找全部),提取出的是所有满足要求的数据。代码从上往下找,一直到代码的最后,把所有符合条件的数据揣好,一起打包返回。
看两个例子你就清楚了。以这个网页为例(URL: https://localprod.pandateacher.com/python-manuscript/crawler-html/spder-men0.0.html):
在网页的HTML代码中,有三个div元素(
),用find()可以提取出首个元素(只有一个),而find_all()可以全部取出(三个)。看代码(第7行为新增代码),然后尝试运行,查看结果:
import requests
from bs4 import BeautifulSoup
url = 'https://localprod.pandateacher.com/python-manuscript/crawler-html/spder-men0.0.html'
res = requests.get (url)
print(res.status_code)
soup = BeautifulSoup(res.text,'html.parser')
# 使用find()方法提取首个<div>元素,并放到变量item里。
item = soup.find('div')
# 打印item的数据类型
print(type(item))
# 打印item
print(item)
运行结果:
200
<class 'bs4.element.Tag'>
<div>大家好,我是一个块</div>
看,运行结果正是首个div元素吧!我们还打印了它的数据类型:<class ‘bs4.element.Tag’>,说明这是一个Tag类标签对象。
再来试试find_all()吧,它可以提取出网页中的全部div元素(3个),请看代码(第7行为新增代码),然后点击运行。
import requests
from bs4 import BeautifulSoup
url = 'https://localprod.pandateacher.com/python-manuscript/crawler-html/spder-men0.0.html'
res = requests.get (url)
print(res.status_code)
soup = BeautifulSoup(res.text,'html.parser')
# 用find_all()把所有符合要求的数据提取出来,并放在变量items里
items = soup.find_all('div')
# 打印items的数据类型
print(type(items))
# 打印items
print(items)
运行结果:
200
<class 'bs4.element.ResultSet'>
[<div>大家好,我是一个块</div>, <div>我也是一个块</div>, <div>我还是一个块</div>]
运行结果是那三个div元素,它们一起组成了一个列表结构。打印items的类型,显示的是<class ‘bs4.element.ResultSet’>,是一个ResultSet类的对象。其实是Tag对象以列表结构储存了起来,可以把它当做列表来处理。
下面,我想强调一下它们用法中的两个要点:
首先,请看举例中括号里的class_,这里有一个下划线,是为了和python语法中的类 class区分,避免程序冲突。当然,除了用class属性去匹配,还可以使用其它属性,比如style属性等。
其次,括号中的参数:标签和属性可以任选其一,也可以两个一起使用,这取决于我们要在网页中提取的内容。
如果只用其中一个参数就可以准确定位的话,就只用一个参数检索。如果需要标签和属性同时满足的情况下才能准确定位到我们想找的内容,那就两个参数一起使用。
再次总结一下find()与find_all()的用法:
这么多的内容,不太可能一下就记住,要想熟练使用,还需要大量练习。那么现在我们就来做个小练习吧,仍然以网站这个书苑不太冷为例:
(url:https://localprod.pandateacher.com/python-manuscript/crawler-html/spider-men5.0.html),目标是爬取网页中的三本书的书名、链接、和书籍介绍。
打开网址,在网页上点击右键-检查,查看源代码,先看一看目标数据所对应的位置。
滑动一下网页,看见我们想要的每一本书的数据,分别存在了三个div元素中,并且有相同的属性:class=“books”,这个共同点就是我们去提取数据的关键。
我们可以先把这三个div元素提取出来,然后再进一步提取那些具体的书的类型、书名等等。
由于我们要找的不是一本书的数据,而是所有书的数据都要找,所以这时应该用find_all()。
接下来要考虑的就是,要用什么参数去查找和定位,标签,还是属性。此时,可以用到开发者工具的搜索功能,点击Ctrl+F,Mac电脑用command+F。
在搜索栏中输入div试试,搜索结果是:
一共找到了8个div元素,但我们只想找到3个,如果只用
有!还记得我们上节课提到的class元素吗,不同元素之间复用同一套样式,只需要给标签设置同一个class值就好了。而这三个设计书籍信息的div样式很显然是一样的,class值都为books。
我们用属性class="books"搜索看看,果然,整个HTML源代码中,只有我们要找的三个元素的属性满足,因此,我们这次就可以只使用这个属性来提取。
(注:点击右键-显示网页源代码,在这个页面里去搜索会更加准确,在这里我们是点击右键-检查,在这个页面里去搜索的)
现在,来看看代码怎么写,再点击运行:
# 调用requests库
import requests
# 调用BeautifulSoup库
from bs4 import BeautifulSoup
# 返回一个Response对象,赋值给res
res = requests.get('https://localprod.pandateacher.com/python-manuscript/crawler-html/spider-men5.0.html')
# 把Response对象的内容以字符串的形式返回
html = res.text
# 把网页解析为BeautifulSoup对象
soup = BeautifulSoup( html,'html.parser')
# 通过匹配标签和属性提取我们想要的数据
items = soup.find_all(class_='books')
# 打印items
print(items)
# 打印items的数据类型
print(type(items))
运行结果:
[<div class="books">
<h2><a name="type1">科幻小说</a></h2>
<a class="title" href="https://book.douban.com/subject/27077140/">《奇点遗民》</a>
<p class="info">本书精选收录了刘宇昆的科幻佳作共22篇。《奇点遗民》融入了科幻艺术吸引人的几大元素:数字化生命、影像化记忆、人工智能、外星访客……刘宇昆的独特之处在于,他写的不是科幻探险或英雄奇幻,而是数据时代里每个人的生活和情感变化。透过这本书,我们看到的不仅是未来还有当下。</p>
<img class="img" src="./spider-men5.0_files/s29492583.jpg"/>
<br>
<br>
<hr size="1"/>
</br></br></div>, <div class="books">
<h2><a name="type2">人文读物</a></h2>
<a class="title" href="https://book.douban.com/subject/26943161/">《未来简史》</a>
<p class="info">未来,人类将面临着三大问题:生物本身就是算法,生命是不断处理数据的过程;意识与智能的分离;拥有大数据积累的外部环境将比我们自己更了解自己。如何看待这三大问题,以及如何采取应对措施,将直接影响着人类未来的发展。</p>
<img class="img" src="./spider-men5.0_files/s29287103.jpg"/>
<br>
<br/>
<hr size="1"/>
</br></div>, <div class="books">
<h2><a name="type3">技术参考</a></h2>
<a class="title" href="https://book.douban.com/subject/25779298/">《利用Python进行数据分析》</a>
<p class="info">本书含有大量的实践案例,你将学会如何利用各种Python库(包括NumPy、pandas、matplotlib以及IPython等)高效地解决各式各样的数据分析问题。由于作者Wes McKinney是pandas库的主要作者,所以本书也可以作为利用Python实现数据密集型应用的科学计算实践指南。本书适合刚刚接触Python的分析人员以及刚刚接触科学计算的Python程序员。</p>
<img class="img" src="./spider-men5.0_files/s27275372.jpg"/>
<br/>
<br/>
<hr size="1"/>
</div>]
<class 'bs4.element.ResultSet'>
现在,三本书的全部信息都被我们提取出来了。它的数据类型是<class ‘bs4.element.ResultSet’>, 前面说过可以把它当做列表list来看待。
不过,列表并不是我们最终想要的东西,我们想要的是列表中的值,所以要想办法提取出列表中的每一个值。
用for循环遍历列表,就可以把这三个div元素取出来了。
请仔细阅读代码,然后点运行看看:
# 调用requests库
import requests
# 调用BeautifulSoup库
from bs4 import BeautifulSoup
# 返回一个Response对象,赋值给res
res = requests.get('https://localprod.pandateacher.com/python-manuscript/crawler-html/spider-men5.0.html')
# 把Response对象的内容以字符串的形式返回
html= res.text
# 把网页解析为BeautifulSoup对象
soup = BeautifulSoup( html,'html.parser')
# 通过定位标签和属性提取我们想要的数据
items = soup.find_all(class_='books')
for item in items:# 打印itemprint('想找的数据都包含在这里了:\n',item)
运行结果:
想找的数据都包含在这里了:<div class="books">
<h2><a name="type1">科幻小说</a></h2>
<a class="title" href="https://book.douban.com/subject/27077140/">《奇点遗民》</a>
<p class="info">本书精选收录了刘宇昆的科幻佳作共22篇。《奇点遗民》融入了科幻艺术吸引人的几大元素:数字化生命、影像化记忆、人工智能、外星访客……刘宇昆的独特之处在于,他写的不是科幻探险或英雄奇幻,而是数据时代里每个人的生活和情感变化。透过这本书,我们看到的不仅是未来还有当下。</p>
<img class="img" src="./spider-men5.0_files/s29492583.jpg"/>
<br>
<br>
<hr size="1"/>
</br></br></div>
想找的数据都包含在这里了:<div class="books">
<h2><a name="type2">人文读物</a></h2>
<a class="title" href="https://book.douban.com/subject/26943161/">《未来简史》</a>
<p class="info">未来,人类将面临着三大问题:生物本身就是算法,生命是不断处理数据ç过程;意识与智能的分离;拥有大数据积累的外部环境将比我们自己更了解自己。如何看待这三大问题,以及如何采取应对措施,将直接影响着人类未来的发展。</p>
<img class="img" src="./spider-men5.0_files/s29287103.jpg"/>
<br>
<br/>
<hr size="1"/>
</br></div>
想找的数据都包含在这里了:<div class="books">
<h2><a name="type3">技术参考</a></h2>
<a class="title" href="https://book.douban.com/subject/25779298/">《利用Python进行数据分析》</a>
<p class="info">本书含有大量的实践案例,你将学会如何利用各种Python库(包括NumPy、pandas、matplotlib以及IPython等)高效地解决各式各样的数据分析问题。由于作者Wes McKinney是pandas库的主要作者,所以本书也可以作为利用Python实现数据密集型应用的科学计算实践指南。本书适合刚刚接触Python的分析人员以及刚刚接触科学计算的Python程序员。</p>
<img class="img" src="./spider-men5.0_files/s27275372.jpg"/>
<br/>
<br/>
<hr size="1"/>
</div>
程序运行很顺利,结果正是那三个div元素。
其实到这里,find()和find_all()的用法讲了,练习也做了,但是,我们现在打印出来的东西还不是目标数据,里面含着HTML标签,所以下面,我们要进入到提取数据中的另一个知识点——Tag对象。
咱们还以上面的代码为例,我们现在拿到的是一个个包含html标签的数据,还没达成目标。
这个时候,我们一般会选择用type()函数查看一下数据类型,因为Python是一门面向对象编程的语言,只有知道是什么对象,才能调用相关的对象属性和方法。
好,来打印一下:
# 调用requests库
import requests
# 调用BeautifulSoup库
from bs4 import BeautifulSoup
# 返回一个response对象,赋值给res
res = requests.get('https://localprod.pandateacher.com/python-manuscript/crawler-html/spider-men5.0.html')
# 把res的内容以字符串的形式返回
html = res.text
# 把网页解析为BeautifulSoup对象
soup = BeautifulSoup( html,'html.parser')
# 通过定位标签和属性提取我们想要的数据
items = soup.find_all(class_='books')
for item in items:# 打印itemprint('想找的数据都包含在这里了:\n',item) print(type(item))
运行结果:
想找的数据都包含在这里了:<div class="books">
<h2><a name="type1">科幻小说</a></h2>
<a class="title" href="https://book.douban.com/subject/27077140/">《奇点遗民》</a>
<p class="info">本书精选收录了刘宇昆的科幻佳作共22篇。《奇点遗民》融入了科幻艺术吸引人的几大元素:数字化生命、影像化记忆、人工智能、外星访客……刘宇昆的独特之处在于,他写的不是科幻探险或英雄奇幻,而是数据时代里每个人的生活和情感变化。透过这本书,我们看到的不仅是未来还有当下。</p>
<img class="img" src="./spider-men5.0_files/s29492583.jpg"/>
<br>
<br>
<hr size="1"/>
</br></br></div>
<class 'bs4.element.Tag'>
想找的数据都包含在这里了:<div class="books">
<h2><a name="type2">人文读物</a></h2>
<a class="title" href="https://book.douban.com/subject/26943161/">《未来简史》</a>
<p class="info">未来,人类将面临着三大问题:生物本身就是算法,ç是不断处理数据的过程;意识与智能的分离;拥有大数据积累的外部环境将比我们自己更了解自己。如何看待这三大问题,以及如何采取应对措施,将直接影响着人类未来的发展。</p>
<img class="img" src="./spider-men5.0_files/s29287103.jpg"/>
<br>
<br/>
<hr size="1"/>
</br></div>
<class 'bs4.element.Tag'>
想找的数据都包含在这里了:<div class="books">
<h2><a name="type3">技术参考</a></h2>
<a class="title" href="https://book.douban.com/subject/25779298/">《利用Python进行数据分析》</a>
<p class="info">本书含有大量的实践案例,你将学会如何利用各种Python库(包括NumPy、pandas、matplotlib以及IPython等)高效地解决各式各样的数据分析问题。由于作者Wes McKinney是pandas库的主要作者,所以本书也可以作为利用Python实现数据密集型应用的科学计算实践指南。本书适合刚刚接触Python的分析人员以及刚刚接触科学计算的Python程序员。</p>
<img class="img" src="./spider-men5.0_files/s27275372.jpg"/>
<br/>
<br/>
<hr size="1"/>
</div>
<class 'bs4.element.Tag'>
我们看到它们的数据类型是<class ‘bs4.element.Tag’>,是Tag对象,不知道你是否还记得,这与find()提取出的数据类型是一样的。
好,既然知道了是Tag对象,下一步,就是看看Tag类对象的常用属性和方法了。
上图是Tag对象的3种用法,咱们一个一个来讲。
首先,Tag对象可以使用find()与find_all()来继续检索。
回到我们刚刚写的代码:即爬取这个书苑不太冷网站中每本书的类型、链接、标题和简介,我们刚刚拿到的分别是三本书的内容,即三个Tag对象。现在,先把首个Tag对象展示在下面,方便我们阅读:
<div class="books"><h2><a name="type1">科幻小说</a></h2><a href="https://book.douban.com/subject/27077140/" class="title">《奇点遗民》</a><p class="info">本书精选收录了刘宇昆的科幻佳作共22篇。《奇点遗民》融入了科幻艺术吸引人的几大元素:数字化生命、影像化记忆、人工智能、外星访客……刘宇昆的独特之处在于,他写的不是科幻探险或英雄奇幻,而是数据时代里每个人的生活和情感变化。透过这本书,我们看到的不仅是未来还有当下。</p> <img class="img" src="./spider-men5.0_files/s29492583.jpg"><br><br><hr size="1">
</div>
看第2行:书籍的类型在这里面;第3行:我们要取的链接和书名在里面;第4行:书籍的简介在里面。因为是只取首个数据,这次用find()就好。
先阅读下面的代码(从11行开始为新增代码):
# 调用requests库
import requests
# 调用BeautifulSoup库
from bs4 import BeautifulSoup
# 返回一个response对象,赋值给res
res = requests.get('https://localprod.pandateacher.com/python-manuscript/crawler-html/spider-men5.0.html')
# 把res的内容以字符串的形式返回
html = res.text
# 把网页解析为BeautifulSoup对象
soup = BeautifulSoup( html,'html.parser')
# 通过定位标签和属性提取我们想要的数据
items = soup.find_all(class_='books')
for item in items:# 在列表中的每个元素里,匹配标签<h2>提取出数据kind = item.find('h2') # 在列表中的每个元素里,匹配属性class_='title'提取出数据title = item.find(class_='title')# 在列表中的每个元素里,匹配属性class_='info'提取出数据 brief = item.find(class_='info') # 打印提取出的数据print(kind,'\n',title,'\n',brief) # 打印提取出的数据类型print(type(kind),type(title),type(brief))
接下来,请你抄写上面的代码,然后点击运行,练习一下。
运行结果:
<h2><a name="type1">科幻小说</a></h2> <a class="title" href="https://book.douban.com/subject/27077140/">《奇点遗民》</a> <p class="info">本书精选收录了刘宇昆的科幻佳作共22篇。《奇点遗民》融入了科幻艺术吸引人的几大元素:数字化生命、影像化记忆、人工智能、外星访客……刘宇昆的独特之处在于,他写的不是科幻探险或英雄奇幻,而是数据时代里每个人的生活和情感变化。透过这本书,我们看到的不仅是未来还有当下。</p>
<class 'bs4.element.Tag'> <class 'bs4.element.Tag'> <class 'bs4.element.Tag'>
<h2><a name="type2">人文读物</a></h2> <a class="title" href="https://book.douban.com/subject/26943161/">《未来简史》</a> <p class="info">未来,人类将面临着三大问题:生物本身就是算法,生命是不断处理数据的过程;意识与智能的分离;拥有大数据积累的外部环境将比我们自己更了解自己。如何看待这三大问题,以及å¦何采取应对措施,将直接影响着人类未来的发展。</p>
<class 'bs4.element.Tag'> <class 'bs4.element.Tag'> <class 'bs4.element.Tag'>
<h2><a name="type3">技术参考</a></h2> <a class="title" href="https://book.douban.com/subject/25779298/">《利用Python进行数据分析》</a> <p class="info">本书含有大量的实践案例,你将学会如何利用各种Python库(包括NumPy、pandas、matplotlib以及IPython等)高效地解决各式各样的数据分析问题。由于作者Wes McKinney是pandas库的主要作者,所以本书也可以作为利用Python实现数据密集型应用的科学计算实践指南。本书适合刚刚接触Python的分析人员以及刚刚接触科学计算的Python程序员。</p>
<class 'bs4.element.Tag'> <class 'bs4.element.Tag'> <class 'bs4.element.Tag'>
除了我们拿到的数据之外;运行结果的数据类型,又是三个<class ‘bs4.element.Tag’>,用find()提取出来的数据类型和刚才一样,还是Tag对象。接下来要做的,就是把Tag对象中的文本内容提出来。
这时,可以用到Tag对象的另外两种属性——Tag.text(获得标签中的值),和Tag[‘属性名’](获得属性值)。
我们用Tag.text提出Tag对象中的文字,用Tag[‘href’]提取出URL。
只需要修改最后一行代码,我们想要的数据就都能成功提取出来了:
# 调用requests库
import requests
# 调用BeautifulSoup库
from bs4 import BeautifulSoup
# 返回一个response对象,赋值给res
res =requests.get('https://localprod.pandateacher.com/python-manuscript/crawler-html/spider-men5.0.html')
# 把res解析为字符串
html=res.text
# 把网页解析为BeautifulSoup对象
soup = BeautifulSoup( html,'html.parser')
# 通过匹配属性class='books'提取出我们想要的元素
items = soup.find_all(class_='books')
# 遍历列表items
for item in items: # 在列表中的每个元素里,匹配标签<h2>提取出数据 kind = item.find('h2') # 在列表中的每个元素里,匹配属性class_='title'提取出数据 title = item.find(class_='title') # 在列表中的每个元素里,匹配属性class_='info'提取出数据 brief = item.find(class_='info') # 打印书籍的类型、名字、链接和简介的文字print(kind.text,'\n',title.text,'\n',title['href'],'\n',brief.text)
看看终端,拿出来啦(≧▽≦)/此处应该有掌声,到这里,我们终于成功解析、提取到了所有的数据。
运行结果:
科幻小说 《奇点遗民》 https://book.douban.com/subject/27077140/ 本书精选收录了刘宇昆的科幻佳作共22篇。《奇点遗民》融入了科幻艺术吸引人的几大元素:数字化生命、影像化记忆、人工智能、外星访客……刘宇昆的独特之处在于,他写的不是科幻探险或英雄奇幻,而是数据时代里每个人的生活和情感变化。透过这本书,我们看到的不仅是未来还有当下。
人文读物 《未来简史》 https://book.douban.com/subject/26943161/ 未来,人类将面临着三大问题:生物本身就是算法,生命是不断处理数据的过程;意识与智能的分离;拥有大数据积累的外部环境将比我们自己更了解自己。如何看待这三大问题,以及如何采取应对措施,将直接影响着人类未来的发展。
技术参考 《利用Python进行数据分析》 https://book.douban.com/subject/25779298/ 本书含有大量的实践案例,你将学会如ä½利用各种Python库(包括NumPy、pandas、matplotlib以及IPython等)高效地解决各式各样的数据分析问题。由于作者Wes McKinney是pandas库的主要作者,所以本书也可以作为利用Python实现数据密集型应用的科学计算实践指南。本书适合刚刚接触Python的分析人员以及刚刚接触科学计算的Python程序员。
这个层层检索的过程有点像是在超市买你想要的零食,比如一包糖果和一包薯片,首先要定位到超市的零食区,然后去糖果区找糖果,再去薯片区找薯片。
不过呢,每个网页都有自己的结构,我们写爬虫程序,还是得坚持从实际出发,具体问题具体分析哈。
我为你准备了一些习题,记得要去完成它们,你与爬虫大神的距离,还要靠一个一个练习去缩短。
走到这里,你已经学完了如何用BeautifulSoup库的相关知识来解析和提取数据。面对这扑面而来的新的知识,我们有必要来梳理一下:
对象的变化过程
其实说白了,从最开始用requests库获取数据,到用BeautifulSoup库来解析数据,再继续用BeautifulSoup库提取数据,不断经历的是我们操作对象的类型转换。
请看下图:
上一关,我们的操作对象从URL链接到了Response对象。而这一关,我们的操作对象是这样的:Response对象——字符串——BS对象。到这里,又产生了两条分岔:一条是BS对象——Tag对象;另一条是BS对象——列表——Tag对象。
而操作对象的转变,则是借由一些步骤完成的,在图中是由阿拉伯数字标注的内容:从Response对象到字符串,是通过response.text完成的,我就不赘述了,图上标示得很清楚。
在此刻,我尤其想要强调的是,学到现在的你炒鸡棒的,b( ̄▽ ̄)d,而你记不全这些内容太太太正常了,因为编程从来都是一门强调实操实练的学科。
好,现在想请屏幕前的你深吸一口气,在椅子上一定坐稳了,千万不要晕倒,因为我对你隐瞒了一件事。
其实刚刚那个图还不完整,完整版的图示是这样的:
Python是一门面向对象编程的过程,图中用英文字母的序号来展示的是每一种对象的方法和属性。比如bs对象的方法有find()和find_all()。我也不赘述了。
这个流程其实对应的是爬虫四步的前3步:
这张图还挺重要的,可以作为你做练习、复习的一个关键参考信息。❀
不过梳理完之后,我们还是得来敲敲代码,光看不练可不行。所以,学完知识之后不只要去写作业,最好把本关的的代码全部再写一次,因为学习可是需要我们付出努力的噢。
总结
又到了一个关卡快要结束的时刻了。快速复习一下:
我们今天学习了用bs库解析数据和提取数据。
解析数据的方法是用BeautifulSoup()。
提取数据的方法是用find()与find_all()。
这一关中,除了学这些零碎的知识,最重要的是,我们要把所学的知识串成一条线:
这就是本关的全部内容了。
最后,我还想多说几句。在BeautifulSoup中,不止find()和find_all(),还有select()也可以达到相同目的。
其实,在bs的官方文档中,find()与find_all()的方法,其实不止标签和属性两种,还有这些:
不过,我们所教的这两种方法,足以胜任你的95%以上的html解析提取问题,以及风变编程中所有html解析与提取的问题。
为什么我不把所有知识都讲给你,因为,学BeautifulSoup就可能需要好多个关卡了,我们的目的只是带领你走一条快速入门的路。
学无止境,当这些知识都被你掌握,而且练习了更多的项目之后,就有余力去自学和拓展更多的知识了。
即便我只是挑了重点之中的重点为你讲解解析数据的方法,这一关的知识量还是有些大,在学完这个关卡之后,你必须再回过头复习一遍,这对你去理解和记忆这些知识,是相当有帮助的。
通过这一关的学习,你就搞明白了用bs库解析数据和提取数据的方法,只要数据在html里,你都可以拿到了。
下一关,我们会进行BeautifulSoup库的相关实操,务求咱们把所学的都用好~
相关文章:

【python爬虫】3.爬虫初体验(BeautifulSoup解析)
文章目录 前言BeautifulSoup是什么BeautifulSoup怎么用解析数据提取数据 对象的变化过程总结 前言 上一关,我们学习了HTML基础知识,知道了HTML是一种用来描述网页的语言,又了解了HTML的基本结构。 认识了HTML中的常见标签和常见属性&#x…...

【Three.js + Vue 构建三维地球-Part One】
Three.js Vue 构建三维地球-Part One Vue 初始化部分Vue-cli 安装初始化 Vue 项目调整目录结构 Three.js 简介Three.js 安装与开始使用 实习的第一个任务是完成一个三维地球的首屏搭建,看了很多的案例,也尝试了用 Echarts 3D地球的模型进行构建…...

Power View
界面 切换可视化效果 对于已经上传到透视表的数据,选择power view,形成表格后。...

SQL查询本年每月的数据
--一、以一行数据的形式,显示本年的12月的数据,本示例以2017年为例,根据统计日期字段判断,计算总和,查询语句如下:selectsum(case when datepart(month,统计日期)1 then 支付金额 else 0 end) as 1月, sum…...

C++之struct和union对比介绍
C之struct和union对比介绍 在C中,struct和union都是用来定义自定义数据类型的关键字,但它们的作用略有不同。 首先了解一下它们的基本概念: struct(结构体):struct 是一个用户自定义的数据类型ÿ…...

微服务--SkayWalking(链路追踪:国产开源框架)
SkayWalking:分布式系统的应用程序性能监视工具 作用:分布式追踪、性能指标分析、应用、服务依赖分析; SkayWalking性能剖析: 我操,能够定位到某一个方法会有多慢。。。 通过Tid查看全局所有的日志信息(…...

在Windows 10上部署ChatGLM2-6B:掌握信息时代的智能对话
在Windows 10上部署ChatGLM2-6B:掌握信息时代的智能对话 硬件环境ChatGLM2-6B的量化模型最低GPU配置说明准备工作ChatGLM2-6B安装部署ChatGLM2-6B运行模式解决问题总结 随着当代科技的快速发展,我们进入了一个数字化时代,其中信息以前所未有的…...

LRU和LFU算法的简单实现
LRU #include <iostream> #include <unordered_map> #include <list> struct Node{int key;int value;Node(int key, int value):key(key),value(value){} }; class LruCache{ private:int maxCapacity;// 最大容量std::list<Node>CacheList;// 缓存链…...

OCR多语言识别模型构建资料收集
OCR多语言识别模型构建 构建多语言识别模型方案 合合,百度,腾讯,阿里这四家的不错 调研多家,发现有两种方案,但是大多数厂商都是将多语言放在一个字典里,构建1w~2W的字典,训练一个可识别多种语…...

倍增的经典题目:扩大区间、st表
1. 扩大区间 P4155 [SCOI2015] 国旗计划例题1:P4155 [SCOI2015] 国旗计划 计算能覆盖整个圆圈的最少区间,题目给定的所有区间互相不包含,按区间左端点排序后,区间的右端点也是单增的。 我们首先需要化圆为线,然后贪…...

LeetCode——和为K的子数组(中等)
题目 给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的连续子数组的个数 。 示例 1: 输入:nums [1,1,1], k 2 输出:2示例 2: 输入:nums [1,2,3], k 3 输出:2 题解 …...

Truncation Sampling as Language Model Desmoothing
本文是LLM系列文章,针对《Truncation Sampling as Language Model Desmoothing》的翻译。 截断采样作为语言模型的去平滑性 摘要1 引言2 背景3 截断作为去平滑性4 方法5 实验与结果6 相关工作7 结论8 不足 摘要 来自神经语言模型的长文本样本可能质量较差。截断采…...

docker安装jenkins
运行jenkins docker run -d \--name jenkins \ --hostname jenkins \-u root \-p 29090:8080 \--restart always \-v D:\springcloud\学习\jekins\jenkins\jks_home:/var/jenkins_home \ jenkins/jenkins获取root登录密码 密码在jekins_home/secrets/initalAdminPassword文件…...

学习pytorch8 土堆说卷积操作
土堆说卷积操作 官网debug torch版本只有nn 没有nn.functional代码执行结果 B站小土堆视频学习笔记 官网 https://pytorch.org/docs/stable/nn.html#convolution-layers 常用torch.nn, nn是对nn.functional的封装,使函数更易用。 卷积核从输入图像左上角…...

pytest自动化测试两种执行环境切换的解决方案
目录 一、痛点分析 方法一:Hook方法pytest_addoption注册命令行参数 1、Hook方法注解 2、使用方法 方法二:使用插件pytest-base-url进行命令行传参 一、痛点分析 在实际企业的项目中,自动化测试的代码往往需要在不同的环境中进行切换&am…...

说说TIME_WAIT和CLOSE_WAIT区别
分析&回答 TCP协议规定,对于已经建立的连接,网络双方要进行四次握手才能成功断开连接,如果缺少了其中某个步骤,将会使连接处于假死状态,连接本身占用的资源不会被释放。网络服务器程序要同时管理大量连接…...

Docker的优势
Docker是一种开源的容器化平台,提供了一种将应用程序、库和其它依赖项封装在容器中的方法。以下是Docker的基本概念和优势: 基本概念: 镜像:一个Docker镜像是一个可运行的软件包,包括应用程序、库和其它依赖项。它是D…...

C++——string使用
string的常见构造接口 string() 构造空的srting类对象,空字符串 string(const char* str) 用字符串初始化 string(const string& str)拷贝构造,使用string类初始化string(size_t n, char c) 用n个字符c初始化 string s1; string s2("hello …...

10. selenium API (二)
目录 1. 多层框架/窗口定位 2. 下拉框处理 2.1 前端界面 2.2 代码 3. 针对 alert 弹窗进行操作 3.1 前端界面 3.2 代码 4. 文件提交 4.1 前端界面 4.2 代码 5. 显示等待 6. 操作浏览器滚动条 7. 截图 8. 浏览器关闭 9. 窗口切换 在上篇文章中,我们学…...

[国产MCU]-W801开发实例-用户报文协议(UDP)数据接收和发送
用户报文协议(UDP)数据接收和发送 文章目录 用户报文协议(UDP)数据接收和发送1、UDP简单介绍2、W801的UDP创建逻辑2.1 UDP使用步骤2.2 代码实现1、UDP简单介绍 用户数据报协议 (UDP) 是一种跨互联网使用的通信协议,用于对时间敏感的传输,例如视频播放或 DNS查找。它通过在数…...

JavaScript 生成 16: 9 宽高比
这篇文章只是对 for 循环一个简单应用,没有什么知识含量。 可以跳过这篇文章。 只是我用来保存一下我的代码,保存在本地我嫌碍眼,总想把他删了。 正文部分 公式:其中 width 表示宽度,height 表示高度 16 9 w i d t…...

HTML5之drawImage函数
参数说明: drawImage(image, x, y) //按原图片大小绘制。 drawImage(image, x, y, width, height) //按指定大小绘制。 drawImage(image, sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight) //常用于图片裁剪。 其中:…...

leetcode7.整数反转-Java
题目 给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。 如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。 假设环境不允许存储 64 位整数(有符号或无符号)。 7. 整数反转 - 力扣&a…...

操作系统备考学习 day2 (1.3.2 - 1.6)
操作系统备考学习 day2 计算机系统概述操作系统运行环境中断和异常的概念系统调用 操作系统体系结构操作系统引导虚拟机 计算机系统概述 操作系统运行环境 中断和异常的概念 中断的作用 CPU上会运行两种程序,一种是操作系统内核程序,一种是应用程序。…...

Django-跨域
一、基础概念 cors 跨域资源共享 二、跨域请求-简单请求 满足以下全部条件的请求为 简单请求 1.请求方法如下: GET or HEAR or POS 2.请求头仅包含如下: Accept、Accept-Language、Content-Language、Content-Type 3.ConTent-Type 仅支持如下三种&…...

wireshark抓包体验
目录 1、使用基础 1.1 数据包筛选 1.2 MAC地址筛选 1.3 端口筛选 1.4 协议筛选 1.5 包长度筛选 1.6 http请求筛选 2.数据包搜索 3.数据包还原 2、例题复现 1、使用基础 1.1 数据包筛选 ip.src 源ip地址 同理可以得到筛选目标地址: ip.dst 目的ip地址 1.2 …...

Prometheus+grafana安装配置
Prometheus安装配置 Prometheus下载地址 官方地址:Download | Prometheus 可根据系统版本下载想要的安装包,复制链接地址 wget https://github.com/prometheus/prometheus/releases/download/v2.33.3/prometheus-2.33.3.linux-amd64.tar.gzwg 解压pr…...

长连接和短连接有什么区别?
长连接和短连接是什么? HTTP的长连接和短连接本质上是TCP长连接和短连接。HTTP属于应用层协议,在传输层使用TCP协议,在网络层使用IP协议。 IP协议主要解决网络路由和寻址问题,TCP协议主要解决如何在IP层之上可靠地传递数据包&…...

Qt应用开发(基础篇)——输入对话框 QInputDialog
一、前言 QInputDialog类继承于QDialog,是一个简单方便的对话框,用于从用户获取单个值。 对话框窗口 QDialog QInputDialog输入对话框带有一个文本标签、一个输入框和标准按钮。输入内容可以字符、数字和选项,文本标签用来告诉用户应该要输入…...

C++ struct 笔记(超级详细)
今日碎碎念:我在学C语言时经常用到结构体struct,之后在写C程序时遇到在struct中定义构造函数和成员函数的情况,这在c语言中是从未遇到过的,觉得奇怪,想到之前并没有真正系统学习C里的struct,有必要今天详细…...