Python中BeautifulSoup模块详解
作者:小麦的小兜 发布时间:2023-07-21 21:53:15
前言
BeautifulSoup是主要以解析web网页的Python模块,它会提供一些强大的解释器,以解析网页,然后提供一些函数,从页面中提取所需要的数据,目前是Python爬虫中最常用的模块之一。
安装库
在使用前需要安装库,这里建议安 * s4,也就是第四版本,因为根据官方文档第三版的已经停止更新。同时安装lxml解释器
pip3 install bs4
pip3 install lxml
导入库
from bs4 import BeautifulSoup
解析文档示例
这里以官方文档进行举例,我把常用的函数都举出来,实际开发过程中用到的不多,了解就可以。
# 取自《爱丽丝梦游仙境》的一段
html = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1"><!--Elsie--></a>,
<a href="http://example.com/lacsie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/title" class="sister" id="link3">Tillite</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""
# 解析文档,建立一个BeautifulSoup对象,各种函数都是针对此对象展开,此函数会自动编码为Unicode
soup = BeautifulSoup(html,'lxml')
此函数有两个参数:
1、需要解析的文本,可以使字符串,可以使本地文件
2、解释器,这里有"lxml", "lxml-xml", "html.parser", or "html5lib",4种,可以解析绝大多数网页,常用lxml解析 这里有一个坑,如果网页中没有规定编码格式,解释器就不能编码为Unicode,必须先声明一下编码格式,只需要到网页源码中查找编码格式然后做个声明就可以。一般在网页中查找charset关键字。
# 美化文档,有些网页书写不规范,这个函数会补全标签,使其看起来更规范
print(soup.prettify())
提取数据示例
获取到文本后,接下来需要提取我们所需的数据,这里用到选择器 有三种选择器
标签选择器(tag选择器)
标准选择器
CSS选择器
1、标签选择器(tag选择器)
# 直接用标签获取标题
print("title: ", soup.title)
# 获取标题文本
print(soup.title.text)
# 获取p标签
print(soup.p)
# 获取head标签
print(soup.head)
# 获取a标签
print(soup.a)
输出:
标签中最重要的俩个属性:name、attributes
# 使用.name函数获取标签名
print('标题标签的名字: ', soup.title.name)
# tag的属性用法和字典基本一样,可以用属性名取属性,类似字典的键值对,也可以用.attrs取属性:
print('a标签中属性为"href"的值: ', soup.a["href"])
# 会返回一个字典,需要何种属性可自行提取
print('a标签的所有属性: ',soup.a.attrs)
dict1 = soup.a.attrs
# 属性为class的值
print('属性为class的值: ', dict1['class'])
输出:
这里的子孙父兄节点,我感觉用起来忒不顺手,可能是我学的不太彻底😄,我在这里列出来,大家看看。
# 返回子节点的列表
print("p的子节点: ", soup.p.contents)
# 返回子节点的生成器
print('a的子节点: ', soup.a.children)
# 返回子孙结点的生成器
print("a的子孙结点: ", soup.a.descendants)
# 返回父节点
print("a的父节点: ", soup.a.parent)
# 递归父节点
print("a的递归父节点: ",soup.a.parents)
输出:
上述的标签选择器如果遇到相同的标签名,比如说上述的文档中就有多个a标签,这时就没法选择相同标签的第二个标签,也可能是我没会操作,如果有发现的欢迎评论。
所以需要一个遍历全文的选择器来提取数据: find_all( name , attrs , recursive , text , **kwargs ) # 可根据标签名、属性、内容查找文档,此函数配合正则表达式可匹配出各种特定的数据。。。
# 遍历文档中所有a标签
print("文档中所有a标签: ", soup.find_all('a'))
a_list = soup.find_all('a')
for i, aList in enumerate(a_list):
print(i, aList)
输出:可以提取到文本中所有a标签的内容,再通过遍历就可以得到每一个的内容
根据属性、文本筛选
# 根据属性筛选
print(soup.find_all(attrs={'class': 'sister'}))
# 根据文本筛选
print(soup.find_all(text="The Dormouse's story"))
正则表达式筛选
#使用正则表达式找出文本中带有story字符串的内容
print(soup.find_all(text=re.compile('story')))
还有一个find()方法,用法和findall()类似,不同的是返回的只有一个值,而 findall()返回的是列表。
CSS选择器
目前来说,CSS选择器是最常用的一种,通过标签及属性的层层嵌套可以实现各种特定内容的提取。
# 元素选择器:选择p标签
print('标签为p:', soup.select("p"))
# 类选择器:类前加'.'
print("文本中所有class类的标签: \n", soup.select('.sister'))
# id选择器:id前加'#'
print("id为link2的标签: \n", soup.select('#link2'))
输出:
# 属性选择器:
print("属性为name的标签: \n", soup.select("p[name]"))
print("选择所有属性中有sister的标签: \n", soup.select("*[href]"))
print("选择p标签的后代第三个a标签 \n", soup.select("p>a")[2])
print("选择id=link1后的所有兄弟标签 \n", soup.select("#link1 ~ .sister"))
print('通过属性为 href="http://example.com/title进行查找" \n', soup.select('a[href="http://example.com/title"]'))
print("通过href属性中以http开头的所有标签的查找 \n", soup.select('a[href^="http"]'))
print("通过href属性中以elsie结尾的所有标签的查找 \n", soup.select('a[href$="elsie"]'))
print("通过href属性中包含.com的所有标签的查找 \n", soup.select("a[href*='.com']"))
# 通过标签层层查找,这里的:nth-child(2)代表第二个p标签,a#link2表示a标签的id为link2的标签
print("通过标签层层查找 \n", soup.select("body>p:nth-child(2)>a#link2"))
示例输出:大家可以自行试试
以上的CSS选择器的常用函数已经讲完,通过上面的示例基本上可以拿到web文本中绝大多数数据。下面通过一个小栗子试试水。
实例小项目
需求:爬取某代理网站的免费 * 地址
第一步:请求数据,获取数据文本第二步:通过BeautifulSoup分析数据 提取数据第三步:保存数据到本地文本
url = "https://www.89ip.cn/"
header = {"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36"}
# 请求数据
response = requests.get(url, headers=header)
print(response.status_code)
# 判断是否请求成功
if response.status_code == 200:
# 获取web信息的文本模式
dataText = response.text
# 使用lxml解析器解析文本
soup = BeautifulSoup(dataText, 'lxml')
# 观察网页源码,获取需求数据,这里使用CSS选择器层层嵌套获得最终的ip信息
ipText = soup.select('body div>div>div>div>table>tbody>tr>td:nth-child(1)')
# 遍历列表获取每一个ip地址
for i in range(len(ipText)):
# 获取ip的文本信息,get_text()是获取文本,strip()是去掉两边空格
ip = ipText[i].get_text().strip()
# 保存到本地
file = open("ipText.txt", 'a+')
file.write(ip+"\n")
# 关闭文件
file.close()
运行结果:
来源:https://blog.csdn.net/m0_64816081/article/details/122790170
猜你喜欢
- IE8正式版已经发布了。本篇文章不会非常扯蛋地去进行什么评测,然后给出什么“Chrome运行JavaScript能力是IE8的15倍”、什么
- 工作时常遇到需要在其它地方拷贝样式,比如Firebug之类的,但是复制出来的样式是带有换行和空格的,对于我这种有点洁癖的人来说,经常会一个个
- AlexNet是2012年ImageNet比赛的冠军,虽然过去了很长时间,但是作为深度学习中的经典模型,AlexNet不但有助于我们理解其中
- 这篇文章主要介绍了Python魔法方法 容器部方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋
- 今天有个哥们问我要是JavaScript函数重名了会有什么后果?开始我没有细想,就说可能会出错吧,可是等我实验完了发现页面没有任何脚本错误提
- 如何显示已在数据库编码了的相对应的记录?我做了一个歌曲库,在查询中使用了几个下拉菜单供选择条件用,如歌手的性别、区域、爱好等,由于选项太多,
- 前言Iframe 是一种将网页嵌入到另一个页面的内容中的方法。这是通过使用 HTML 元素、外部网站的 URL 以及窗口在您的网站上的外观参
- 之前一直对于python类的继承机制认知的比较混乱,今天学习记录一下。(1)首先使用直接继承的方式class parent():  
- ajax 同步请求和异步请求的差异分析,需要的朋友可以参考下。代码一:Synchronize = function(url,param) {
- 为 Web页指定 DOCTYPE 会影响浏览器呈现页的方式。Internet Explorer、Mozilla Firefox 和 Oper
- 如下所示:# u [32,30,200]# u_logits [400,32,30]q_j_400 = [] for j in range(
- 我开发过几个采集程序,也研究过很多采集程序代码,所以对采集程序的原理还算是稍微有些了解。先说一下采集原理:采集程序的主要步骤如下: 一、获取
- 目录一、Python字典1.什么是字典2.字典的创建方式2.1 通过其他字典创建2.2 通过关键字参数创建2.3 通过键值对的序列创建2.4
- 任何熟悉SQL和关系数据库的人都遇见过大量的连接类型。最简单的说,连接(join)会把两个表的内容组合到一个虚拟表或者recordset内。
- 相信互联网的从业者都有同一个顾虑,那就是怎样将自己网站的用户牢牢抓住。如果以用户的角度来讲,任何网站其实都是一样的,都是我获取东西、获取服务
- Python SMTP发送邮件SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址
- 本文主要讲如何不依赖TenserFlow等高级API实现一个简单的神经网络来做分类,所有的代码都在下面;在构造的数据(通过程序构造)上做了验
- 开门见山,直接使用 skimage 库为图像添加高斯噪声是很简单的:import skimageorigin = skimage.io.im
- 如何做一个随机密码产生器?<%genPassword = ""RandomizeFor&nbs
- Oracle 数据库启动Oracle shutdown的时候突然断电,导致使用sql/plus启动时无法连接到数据库,具体描述为: conn