跳转到主内容
思享编程网:思考分享,玩转编程世界!

【RPA开发】Beautiful Soup 使用详解

爬虫时通过 requests.get 方法获得 html 源代码后,通常需要从源代码中提取关键信息,这有多种方式,比如使用正则表达式匹配,也可通过 python 的第三方库 Beautiful Soup 实现定位提取关键信息,类似的库还有 lxml 第三方库中的 etree 模块。

目录 1 快速开始 1.1 Beautiful Soup 介绍 1.2 基础信息提取 ① HTML 代码 ② 基础方法汇总 ③ find 简单使用 1.3 解析器介绍 2 find 使用 2.1 标签/tag名定位 2.2 标签+属性定位 2.3 标签+文本值定位 2.4 正则表达式 2.5 find().find() 3 select 使用 3.1 css基本属性定位 3.2 css其他属性定位 3.3 css标签结合其他属性定位 3.4 css层级定位 3.5 css索引定位 3.6 css模糊匹配 4 实战--猫眼榜单 4.1 使用 requests 请求页面 4.2 分析页面及元素定位 1 快速开始 1.1 Beautiful Soup 介绍 简单来说,Beautiful Soup 是 Python 用于解析 HTML 和 XML 文件的第三方库,可以从 HTML 和 XML 文件中提取数据。

官方网址 : Beautiful Soup Documentation 中文文档 : Beautiful Soup 中文文档 安装 :pip install beautifulsoup4 Beautiful Soup 3 目前已经停止开发,官方支持 Beautiful Soup 4,并且将其移植到 BS4,也就是说我们需要 import bs4,本文 beautifulsoup4 版本 = 4.12.2。

Beautiful Soup提供了多种搜索方式,可以轻松定位所需的元素。

它还可以修复已损坏的HTML和XML文件,使其更易于理解和处理。

1.2 基础信息提取 ① HTML 代码 下面是一段官方提供的 html 代码( 爱丽丝梦游仙境的一段内容 ):

The Dormouse's story

The Dormouse's story

Once upon a time there were three little sisters; and their names were Elsie, Lacie and Tillie;

and they lived at the bottom of a well.

...

页面效果如下, 右键选择“检查” 即可查看其 html 规范格式 👇

该 html 包含了诸多元素,比如标题元素(

The Dormouse's story

),其中 p 为其 tag-标签,class 是其属性,“The Dormouse's story”是其文本,其余元素类似,我们正是通过标签和相关属性对各元素进行定位。

② 基础方法汇总

from bs4 import BeautifulSoup

html_doc = """

The Dormouse's story

The Dormouse's story

Once upon a time there were three little sisters; and their names were Elsie, Lacie and Tillie;

and they lived at the bottom of a well.

...

"""

#默认解析html,若想要解析xml,需要把lxml换为xml soup = BeautifulSoup(html_doc, 'lxml')

print(soup.title) #html的标题元素 # The Dormouse's story

print(soup.title.name) #html的标题元素标签名 # title

print(soup.title.string) #html的标题文本 # The Dormouse's story

print(soup.title.parent.name)#标题元素的父元素的标签名 # head

print(soup.p) #html中标签名为p的第一个元素 #

The Dormouse's story

print(soup.p['class']) #该元素的class属性值 # ['title']

print(soup.a) #html中标签名为a的第一个元素 # Elsie

print(soup.get_text()) #从文档中获取所有文字内容 ③ find 简单使用

print(soup.find_all('a')) #找到所有标签名为a的元素

# [Elsie, # Lacie, # Tillie]

print(soup.find(id="link3")) #找到id属性为link3的元素 # Tillie

for link in soup.find_all('a'): #从文档中找到所有标签的链接 print(link.get('href')) # http://example.com/elsie # http://example.com/lacie # http://example.com/tillie 1.3 解析器介绍 Beautiful Soup 可以使用不同的解析器,例如Python的内置HTML解析器,标准的xml解析器和第三方解析器(如lxml)。

下表列出了主要的解析器,以及它们的优缺点:

官方推荐使用 lxml 作为解析器(pip install lxml),因为效率更高,在 Python2.7.3 之前的版本和 Python3中3.2.2 之前的版本,必须安装 lxml 或 html5lib ,因为那些 Python 版本的标准库中内置的 HTML 解析方法不够稳定。

2 find 使用 为了使用Beautiful Soup解析网页,需要先根据网页的结构找到所需的关键信息。

在此过程中,常用的两个函数是find和find_all,通过它们可以找到并分析网页结构,以获取所需信息。

find_all() 方法将返回文档中符合条件的所有元素,返回结果是值包含一个元素的列表;find() 方法直接返回结果(元素)。

find_all() 方法没有找到目标是返回空列表,find() 方法找不到目标时返回 None。

2.1 标签/tag名定位 比如文档中只有一个 标签,那么使用 find_all() 方法来查找标签就不太合适,使用 find_all 方法并设置 limit=1 参数不如直接使用 find() 方法。

语法: soup.find_all("标签名") soup.find_all("标签名", limit = 数量) soup.find_all(name = "标签名", limit = 数量) soup.find("标签名") soup.find(name = "标签名") 下面两行代码是等价的:

soup.find_all('title', limit=1) # 标签名/tag名为title

# [The Dormouse's story]

soup.find('title') # The Dormouse's story 2.2 标签+属性定位 标签名很容易重复,因此需要搭配属性名来进行准确定位!

下边两行代码作用一致,name 指的就是标签名,千万不要和 name 属性搞混了~ 语法: soup.find_all("标签名", attrs = {'属性':'属性值'}) soup.find("标签名", attrs = {'属性':'属性值'}) 其他属性比如 id、name、href 等等,都可以放到 attrs 的字典里去!

#2标签/tag名定位

soup.find("p",attrs={'class':'title'}) #标签名为p,class属性值为title soup.find(name="p",attrs={'class':'title'}) #

The Dormouse's story

2.3 标签+文本值定位 同上,不过文本值需要用到 string 这个入参,text 目前已被 deprecated,官方推荐 string。

语法: soup.find_all("标签名", string= "文本") soup.find("标签名", string= "文本")

#3标签+文本值定位

soup.find("a",string="Elsie") #Elsie 2.4 正则表达式 find 和 find_all 同样支持正则表达式的查找,如找出标签名中含有 title 或者是 p 的元素。

#4正则表达式

tags = soup.find_all(name =re.compile('title|a')) for i in tags: print(i) print('--------------') 控制台输出:

The Dormouse's story

--------------

The Dormouse's story

--------------

Elsie

--------------

Lacie

--------------

Tillie

-------------- 2.5 find().find() find() 定位到的就是元素,该元素依然可能存在子元素,那么就可以继续使用 find() 来进行定位。

from bs4 import BeautifulSoup

html_doc = """

The Dormouse's story

The Dormouse's story

Once upon a time there were three little sisters; and their names were Elsie, Lacie and Tillie;

and they lived at the bottom of a well.

...

"""

soup = BeautifulSoup(html_doc, 'lxml')

story = soup.find('p',attrs={"class":"story"}) Elsie = story.find('a',attrs={"id":"link1"}) #Elsie 3 select 使用 select 和 select_one 类似于 find 和find_all,都是用来进行元素定位,不过它的选取规则依赖于 css 选择器。

3.1 css基本属性定位 css选择器也支持基本属性(tag、id、class)定位方式。

语法: soup.select("标签名") #css+id定位 soup.select("#id值") #css+class定位 soup.select(".class值") #css+标签定位

#1.css基本属性定位

soup.select("title") #[The Dormouse's story] soup.select("#link1") #[Elsie] soup.select(".title") #[

The Dormouse's story

]
3.2 css其他属性定位 另外一些非基础元素也可以通过以下形式进行辅助定位~ 语法: soup.select('[属性名=属性值]') #css+其他属性 soup.select('[属性名1=属性值1][属性名2=属性值2]') #css+多个其他属性

#2.css其他属性定位

soup.select('[href="http://example.com/elsie"]') #[Elsie] soup.select('[class="sister"][id="link3"]') #[Tillie] 3.3 css标签结合其他属性定位 我们也可以通过标签+属性来进行定位 语法: soup.select('标签名#id值') #标签+id属性定位 soup.select('标签名.class值') #标签+class属性定位 soup.select('标签名[属性名=属性值]') #标签+其他属性定位

#3.css标签结合其他属性定位

soup.select('a#link1') #[Elsie] soup.select('p.title') #[

The Dormouse's story

] soup.select('a[id=link1]') #[Elsie]
3.4 css层级定位 在定位某个元素时,若无简洁标签属性可供参考,我们可以先定位到该元素的上级或上上级元素,随后通过层级关系获取该元素的位置。

语法: soup.select('标签1 > 标签2') #标签2为标签1的子标签 soup.select('标签1 > #id值') #id值为标签1的子标签的id值,class也可

#4.css层级定位

soup.select('head > title') #[The Dormouse's story] soup.select('p > #link1') #[Elsie] 3.5 css索引定位

如图,该元素下存在3个a标签,像这种有多个相同标签名的元素,可以使用索引定位,通过索引来指定具体哪个 a 标签的元素。

注:与python列表索引的概念不同,此处的标签索引是从1开始;python列表的索引是从0开始。

语法: soup.select('标签:nth-child(n)') #正着数第n个标签 soup.select('标签:nth-last-child(n)') #倒着数第n个标签

#5.css索引定位

soup.select('a.sister:nth-child(1)') #a标签,类名为sister #[Elsie] soup.select('a.sister:nth-last-child(2)') #[Lacie] 3.6 css模糊匹配 有时会遇到属性值过长的情况,此时我们可以通过模糊匹配来处理,只需要属性值的部分内容即可。

语法: soup.select("[属性名~='部分属性值']") #1.属性值由多个空格隔开,匹配其中一个值的方法 soup.select("[属性名^='属性值开头']") #2.匹配字符串开头 soup.select("[属性名$='属性值结尾']") #3.匹配字符串结尾

from bs4 import BeautifulSoup

html_doc = """

The Dormouse's story

The Dormouse's story

Once upon a time there were three little sisters; and their names were Elsie, Lacie and Tillie;

and they lived at the bottom of a well.

...

"""

soup = BeautifulSoup(html_doc, 'lxml')

#5.css模糊匹配 print(soup.select("[class~='test']") ) #[Elsie] print(soup.select("[class^='titl']")) #[

The Dormouse's story

] print(soup.select("[id$='ink3']")) #[Tillie]
4 实战--猫眼榜单 那么在项目中如何使用 Beautiful Soup 对爬到的网页进行分析并提前关键的字段,本章内容将进行解答。

4.1 使用 requests 请求页面 本文针对 猫眼电影榜单--热映口碑榜 进行实战,该页面如下:

我们使用 requests 第三方库获取页面内容(html),requests 就不多说了,首先获取实际页面的请求头(使用浏览器的开发者工具):

爬虫代码:

import requests

url = "http://maoyan.com/board/7?offset=0" headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.54', 'Accept': '*/*', 'Host': 'www.maoyan.com', 'Connection': 'keep-alive' }

resp = requests.get(url,headers=headers) 4.2 分析页面及元素定位

右键检查使用开发者工具,可以看到 标签名为dl的元素() dl中包含了10个的dd,每个dd里面包含着每一部电影的各种信息,解析dd就能解析出我们需要的属性,因此我们先定位到该元素。

#使用BeautifulSoup进行分析

maoyan_soup = BeautifulSoup(resp.text, "lxml") wrapper_tag = maoyan_soup.select_one('dl.board-wrapper') dd_tags = board_wrapper_tag.select('dd')

我们需要采集每条电影记录的排名、电影名、主演和上映时间,各信息对应的元素信息如上图所示,本文我使用 css 选择器进行定位,我将他们放在了 dic 里边。

css_items = {

'index': 'i.board-index', 'name': 'p.name a', 'star': 'p.star', 'time': 'p.releasetime' } 完整代码如下:

import requests

from bs4 import BeautifulSoup

url = "http://maoyan.com/board/7?offset={}" headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.54', 'Accept': '*/*', 'Host': 'www.maoyan.com', 'Connection': 'keep-alive', 'Cookie': '__mta=255104311.1682493547126.1682498459882.1682498495101.29; uuid_n_v=v1; uuid=A1063700E40211EDB6A41DA4355E52AD975693BE63D7498981D8E398A28DDC69; _csrf=9550a5fdc0d1595e1cd735b8a493bf15d4a988a78c1c3e57a05ccc904bb1e703; _lx_utm=utm_source=bing&utm_medium=organic; _lxsdk_cuid=187bc6e211ac8-026291e2eaf349-7e57547c-e1000-187bc6e211ac8; _lxsdk=A1063700E40211EDB6A41DA4355E52AD975693BE63D7498981D8E398A28DDC69; Hm_lvt_703e94591e87be68cc8da0da7cbd0be2=1682493547; __mta=255104311.1682493547126.1682493552847.1682493564446.4; Hm_lpvt_703e94591e87be68cc8da0da7cbd0be2=1682498495; _lxsdk_s=187bcb90647-db6-e4a-a90||10' } css_items = { 'index': 'i.board-index', 'name': 'p.name a', 'star': 'p.star', 'time': 'p.releasetime' } data_list = []

resp = requests.get(url.format(0 * 10),headers=headers) maoyan_soup = BeautifulSoup(resp, "lxml")

wrapper_tag = maoyan_soup.select_one('dl.board-wrapper') if wrapper_tag is not None: dd_tags = wrapper_tag.select('dd') index, name, star, time ='', '', '', ''

for dd in dd_tags: index = dd.select_one(css_items.get('index')).text name = dd.select_one(css_items.get('name')).text star = dd.select_one(css_items.get('star')).text.strip() time = dd.select_one(css_items.get('time')).text data = dict(index=index, name=name, star=star, time=time) #json格式 data_list.append(data) print(data_list) 考虑到猫眼会进行反扒,下边也提供了 html 直接供大家进行测试:

热映口碑榜 - 猫眼电影 - 一网打尽好电影

2023-04-26已更新

榜单规则:将昨日国内热映的影片,按照评分从高到低排列取前10名,每天上午10点更新。相关数据来源于“猫眼专业版”及“猫眼电影库”。

1

泰坦尼克号

主演:莱昂纳多·迪卡普里奥,凯特·温丝莱特,比利·赞恩

上映时间:1998-04-03

9.6

2

灌篮高手

主演:宫城良田,三井寿,流川枫

上映时间:2023-04-20

9.4

3

保你平安

主演:大鹏,李雪琴,尹正

上映时间:2023-03-10

9.4

4

忠犬八公

主演:大黄(中华田园犬),冯小刚,陈冲

上映时间:2023-03-31

9.3

5

超级马力欧兄弟大电影

主演:克里斯·帕拉特,安雅·泰勒-乔伊,查理·戴

上映时间:2023-04-05

9.3

6

望道

主演:刘烨,胡军,文咏珊

上映时间:2023-03-24

9.3

7

名侦探柯南:贝克街的亡灵

主演:高山南,山崎和佳奈,神谷明

上映时间:2023-04-04

9.3

8

生无可恋的奥托

主演:汤姆·汉克斯,玛丽安娜·特雷维尼,曼努埃尔·加西亚-鲁尔福

上映时间:2023-03-24

9.3

9

铃芽之旅

主演:原菜乃华,松村北斗,深津绘里

上映时间:2023-03-24

9.2

10

爱很美味

主演:李纯,张含韵,王菊

上映时间:2023-04-15

9.2

相关文章