python-14(BS4解析网页)

2024-05-27 20:52
文章标签 python 网页 解析 14 bs4

本文主要是介绍python-14(BS4解析网页),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

课前案例

Beautiful Soup

什么是Beautiful Soup

解析器

安装与配置

快速入门

解析数据

标签

属性

标签内容

遍历文档树

子节点

父节点

兄弟节点

搜索文档树

find

find_all

css选择器

3.综合案例


课前案例

通过requests模块爬取指定网站中的图片并保存到本地目录中。

import re
import threading
import uuid
from pathlib import Path
import requests# 定义一个函数用于下载图片
def download(url):# 生成一个唯一的文件名,使用uuid4生成的随机UUID加上.jpg后缀filename = str(uuid.uuid4()) + ".jpg"# 打印一条消息,告知用户正在下载图片print(f"正在下载{filename}图片,请稍等。。。")# 创建一个文件路径对象,路径为"imgs\\"加上生成的文件名p = Path("imgs\\" + filename)# 创建一个空文件,如果文件不存在的话p.touch()# 发送GET请求到图片的URL,获取图片内容f = requests.get(url)# 将获取到的图片内容写入到之前创建的文件中p.write_bytes(f.content)# 设置爬取网页地址
resp = requests.get('http://www.deskcity.org/animals/')  # 注意:这里需要提供一个有效的URL
# 设置编码格式
resp.encoding = 'utf-8'
# 使用正则表达式查找resp.text中所有<img>标签的src属性值
rs = re.findall(r'<img src="(.*?)"', resp.text)# 创建一个线程列表用于存储所有下载线程
threads = []# 遍历从HTML中提取的图片URL列表
for url in rs:# 创建一个线程,目标是执行download函数,参数是当前的URLt = threading.Thread(target=download, args=(url,))t.start()  # 启动线程threads.append(t)  # 将线程添加到线程列表中# 等待所有线程结束
for t in threads:t.join()print('结束')

上述案例采用的是同步方式下载图片,效率太低。异步方式如下(线程):

# target为目标函数;args中传入的是download函数的参数url
threading.Thread(target=download,args=(url,)).start()

注意:args为元组格式,如果传入一个参数注意后面必须跟着一个逗号;线程配置完毕之后记得调用start方法启动线程。

Beautiful Soup

什么是Beautiful Soup

Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式.Beautiful Soup会帮你节省数小时甚至数天的工作时间.

解析器

Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器:

解析器使用方法优势劣势
Python标准库BeautifulSoup(markup, "html.parser")Python的内置标准库执行速度适中文档容错能力强Python 2.7.3 or 3.2.2)前 的版本中文档容错能力差
lxml HTML 解析器BeautifulSoup(markup, "lxml")速度快文档容错能力强需要安装C语言库
lxml XML 解析器BeautifulSoup(markup, ["lxml-xml"])``BeautifulSoup(markup, "xml")速度快唯一支持XML的解析器需要安装C语言库
html5libBeautifulSoup(markup, "html5lib")最好的容错性以浏览器的方式解析文档生成HTML5格式的文档速度慢不依赖外部扩展

安装与配置

# 安装requests模块
pip install requests==2.10.0
# 安装beautiful soup4
pip install bs4
# 安装lxml解析器
pip install lxml

快速入门

将课件资料中的index.html文件复制到python项目中即可。

解析数据

标签

每个tag都有自己的名字,通过soup.name来获取标签。

# 获取p标签
p = soup.p
print(p)
# 获取title标签
title = soup.title
print(title)

注意:如果有多个相同的标签,则会返回第一个。

属性

一个标签可能有很多个属性。例如:标签 <b class="boldest"> 有一个 class 的属性,值为 boldest 。标签的属性的操作方法与字典相同。

  • 获取指定标签的单一属性,类似字典方式

# 获取p标签的class属性
attrs = soup.p["class"]
print(attrs)

注意:最常见的多值的属性是 class (一个标签可以有多个CSSclass). 还有一些属性 rel , rev , accept-charset , headers , accesskey . 在Beautiful Soup中多值属性的返回类型是list

  • 获取指定标签的单一属性,通过attrs方式

# 通过attrs获取p标签的id属性
id_ = soup.p.attrs["id"]
print(id_)

  • 获取指定标签的所有属性:

# 获取指定标签的所有属性
p_attrs = soup.p.attrs
print(p_attrs)

标签内容

通过.text.string获取标签节点的内容,也可以通过.strings获取标签节点下的所有内容。

# 获取单个标签的内容
text = soup.p.text
print(text)
print(soup.p.string)
# 获取该标签下所有的内容,返回generator生成器
strings = soup.div.strings
for st in strings:print(st)

关于解析标签的使用

from bs4 import BeautifulSoup
html_doc = """
<html>
<head><title>title</title></head>
<body><div><p class="aa" id="username">hello world</p><p>hello python</p><p>hello girl</p><input class="aa" type="text" value="hehe"/></div>
</body>
</html>
"""
# 解析文档
soup = BeautifulSoup(html_doc,'lxml')
# 获取p标签
p = soup.p
print(p)
# 获取title标签
title = soup.title
print(title)
# 逐级获取
pp = soup.body.div.input
print('逐级获取',pp)# 中括号的访问形式
# 获取标签某属性值
p_class = pp['type']
print(p_class)# attrs的访问方式
# 获取标签某属性值
id_ = soup.p.attrs["id"]
print(id_)
# 查看某标签的所有属性及值
attrs = p.attrs
print(attrs)
for k,v in attrs.items():print(k,v)
# 标签内容
print('div.text',soup.div.text)
print('div.string',soup.div.string)strings = soup.div.strings
print(strings)
for st in strings:print('st',st)

遍历文档树

子节点

标签小技巧获取层级子节点:

# tag小技巧获取层级子节点
print(soup.body.div.p)

.contents:将标签的子节点以列表的方式输出

# 获取div标签下的所有子节点
print(soup.body.div.contents)
# 获取div标签下的第二个子节点
print(soup.body.div.contents[1])
# 获取div标签下的第二个子节点的标签名
print(soup.body.div.contents[1].name)
# 获取div标签下的第二个子节点的所有属性
print(soup.body.div.contents[1].attrs)

.children:对标签的子节点进行循环

# 获取div下的的子节点
children = soup.body.div.children
print(children)
# 循环打印节点信息
for child in children:print(child)

.descendants:对所有标签的子孙节点进行递归循环

descendants = soup.body.descendants
for des in descendants:print(des)

更多内容请查看官网子节点。

from bs4 import BeautifulSoup
html_doc = """
<html>
<head><title>title</title></head>
<body><div><p class="aa" id="username">hello world<p>123</p></p><p>hello python</p><p>hello girl</p><input class="aa" type="text" value="hehe"/></div>
</body>
</html>
"""
# 解析文档
soup = BeautifulSoup(html_doc,'lxml')
# 获取div标签下的所有子节点
print(soup.div.contents)
# 获取div标签下的第二个子节点
print(soup.body.div.contents[1])
# 获取div标签下的第二个子节点的标签名
print(soup.body.div.contents[1].name)
# 获取div标签下的第二个子节点的所有属性
print(soup.body.div.contents[1].attrs)
# `.children`:对标签的子节点进行循环
for s in soup.div.children:print('s',s)
# `.descendants`:对所有标签的子孙节点进行递归循环
descendants = soup.div.descendants
for des in descendants:print('对所有标签的子孙节点进行递归循环',des)
父节点

.parent:获取某个元素的父节点

print(soup.p.parent)

.parents:递归得到元素的所有父辈节点

parents = soup.p.parents
for p in parents:print(p)

更多内容请查看官网父节点。

from bs4 import BeautifulSoup
html_doc = """
<html>
<head><title>title</title></head>
<body><div><p class="aa" id="username">hello world</p><p>hello python</p><p>hello girl</p><input class="aa" type="text" value="hehe"/></div>
</body>
</html>
"""
# 解析文档
soup = BeautifulSoup(html_doc,'lxml')
# `.parent`:获取某个元素的父节点
print(soup.p.parent,'\n')
# `.parents`:递归得到元素的所有父辈节点
parents = soup.p.parents
for p in parents:print(p)
兄弟节点

.next_sibling:获取下级单个兄弟节点

print(soup.p.next_sibling.next_sibling)

.previous_sibling:获取上级单个兄弟节点

print(soup.body.previous_sibling.previous_sibling)

注意:在使用.next_sibling.previous_sibling获取单个兄弟节点时,兄弟节点之间存在顿号和换行符的可能!!!

更多内容请查看官网兄弟节点。

from bs4 import BeautifulSoup
html_doc = """
<html>
<head><title>title</title></head>
<body><div><p class="aa" id="username">hello world<p>123</p></p><p>hello python</p><p>hello girl</p><input class="aa" type="text" value="hehe"/></div>
</body>
</html> 
"""
# 解析文档
soup = BeautifulSoup(html_doc,'lxml')
# 格式化文档
# print(soup.prettify())
# 获取下级单个兄弟标签
xd = soup.p.next_sibling
print(xd)
# `.previous_sibling`:获取上级单个兄弟节点
md = soup.p.previous_sibling
print(md)

搜索文档树

find

find方法,语法格式如下:

find( name , attrs , recursive , string , **kwargs )

参数说明:

参数说明
name需要查找的标签名,可以是字符串、正则表达式、列表或True
attrs需要查找的标签的属性,可以是字典类型或关键字参数
recursive是否递归地搜索子标签,默认为True,即会搜索所有子孙标签
string需要查找的标签中包含的文本内容
kwargs其他属性条件

通过find方法搜索指定的标签。

print(soup.find('p', class_="aa"))
print(soup.find('p', class_="aa", id="username"))

注意:class类样式的处理。

True 可以匹配任何值,如下示例返回第一个节点:

print(soup.find(True))

更多内容请查看官网。

find_all

find_all()方法的基本语法如下:

find_all(name=None, attrs={}, recursive=True, text=None, limit=None, **kwargs)

参数说明:

参数说明
name需要查找的标签名,可以是字符串、正则表达式、列表或True
attrs需要查找的标签的属性,可以是字典类型或关键字参数
recursive是否递归地搜索子标签,默认为True,即会搜索所有子孙标签
text需要查找的标签中包含的文本内容
limit限制返回的结果数量,可以传入一个整数值

返回值:

  • 如果找到满足条件的元素,则返回一个包含这些元素的列表。

  • 如果未找到满足条件的元素,则返回一个空列表。

find_add方法搜索当前标签下所有子节点,并判断是否符合过滤器的条件。

all = soup.find_all('p')
for a in all:print(a)
print(soup.find_all(["p", "input"]))

更多内容请查看官网。

from bs4 import BeautifulSoup
html_doc = """
<html>
<head><title>title</title></head>
<body><div><p class="aa" id="username">hello world<p>mmmm</p></p><p class="aa" id="pa">hello world</p><p>hello python</p><p>hello girl</p><input class="aa" type="text" value="hehe"/></div>
</body>
</html>
"""
soup = BeautifulSoup(html_doc,'lxml')
# find和find_all的区别:
# find:查一个
# find_all:查多个# # 标签查找(返回列表格式)
# ps = soup.find_all(['p','input'])
# print(ps)
# # 根据属性查找
# pr = soup.find_all(class_='aa')
# print(pr)
#
# print(soup.find(attrs={"value":"hehe"}))
css选择器

Beautiful Soup支持大部分的CSS选择器。在 TagBeautifulSoup 对象的 .select() 方法中传入字符串参数, 即可使用CSS选择器的语法找到标签:

print(soup.select("title"))
print(soup.select("body div"))
print(soup.select("p.aa"))
from bs4 import BeautifulSouphtml_doc = """
<html>
<head><title>title</title></head>
<body><div><p class="aa" id="username">hello world<p id ='e'>mmmm</p></p><p class="aa" id="pa">hello world</p><p>hello python</p><p>hello girl</p><input class="aa" type="text" value="hehe"/></div>
</body>
</html>
"""
# 解析文档
soup = BeautifulSoup(html_doc,'lxml')
# CSS查询
# 类名
print(soup.div.select(".aa"))
# id
print(soup.select('#pa'))
#p标签中类名为aa
print(soup.select('p.aa'))
#div标签中的p标签
print(soup.select('div p'))
#获取属性值(id的值)
print(soup.select('.aa')[0].get("id"))

3.综合案例

通过requestsBeautiful Soup4模块结合实现小说网站内容爬虫案例。

import requests   # 导入requests模块,用于发送网络请求
from bs4 import BeautifulSoup   # 导入BeautifulSoup模块,用于解析HTML文档# 发送GET请求到指定的URL
resp = equests.get('https://www.readnovel.com/chapter/22376031000468402/96104372900365392')
# 获取网页文档
soup = BeautifulSoup(resp.text, 'lxml')  # 使用lxml解析器解析响应的文本内容for i in range(3):  # 循环3次,用于爬取前三章的数据print(f'正在爬取{i + 1}章数据')  # 打印当前正在爬取的章节编号with open("庆余年", "a+", encoding="utf-8") as fp:  # 以追加模式打开文件"庆余年",编码为utf-8title = soup.find(class_='j_chapterName')  # 查找具有'class_='j_chapterName'的元素fp.write(title.string + "\n")  # 将找到的章节标题写入文件,后面跟一个换行符strings = soup.select('.ywskythunderfont')[0].strings  # 选择具有'class_='ywskythunderfont'的元素,并获取其文本内容for line in list(strings)[0:-1]:  # 遍历字符串列表,跳过最后一个元素(通常是章节结束标记)fp.write(line + "\n")  # 将每一行内容写入文件,后面跟一个换行符# 下一章href = "小说阅读网" + soup.select('#j_chapterNext')[0]['href']  # 获取下一章的链接地址resp = requests.get(href)  # 发送GET请求到下一章的链接地址soup = BeautifulSoup(resp.text, 'lxml')  # 使用lxml解析器解析响应的文本内容

这篇关于python-14(BS4解析网页)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/1008570

相关文章

8种快速易用的Python Matplotlib数据可视化方法汇总(附源码)

《8种快速易用的PythonMatplotlib数据可视化方法汇总(附源码)》你是否曾经面对一堆复杂的数据,却不知道如何让它们变得直观易懂?别慌,Python的Matplotlib库是你数据可视化的... 目录引言1. 折线图(Line Plot)——趋势分析2. 柱状图(Bar Chart)——对比分析3

Python模拟串口通信的示例详解

《Python模拟串口通信的示例详解》pySerial是Python中用于操作串口的第三方模块,它支持Windows、Linux、OSX、BSD等多个平台,下面我们就来看看Python如何使用pySe... 目录1.win 下载虚www.chinasem.cn拟串口2、确定串口号3、配置串口4、串口通信示例5

Python Pandas高效处理Excel数据完整指南

《PythonPandas高效处理Excel数据完整指南》在数据驱动的时代,Excel仍是大量企业存储核心数据的工具,Python的Pandas库凭借其向量化计算、内存优化和丰富的数据处理接口,成为... 目录一、环境搭建与数据读取1.1 基础环境配置1.2 数据高效载入技巧二、数据清洗核心战术2.1 缺失

使用Java实现Navicat密码的加密与解密的代码解析

《使用Java实现Navicat密码的加密与解密的代码解析》:本文主要介绍使用Java实现Navicat密码的加密与解密,通过本文,我们了解了如何利用Java语言实现对Navicat保存的数据库密... 目录一、背景介绍二、环境准备三、代码解析四、核心代码展示五、总结在日常开发过程中,我们有时需要处理各种软

利用Python实现Excel文件智能合并工具

《利用Python实现Excel文件智能合并工具》有时候,我们需要将多个Excel文件按照特定顺序合并成一个文件,这样可以更方便地进行后续的数据处理和分析,下面我们看看如何使用Python实现Exce... 目录运行结果为什么需要这个工具技术实现工具的核心功能代码解析使用示例工具优化与扩展有时候,我们需要将

Python+PyQt5实现文件夹结构映射工具

《Python+PyQt5实现文件夹结构映射工具》在日常工作中,我们经常需要对文件夹结构进行复制和备份,本文将带来一款基于PyQt5开发的文件夹结构映射工具,感兴趣的小伙伴可以跟随小编一起学习一下... 目录概述功能亮点展示效果软件使用步骤代码解析1. 主窗口设计(FolderCopyApp)2. 拖拽路径

Python使用Reflex构建现代Web应用的完全指南

《Python使用Reflex构建现代Web应用的完全指南》这篇文章为大家深入介绍了Reflex框架的设计理念,技术特性,项目结构,核心API,实际开发流程以及与其他框架的对比和部署建议,感兴趣的小伙... 目录什么是 ReFlex?为什么选择 Reflex?安装与环境配置构建你的第一个应用核心概念解析组件

Python将字符串转换为小写字母的几种常用方法

《Python将字符串转换为小写字母的几种常用方法》:本文主要介绍Python中将字符串大写字母转小写的四种方法:lower()方法简洁高效,手动ASCII转换灵活可控,str.translate... 目录一、使用内置方法 lower()(最简单)二、手动遍历 + ASCII 码转换三、使用 str.tr

Python处理超大规模数据的4大方法详解

《Python处理超大规模数据的4大方法详解》在数据的奇妙世界里,数据量就像滚雪球一样,越变越大,从最初的GB级别的小数据堆,逐渐演变成TB级别的数据大山,所以本文我们就来看看Python处理... 目录1. Mars:数据处理界的 “变形金刚”2. Dask:分布式计算的 “指挥家”3. CuPy:GPU

Python多进程、多线程、协程典型示例解析(最新推荐)

《Python多进程、多线程、协程典型示例解析(最新推荐)》:本文主要介绍Python多进程、多线程、协程典型示例解析(最新推荐),本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定... 目录一、multiprocessing(多进程)1. 模块简介2. 案例详解:并行计算平方和3. 实现逻