6.网络爬虫——BeautifulSoup详讲与实战
Posted 以山河作礼。
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了6.网络爬虫——BeautifulSoup详讲与实战相关的知识,希望对你有一定的参考价值。
网络爬虫——BeautifulSoup详讲与实战
前言: 📝📝此专栏文章是专门针对网络爬虫基础,欢迎免费订阅!
📝📝第一篇文章《1.认识网络爬虫》获得全站热搜第一,python领域热搜第一, 第四篇文章《4.网络爬虫—Post请求(实战演示)》全站热搜第八,欢迎阅读! 🎈🎈欢迎大家一起学习,一起成长!!
💕💕:悲索之人烈焰加身,堕落者不可饶恕。永恒燃烧的羽翼,带我脱离凡间的沉沦。
BeautifulSoup简介:
- Beautiful Soup 简称 BS4(其中 4
表示版本号)BeautifulSoup是一个Python库,用于从html和XML文件中提取数据。它提供了一些简单的方式来遍历文档树和搜索文档树中的特定元素。 - BeautifulSoup可以解析HTML和XML文档,并将其转换为Python对象,使得我们可以使用Python的操作来进行数据提取和处理。它还可以处理不完整或有误的标记,并使得标记更加容易阅读。
- BeautifulSoup是一个流行的Web爬虫工具,被广泛应用于数据抓取、数据清洗和数据分析等领域。
BS4下载安装
由于 Bautiful Soup 是第三方库,因此需要单独下载,下载方式非常简单,执行以下命令即可安装:
pip install bs4
BS4解析对象
BeautifulSoup4(BS4)对象是BeautifulSoup库解析HTML或XML文档并创建的Python对象。它是一个树形结构,其中包含了文档中的节点,例如标签、字符串和注释。BS4对象可以解析HTML和XML文档,并提供了许多方法来完成对节点的查找、筛选和修改的操作。
例如,可以使用
.find()
方法查找包含特定文本的标签,使用.select()
方法根据CSS选择器选择元素,使用.text
属性获取标签的文本内容等等。所有这些方法都是BS4对象中提供的。
创建 BS4 解析对象是万事开头的第一步,这非常地简单,语法格式如下所示:
#导入解析包
from bs4 import BeautifulSoup
#创建beautifulsoup解析对象
soup = BeautifulSoup(html_doc, 'html.parser') # html_doc 表示要解析的文档,而 html.parser 表示解析文档时所用的解析器,此处的解析器也可以是 'lxml' 或者 'html5lib'
#prettify()用于格式化输出html/xml文档
print(soup.prettify())
完整代码:
# 导入解析包
from bs4 import BeautifulSoup
import requests
url = 'https://movie.douban.com/subject/35457272/?from=showing'
headers =
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36'
html = requests.get(url, headers=headers)
# 创建beautifulsoup解析对象
soup = BeautifulSoup(html.text,
'html.parser') # html_doc 表示要解析的文档,而 html.parser 表示解析文档时所用的解析器,此处的解析器也可以是 'lxml' 或者 'html5lib'
# prettify()用于格式化输出html/xml文档
print(soup.prettify())
这段代码使用了Python中的BeautifulSoup库和requests库,对指定网页进行了请求并用BeautifulSoup解析了返回的HTML文档。最后使用prettify()方法格式化输出解析后的文档。
运行结果:
Beautiful Soup 将 HTML 文档转换成一个树形结构,该结构有利于快速地遍历和搜索 HTML 文档。下面使用树状结构来描述一段 HTML 文档:
<html>
<head>
<title>中文</title>
</head>
<body>
<h1>net</h1>
<p>
<b>编程</b>
</p>
</body>
</html>
树状图如下所示:
文档树中的每个节点都是 Python 对象,这些对象大致分为四类:Tag , NavigableString , BeautifulSoup
, Comment 。其中使用最多的是 Tag 和 NavigableString。
- Tag:标签类,HTML 文档中所有的标签都可以看做 Tag 对象。
- NavigableString:字符串类,指的是标签中的文本内容,使用 text、string、strings 来获取文本内容。
- BeautifulSoup:表示一个 HTML 文档的全部内容,您可以把它当作一个人特殊的 Tag 对象。
- Comment:表示 HTML 文档中的注释内容以及特殊字符串,它是一个特殊的 NavigableString 。
Tag节点
标签(Tag)是组成 HTML 文档的基本元素。在 BS4 中,通过标签名和标签属性可以提取出想要的内容。看一组简单的示例
from bs4 import BeautifulSoup
soup = BeautifulSoup('<p class="url"><b>net</b></p>', 'html.parser')
# 获取第一个p标签的html代码
print(soup.p)
# 获取b标签
print(soup.p.b)
# 获取p标签内容,使用NavigableString类中的string、text、get_text()
print(soup.p.text)
# 返回一个字典,里面是多有属性和值
print(soup.p.attrs)
# 查看返回的数据类型
print(type(soup.p))
# 根据属性,获取标签的属性值,返回值为列表 不存在就报错
print(soup.p['class'])
# 获取具体属性 获取最近的第一个属性 不存在就返回None
if soup.title:
print(soup.title.get('class'))
else:
print('title标签不存在')
# 给class属性赋值,此时属性值由列表转换为字符串
soup.p['class'] = ['abc', 'data']
print(soup.p)
遍历节点
Tag 对象提供了许多遍历 tag 节点的属性,比如 contents、children 用来遍历子节点;parent 与 parents 用来遍历父节点;示例如下:
from bs4 import BeautifulSoup
import requests
url = 'https://movie.douban.com/subject/35457272/?from=showing'
headers =
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36'
html = requests.get(url, headers=headers)
soup = BeautifulSoup(html.text, 'html.parser')
# 查找第一个符合条件的标签
print(soup.find('span', class_='year'))
# 查找所有符合条件的标签
for item in soup.find_all('span', class_='rating_num'):
print(item.text)
# 使用CSS选择器查找标签
print(soup.select('#content > h1 > span:nth-child(1)'))
# 遍历所有文本内容
for string in soup.stripped_strings:
print(string)
上述代码中,我们首先使用requests库获取了指定网页的HTML文档,然后使用BeautifulSoup库解析HTML文档,并使用不同的方法遍历了节点,包括:
-
使用find()方法查找第一个符合条件的标签,其中class_参数用于指定class属性的值。
-
使用find_all()方法查找所有符合条件的标签,返回一个列表。
-
使用select()方法使用CSS选择器查找标签,返回一个列表。
-
使用stripped_strings属性遍历所有文本内容,返回一个生成器。需要注意的是,stripped_strings返回的是去除空白字符后的文本内容。
find_all()与find()
find_all()与find()都是BeautifulSoup对象的方法,用于在HTML文档中查找符合条件的标签。
find_all()
find_all():返回所有符合条件的标签,结果是一个列表。如果没有符合条件的标签,则返回空列表。
find_all()是BeautifulSoup对象的方法,用于在HTML文档中查找符合条件的标签。
该方法的语法格式为:soup.find_all(name, attrs, recursive, string, limit,
**kwargs),其中各参数的含义如下:
- name:标签名。可以传入一个标签名的字符串,如’a’、'div’等,也可以传入一个列表,如[‘a’,
‘div’],表示查找多个标签名的标签。如果不指定该参数,则返回所有标签。 - attrs:标签属性。可以传入一个字典,其中键表示属性名,值表示属性值,如‘class’:
‘movie’,表示查找class属性值为’movie’的标签。也可以传入一个字符串,如’class=“movie”',表示查找class属性值为’movie’的标签。默认值为None。 - recursive:是否递归查找。默认值为True,表示递归查找所有子孙节点;如果设置为False,则只查找直接子节点。
- string:文本内容。可以传入一个字符串,表示查找指定文本内容的标签。
- limit:结果数量。可以传入一个整数,表示最多返回的结果数量。默认值为None,表示返回所有结果。
- **kwargs:其他属性。可以传入其他属性,如id、class等,表示查找具有指定属性的标签。
下面是一个示例代码,演示如何使用find_all()方法查找符合条件的标签:
from bs4 import BeautifulSoup
html_doc = """
<html>
<head>
<title>电影列表</title>
</head>
<body>
<h1>电影列表</h1>
<div class="movie">
<h2>黑白迷宫</h2>
<p>导演:张艺谋</p>
<p>主演:李连杰、章子怡</p>
<p>评分:<span class="rating">8.9</span></p>
</div>
<div class="movie">
<h2>西游记之大圣归来</h2>
<p>导演:田晓鹏</p>
<p>主演:张磊、石磊、杨晓婧</p>
<p>评分:<span class="rating">9.2</span></p>
</div>
</body>
</html>
"""
soup = BeautifulSoup(html_doc, 'html.parser')
# 查找所有div标签
div_list = soup.find_all('div')
print(div_list)
# 查找class属性值为"movie"的div标签
movie_list = soup.find_all('div', class_='movie')
print(movie_list)
# 查找评分大于9.0的电影
rating_list = soup.find_all('span', class_='rating', string=lambda x: float(x) > 9.0)
print(rating_list)
# 查找第一个电影的导演名
director = soup.find('div', class_='movie').find('p').next_sibling.string
print(director)
上述代码中,我们首先定义了一个HTML文档字符串,然后使用BeautifulSoup库解析HTML文档,并使用find_all()方法查找了符合条件的标签。
具体来说:
- 使用
find_all('div')
方法查找所有div标签,并将结果存储在div_list列表中。 - 使用
find_all('div',class_='movie')
方法查找所有class属性值为"movie"的div标签,并将结果存储在movie_list列表中。 - 使用
find_all('span', class_='rating', string=lambda x: float(x) > 9.0)
方法查找所有class属性值为"rating"且文本内容大于9.0的span标签,并将结果存储在rating_list列表中。注意这里使用了lambda表达式作为string参数的值,表示只返回文本内容大于9.0的标签。 - 使用
find('div',class_='movie').find('p').next_sibling.string
方法查找第一个class属性值为"movie"的div标签中第一个p标签的下一个兄弟节点的文本内容,即导演名。需要注意的是,next_sibling属性返回下一个兄弟节点,可能是空白字符节点,因此需要使用string属性获取文本内容。
find()
find():返回第一个符合条件的标签,结果是一个Tag对象。如果没有符合条件的标签,则返回None。
find()是BeautifulSoup对象的方法,用于在HTML文档中查找第一个符合条件的标签。
该方法的语法格式为:soup.find(name, attrs, recursive, string,
**kwargs),其中各参数的含义与find_all()方法相同。与find_all()方法不同的是,find()只返回第一个符合条件的标签,并且返回的是一个Tag对象,而不是一个列表。如果没有找到符合条件的标签,则返回None。
下面是一个示例代码,演示如何使用find()方法查找符合条件的标签:
from bs4 import BeautifulSoup
html_doc = """
<html>
<head>
<title>电影列表</title>
</head>
<body>
<h1>电影列表</h1>
<div class="movie">
<h2>黑白迷宫</h2>
<p>导演:张艺谋</p>
<p>主演:李连杰、章子怡</p>
<p>评分:<span class="rating">8.9</span></p>
</div>
<div class="movie">
<h2>西游记之大圣归来</h2>
<p>导演:田晓鹏</p>
<p>主演:张磊、石磊、杨晓婧</p>
<p>评分:<span class="rating">9.2</span></p>
</div>
</body>
</html>
"""
soup = BeautifulSoup(html_doc, 'html.parser')
# 查找第一个div标签
div = soup.find('div')
print(div)
# 查找class属性值为"movie"的第一个div标签
movie = soup.find('div', class_='movie')
print(movie)
# 查找评分大于9.0的第一个电影
rating = soup.find('span', class_='rating', string=lambda x: float(x) > 9.0)
print(rating)
# 查找第一个电影的导演名
director = soup.find('div', class_='movie').find('p').next_sibling.string
print(director)
上述代码中,我们使用find()方法查找了符合条件的标签,并返回了一个Tag对象。
具体来说:
- 使用
find('div')
方法查找第一个div标签,并将结果存储在div变量中。 - 使用
find('div', class_='movie')
方法查找第一个class属性值为"movie"的div标签,并将结果存储在movie变量中。 - 使用
find('span', class_='rating', string=lambda x: float(x) > 9.0)
方法查找class属性值为"rating"且文本内容大于9.0的第一个span标签,并将结果存储在rating变量中。注意这里使用了lambda表达式作为string参数的值,表示只返回文本内容大于9.0的标签。 - 使用
find('div',class_='movie').find('p').next_sibling.string
方法查找第一个class属性值为"movie"的div标签中第一个p标签的下一个兄弟节点的文本内容,即导演名。
豆瓣电影实战
本次实战目的是获取方框内内容,使用学过的bs4来操作
首先点击检查,鼠标附魔,查看数据是否在代码中。
通过附魔后,查看代码,发现数据在代码中,接下来我们通过get请求获取网页全部代码:
import requests
from bs4 import BeautifulSoup
url = 'https://movie.douban.com/subject/35457272/?from=showing'
headers =
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36'
html = requests.get(url, headers=headers)
print(html.text)
接下来使用BS4来解析数据,并把它提取出来,放在txt文件夹里面。
import requests
from bs4 import BeautifulSoup
url = 'https://movie.douban.com/subject/35457272/?from=showing'
headers =
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36'
html = requests.get(url, headers=headers)
print(html.text)
data = BeautifulSoup(html.text, 'lxml') # 第一个参数是要解析的html文本,第二个参数是使用那种解析器
obj = data.find(id="info")
print(obj.get_text())
with open('豆瓣.txt', 'w', encoding='utf-8') as f:
f.write(obj.get_text())
任务完成!!!
🍁 🍁今日学习笔记到此结束,感谢你的阅读,如有疑问或者问题欢迎私信,我会帮忙解决,如果没有回,那我就是在教室上课,抱歉。
🍂🍂🍂🍂
爬虫入门手记03爬虫解析利器beautifulSoup模块的基本应用
【网络爬虫入门03】爬虫解析利器beautifulSoup模块的基本应用
广东职业技术学院 欧浩源 2017-10-20
1、引言
网络爬虫最终的目的就是过滤选取网络信息,因此最重要的就是解析器了,其性能的优劣直接决定这网络爬虫的速度和效率。BeautifulSoup可以通过定位HTML件中的标签来格式化和组织复杂的网络信息,尝试化平淡为神奇,用简单易用的Python对象为我们展现XML的信息结构,它会帮你节省数小时甚至数天的工作时间。
2、什么是BeautifulSoup模块?
BeautifulSoup是一个非常优秀的Python扩展库,它可以从HTML或XML文件中提取我们感兴趣的数据。它不但可以标签进行查找,还可以通过标签属性来查找。 BeautifulSoup除了支持Python标准库中的HTML解析器之外,还支持一些第三方的解析器,可以有针对性地向网页进行解析。 BeautifulSoup官方推荐使用lxml作为解析器,据说因为lxml解析器的效率更高。
学习BeautifulSoup的最完整和最好资料是官方文档,常用的内容熟练掌握,不常用的需要的时候查阅就好。在本文中,只总结爬虫开发中常用知识,更多内容要看官方文档:
http://beautifulsoup.readthedocs.io/zh_CN/latest/#id18
3、对象的种类
BeautifulSoup对象是一个复杂的树形结构,它的每一个节点都是一个Python对象,获取网页内容就是一个提取对象内容的过程,其提取对象的方法可以分为:遍历文档树、搜索文档树、CSS选择器。
所有的对象可以分为4种:
<1> Tag:Tag对象与XML或HTML原生文档中的tag相同。它有很多方法和属性,其中最重要的是:name和attributes。BeautifulSoup对象通过find()和find_all()方法,或者直接调用子标签获取一列对象或单个对象。
<2> NavigableString:用来表示标签里的文字,不是标签。
<3> Comment:这是一个特殊类型的NavigableString对象,用来查找HTML文档中的注释。
<4> BeautifulSoup:这个对象表示文档的全部内容。大部分时候可以把它当作Tag对象,它支持遍历文档树和搜索文档树的大部分方法。
4、官方测试样例
5、遍历文档树
文档树的遍历方法就好像爬树一样,需要首先爬到树干上,然后慢慢爬到小树干,最后到树枝上,就可以得到需要的数据了。
例1:获取文档树中的‘body标签中的‘p’标签中的’‘b’标签。
在遍历文档树中,搞清各个标签之间的关系是非常重要的。子标签就是一个父标签的下一级;而后代标签是指一个父标签下面所有级别的标签。所有子标签都是后代标签,但不是所有的后代标签都是子标签。一般情况下,BeautifulSoup的方法总是处理当前标签的后代标签。
可以通过 .parent 属性来获取某个元素的父节点.
例2:获取文档树中‘p’标签的父标签。
tag的.contents 属性可以将tag的子节点以列表的方式输出;通过tag的.children 生成器,也可以对tag的子节点进行循环。
例3:获取文档树中‘p’标签的子标签。
6、搜索文档树
相对于遍历文档树来说,搜索文档树最常用。在搜索文档树时,最常用的是find_all()和find()方法。在这里,主要通过例子讲述find_all()的常见使用,关于find_all()的具体描述参见官方文档。
find_all (name, attrs, recursive, string, limit, keyword)
该方法搜索当前tag的所有tag子节点,并判断是否符合过滤器的条件。
[1] name参数:可以查找所有名字为name的tag,字符串对象会自动忽略掉。该参数的值可以接受:字符串、正则表达式、列表和True。
例4:搜索文档树中的‘title’标签。
例5:搜索文档树中的‘a’标签,逐条打印出来。
[2] attrs参数:是用一个Python字典封装一个标签的若干属性和对应的属性值。
例6:搜索‘a’标签中,id属性的值为“link2”的标签。
因为表示CSS类名的关键字class在Python中是保留字,所以,在按照CSS类名搜索tag的时候,如果使用class作为参数会导致语法的错误,不过,可以通过class_搜索指定CSS类名的tag,或者通过字典的方式指定参数。
例7:搜索‘a’标签中,class属性的值为“sister1”的标签。
例8:搜索‘a’标签中,class属性的值为“sister1”和属性值为“sister3”的标签。
[3] recursive参数:是一个布尔变量。该参数为True,find_all()就会根据你的要求去查找标签参数的所有子标签,以及子标签的子标签。如果该参数为False,find_all()就只查找文档一级标签。该参数默认是True的,一般情况下不需要修改,除非你真正了解自己需要那些信息,而且抓去的速度非常重要,那么你可以设置该参数。
[4] string参数:通过该参数可以搜索文档中的字符串内容,与name参数相似,其可选值一样,接受:字符串、正则表达式、列表和True,例如:
soup.find_all(string = "Elsie")
soup.find_all(string = ["Elsie", "Tillie", "Lacie"])
soup.find_all(string = re.compile("Dormouse"))
该参数还可以与其他参数混合使用来过滤:
soup.find_all("a", string = "Elsie")
例9:搜索文档树中符合列表中参数的字符串内容。
[5] limit参数:find_all()方法返回的是全部的搜索结果,如果我们不需要全部结果,可以使用limit参数来限制返回结果的数量。当搜索到的结果数量达到limit的限制时,就停止搜索返回结果。find()方法实际上等价于find_all()的limit参数为1的情形。
例10:搜索\'a\'标签并返回一个结果。
[6]keyword参数:如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜索。
通过标签参数name把标签列表传到find_all()里获取一系列标签,其实就是一个“或”关系的过滤器;而关键字参数keyword可以让你增加一个“与”关系的过滤器来简化工作。
如果传入一个名字为id的参数,BeautifulSoup会搜索每一个tag的id属性,如果传入href参数,则会搜索每一个tag的href属性。在搜索指定名字的属性时,可以使用的参数值包括:字符串、正则表达式、列表和True。
例11:在文档树中查找所有包含id属性的tag,无论id属性的值是什么。
例12:查找id属性值为link2的标签。
除了上面的基础应用之外,关于find_all()使用可以相当灵活,需要通过在实践中不断的体会和积累,我们在看几个例子:
例13:使用多个指定名字的参数,同时过滤tag的多个属性。
例14:将‘a’标签中的网络链接抓取出来。
例15:将‘a’标签中的网络链接和字符串抓取出来,形成可视数据。
例16:将class属性值为“story”的‘p’标签的全部子标签的文本抓取出来。
7、小结
对爬取网页的解析工作,除了 BeautifulSoup之外,还可以使用re正则表达式、lxml解析器、xpath等等来实现,熟练掌握一个工具,学习其他的会很容易。BeautifulSoup的用法远不止此,但作为网络爬虫的入门应用,上述知识基本足够。如果在学习过程中观看不练,会感觉非常抽象,无法理解;如果只知道敲代码而忽略了为什么,也只能一知半解,难以灵活应用。
以上是关于6.网络爬虫——BeautifulSoup详讲与实战的主要内容,如果未能解决你的问题,请参考以下文章
Python网络爬虫与信息提取—— BeautifulSoup
爬虫入门手记03爬虫解析利器beautifulSoup模块的基本应用
Python网络爬虫——BeautifulSoup4库的使用