当前位置: 首页 > news >正文

python学习:爬虫+项目测试

        本期我们来学习一个python中的一个常见的应用:爬虫。

        相关代码已经上传至作者个人gitee:楼田莉子/Python 学习

目录

爬虫的介绍

requests请求库

        什么是requests请求库

        requests请求库的下载

beautiful soup解析库

        beautiful soup解析库

        beautiful soup对象的介绍及其创建

        1. BeautifulSoup 对象

2. Tag 对象

        3. NavigableString 对象

        4. Comment 对象

        对象关系与示例

        beautiful soup对象的find方法

        beautiful soup4方法表

正则表达式

        正则表达式基本语法

        元字符表

        量词模式表

        标志修饰符表

        常用模式示例表

        转义字符表        

        特殊转义序列表

        字符类转义表

        Unicode 字符类转义

        正则表达式方法

        re 模块主要函数表

        正则表达式模式对象 (Pattern) 方法表

        匹配对象 (Match) 方法表

        方法参数详解表

        标志参数表

        使用示例对比表

        findall方法中flag参数详解

        r原串

json模块      

        json转python

        python转json

项目测试:爬取图片


爬虫的介绍

        在浏览器上搜索相关的内容是很常见的事情,但是如果我们要进行多轮访问搜索的话就会显得很麻烦,因此便有了爬虫这个东西的存在。

        当你使用浏览器的时候,会先发送请求给服务器,随后服务器会获取反馈数据并进行渲染。

        但是爬虫只是发送请求给服务器,随后服务器会获取反馈相应的数据

        网络爬虫的定义如下:

        网络爬虫(Web Crawler),也被称为网络蜘蛛(Web Spider),是一种按照预设规则,自动、批量地浏览万维网并下载网页内容的计算机程序或自动化脚本。它是搜索引擎的核心组成部分,也是大数据领域进行数据采集的关键技术。

        关于爬虫,其核心概念主要有以下几点:

  • 种子URL: 爬虫开始抓取的初始网址集合。

  • 网页抓取: 通过HTTP/HTTPS协议向目标服务器发送请求,并获取网页原始数据(通常是HTML代码)的过程。

  • 解析与提取: 对抓取到的网页进行解析(如使用正则表达式、XPath、CSS选择器等),从中提取出有价值的结构化数据(如文本、链接、图片URL等)和新的URL。

  • URL队列: 一个用于管理待抓取URL的队列,爬虫会从队列中取出URL进行抓取,并将新发现的URL放入队列,遵循一定的策略(如广度优先或深度优先)。

  • 去重: 在爬行过程中,通过特定算法(如布隆过滤器)对URL进行判重,避免重复抓取相同页面,提高效率。

  • Robots协议: 网站所有者放置在根目录下的robots.txt文件,用于告知爬虫哪些目录或文件可以被抓取,哪些应被禁止。遵守该协议是网络爬虫的道德和法律基础。

        爬虫的特点是:

  • 自动化: 无需人工干预,可7x24小时不间断工作。

  • 高效性: 抓取速度远超人工操作,能快速处理海量数据。

  • 可扩展性: 可以通过分布式架构,部署多个爬虫节点协同工作,进一步提升抓取能力。

  • 按需配置: 爬虫的行为和规则可以根据目标网站的结构和用户的数据需求进行高度定制。

requests请求库

        什么是requests请求库

        requests 是 Python 中最流行、最简洁易用的 HTTP 库。在爬虫中,它的核心作用就是模拟浏览器向目标网站服务器发送 HTTP 请求,并获取服务器返回的响应数据

        requests请求库的下载

        本次我们采用pip下载方式,关于pip的内容在作者前面的博客内容中已经介绍过了,可以去看这篇博客:https://blog.csdn.net/2401_89119815/article/details/151651579?fromshare=blogdetail&sharetype=blogdetail&sharerId=151651579&sharerefer=PC&sharesource=2401_89119815&sharefrom=from_link

        下载方式:在终端敲入如下所示的代码

pip install requests

        验证安装

import requests
print(requests.__version__)

        如果运行没有报错就安装成功

        示例:

#导入模块
import requests
#发送请求
response=requests.get("https://www.baidu.com")
#获知字符编码格式
#print(response.encoding)
#如果不是utf-8可以这么指定
#response.encoding="utf-8"
#获取响应
print(response.text)#文本数据
print(response.content)#二进制数据
#二进制解码为utf-8字符编码格式
print(response.content.decode("utf-8"))

beautiful soup解析库

        Beautiful Soup(简称 bs4)是一个 Python 库,其主要功能是从 HTML 或 XML 文档中提取数据

        其作用为:

  • 解析混乱的 HTML:即使 HTML 格式不规范、标签未闭合,它也能很好地处理。

  • 导航与搜索:提供了一套简单、直观的方法来遍历 HTML 的树形结构,并快速找到所需的标签和内容。

  • 数据提取:从标签中提取文本、属性(如链接的 href、图片的 src)。

        beautiful soup解析库

        beautiful soup3已经停止更新了,所以我们只下载beautiful soup解析库4

pip install beautifulsoup4

        注意:尽管安装的时候叫beautifulsoup4,但是导入的时候是导入bs4!

        同时为了更好的兼容性,建议安装lxml解析器,安装方式如下

pip install lxml

        beautiful soup对象的介绍及其创建

        BeautifulSoup对象:代表要解析整个文档树。
        它支持 遍历文档树 和 搜索文档树 中描述的大部分的方法。

        测试:

#导入模块
from bs4 import BeautifulSoup
import lxml
#创建对象
soup=BeautifulSoup("<html>data</html>",'lxml')
#打印对象
print(soup)

         beautiful soup对象主要有以下几个部分组成:

        1. BeautifulSoup 对象

        作用:代表整个解析后的文档,是解析树的根节点。

        特点

  • 可以像 Tag 对象一样进行遍历和搜索

  • 包含了文档的所有内容

  • 通常是我们创建的第一个对象

    #创建对象
    from bs4 import BeautifulSouphtml_doc = """
    <html>
    <head><title>示例页面</title></head>
    <body>
    <p class="content">这是一个段落</p>
    </body>
    </html>
    """soup = BeautifulSoup(html_doc, 'lxml')
    print(type(soup))  # <class 'bs4.BeautifulSoup'>
    #常见方法
    # 获取文档标题
    print(soup.title)  # <title>示例页面</title># 获取文档的字符串表示
    print(soup.prettify())  # 格式化的HTML# 查找所有元素(与Tag对象方法相同)
    all_ps = soup.find_all('p')

    2. Tag 对象

    作用:对应 HTML/XML 中的标签,是 BeautifulSoup 中最常用的对象。

    特点

  • 具有名称和属性

  • 可以包含其他 Tag 对象或字符串

  • 支持遍历和搜索方法

#创建对象
# 获取第一个 <p> 标签
p_tag = soup.p
print(type(p_tag))  # <class 'bs4.element.Tag'># 标签名称
print(p_tag.name)   # 'p'# 标签属性(返回字典)
print(p_tag.attrs)  # {'class': ['content']}# 获取特定属性
print(p_tag['class'])     # ['content']
print(p_tag.get('class')) # ['content']
#常见方法
# 查找后代标签
p_tag.find_all('span')# 获取所有直接子标签
list(p_tag.children)# 获取所有后代标签
list(p_tag.descendants)# 获取父标签
parent = p_tag.parent# 获取兄弟标签
next_sibling = p_tag.next_sibling
prev_sibling = p_tag.previous_sibling

        3. NavigableString 对象

        作用:代表标签内的文本内容,是特殊的字符串对象。

        特点

  • 可以像普通字符串一样操作

  • 支持在解析树中导航

  • 不包含任何子节点

    # 获取标签的文本内容
    text_content = p_tag.string
    print(type(text_content))  # <class 'bs4.element.NavigableString'>
    print(text_content)        # '这是一个段落'# 或者使用 .text 属性(获取所有后代文本)
    print(p_tag.text)          # '这是一个段落'# NavigableString 可以转换为普通字符串
    normal_string = str(text_content)
    print(type(normal_string)) # <class 'str'>

        重要区别

  • .string:如果标签只有一个子节点且是字符串,返回该字符串,否则返回 None

  • .text 或 .get_text():返回标签及其所有后代标签中的文本内容
html = '<div>Hello <span>World</span></div>'
soup = BeautifulSoup(html, 'lxml')
div_tag = soup.divprint(div_tag.string)   # None(因为包含多个子节点)
print(div_tag.text)     # 'Hello World'(所有文本内容)

        4. Comment 对象

        作用:特殊类型的 NavigableString,表示 HTML 注释。

        特点

  • 继承自 NavigableString

  • 在输出时不会显示注释符号

  • 需要特殊处理来识别

html_with_comment = '<p>正常文本<!-- 这是一个注释 --></p>'
soup = BeautifulSoup(html_with_comment, 'lxml')
p_tag = soup.p# 遍历所有子节点
for child in p_tag.children:print(f"类型: {type(child)}, 内容: {repr(child)}")# 输出:
# 类型: <class 'bs4.element.NavigableString'>, 内容: '正常文本'
# 类型: <class 'bs4.element.Comment'>, 内容: ' 这是一个注释 '# 检查是否为注释
comment = list(p_tag.children)[1]
print(isinstance(comment, str))        # True(Comment也是字符串)
print(hasattr(comment, 'comment'))     # 检查是否有comment属性

        对象关系与示例

from bs4 import BeautifulSoup# 复杂HTML示例
complex_html = """
<html>
<body>
<div id="main"><h1>标题</h1><p class="content">第一段<strong>重点</strong>内容</p><!-- 这是注释 --><p>第二段内容</p>
</div>
</body>
</html>
"""soup = BeautifulSoup(complex_html, 'lxml')# 1. 获取BeautifulSoup对象
print("=== BeautifulSoup对象 ===")
print(f"文档类型: {type(soup)}")# 2. 获取Tag对象
div_tag = soup.find('div', id='main')
print("\n=== Tag对象 ===")
print(f"标签名: {div_tag.name}")
print(f"标签属性: {div_tag.attrs}")# 3. 遍历Tag对象的子节点
print("\n=== 遍历子节点 ===")
for i, child in enumerate(div_tag.children):print(f"子节点 {i}: 类型={type(child).__name__}, 内容={repr(str(child)[:30])}")# 4. 处理NavigableString
print("\n=== NavigableString ===")
first_p = div_tag.find('p')
print(f"段落文本: {repr(first_p.text)}")# 5. 处理混合内容
print("\n=== 混合内容分析 ===")
for element in first_p.contents:element_type = type(element).__name__content = repr(str(element).strip())print(f"元素: {element_type:15} -> {content}")

        打印结果为:

=== BeautifulSoup对象 ===
文档类型: <class 'bs4.BeautifulSoup'>=== Tag对象 ===
标签名: div
标签属性: {'id': 'main'}=== 遍历子节点 ===
子节点 0: 类型=NavigableString, 内容='\n'
子节点 1: 类型=Tag, 内容='<h1>标题</h1>'
子节点 2: 类型=NavigableString, 内容='\n'
子节点 3: 类型=Tag, 内容='<p class="content">第一段<strong>'
子节点 4: 类型=NavigableString, 内容='\n'
子节点 5: 类型=Comment, 内容=' 这是注释 '
子节点 6: 类型=NavigableString, 内容='\n'
子节点 7: 类型=Tag, 内容='<p>第二段内容</p>'
子节点 8: 类型=NavigableString, 内容='\n'=== NavigableString ===
段落文本: '第一段重点内容'=== 混合内容分析 ===
元素: NavigableString -> '第一段'
元素: Tag             -> '<strong>重点</strong>'
元素: NavigableString -> '内容'

        beautiful soup对象的find方法

        find方法的作用:搜索文档树

        语法格式:

find(name=None, attrs={}, recursive=True, string=None, **kwargs)

        参数为以下含义:

参数类型说明默认值
name字符串/列表/正则表达式/函数要查找的标签名称None
attrs字典要匹配的属性键值对{}
recursive布尔值是否递归搜索所有子节点True
string字符串/正则表达式/函数要匹配的文本内容None
**kwargs键值参数属性的快捷方式(如 id="main"-

        返回值内容:

  • 找到匹配元素:返回 Tag 对象

  • 未找到匹配元素:返回 None

一个案例讲遍find所有方法:

#导入模块
from bs4 import BeautifulSoup
#准备文档字符串
html='''<!DOCTYPE html>
<html>
<head><title>简单测试页面</title>
</head>
<body><h1>商品列表</h1><div class="product"><h2 class="name">笔记本电脑</h2><p class="price">¥5999</p><p class="category">电子产品</p></div><div class="product"><h2 class="name">Python编程书</h2><p class="price">¥89</p><p class="category">图书</p></div><div class="product sale"><h2 class="name">无线鼠标</h2><p class="price">¥129 <span class="old-price">¥199</span></p><p class="category">电子产品</p></div><table border="1"><tr><th>商品</th><th>库存</th></tr><tr><td>笔记本电脑</td><td>15</td></tr><tr><td>Python编程书</td><td>32</td></tr></table><div class="pagination"><a href="/page1">上一页</a><a href="/page2">1</a><a href="/page3">2</a><a href="/page4">下一页</a></div>
</body>
</html>'''
#创建对象
soup=BeautifulSoup(html,"lxml")
#查找title标签
title=soup.find('title')
print(title)
#查找a标签
a=soup.find('a')
print(a)
#查找所有的a标签
a_s=soup.find_all('a')
print(a_s)
#根据属性查找
#方式一:命名参数指定
link1=soup.find(id="name")
print(link1)
#方式二:attrs指定属性字典,更推荐这个方法
link1_2 =soup.find(attrs={"id":"name"})
print(link1_2)
#查找文本
text=soup.find(text="Python编程书")
print(text)
#tag对象
print(type(a))
#标签名
print("标签名>",a.name)
print("标签属性>",a.attrs)
print("标签文本内容>",a.text)

        beautiful soup4方法表

方法类别方法名称功能描述返回值类型
文档解析BeautifulSoup(html, 'parser')创建BeautifulSoup对象,解析HTML/XML文档BeautifulSoup对象
搜索方法find(name, attrs, recursive, string, **kwargs)查找第一个匹配的标签Tag对象 或 None
find_all(name, attrs, recursive, string, limit, **kwargs)查找所有匹配的标签ResultSet(Tag对象列表)
find_parent(name, attrs, string, **kwargs)在父标签中查找第一个匹配的标签Tag对象 或 None
find_parents(name, attrs, string, limit, **kwargs)在祖先标签中查找所有匹配的标签ResultSet(Tag对象列表)
find_next_sibling(name, attrs, string, **kwargs)查找后一个兄弟标签Tag对象 或 None
find_previous_sibling(name, attrs, string, **kwargs)查找前一个兄弟标签Tag对象 或 None
select(css_selector)使用CSS选择器查找所有匹配的标签ResultSet(Tag对象列表)
select_one(css_selector)使用CSS选择器查找第一个匹配的标签Tag对象 或 None
遍历方法contents获取标签的直接子节点列表列表
children获取标签的直接子节点的迭代器生成器
descendants获取标签所有后代节点的迭代器生成器
parent获取标签的父节点Tag对象 或 BeautifulSoup对象
parents获取标签所有祖先节点的迭代器生成器
next_sibling获取后一个兄弟节点PageElement 或 None
previous_sibling获取前一个兄弟节点PageElement 或 None
next_siblings获取后面所有兄弟节点的迭代器生成器
previous_siblings获取前面所有兄弟节点的迭代器生成器
数据提取get_text(separator, strip)获取标签及其所有后代的文本内容字符串
text获取标签及其所有后代的文本内容(get_text()的别名)字符串
string如果标签只有一个NavigableString子节点,则返回该节点NavigableString 或 None
strings获取标签内所有字符串的迭代器生成器
stripped_strings获取标签内所有去空白的字符串迭代器生成器
get(attribute_name, default)获取标签属性的值属性值字符串 或 default
has_attr(attribute_name)检查标签是否包含指定属性布尔值
attrs获取标签的所有属性字典字典
文档操作prettify(encoding, formatter)返回格式化的文档字符串字符串
decode(pretty, encoding, formatter)将文档渲染为字符串字符串
encode(encoding, indent, formatter)将文档编码为字节字节
append(tag)向标签中添加内容None
extract()将标签从文档树中移除Tag对象
decompose()将标签从文档树中移除并完全销毁None
replace_with(content)用指定内容替换当前标签None
wrap(tag)用指定标签包装当前标签新Tag对象
unwrap()移除当前标签的包装,保留其内容被移除的Tag对象

正则表达式

        正则表达式(Regular Expression)是一种强大的文本处理工具,用于在字符串中进行模式匹配和搜索操作。Python 通过 re 模块提供了完整的正则表达式功能。        

import re

        正则表达式是由普通字符和特殊字符(元字符)组成的文本模式,用于描述、匹配一系列符合某个句法规则的字符串。

        正则表达式基本语法

        元字符表

类别元字符描述示例匹配结果
基本匹配.匹配除换行符外的任意字符a.c"abc", "a c", "a-c"
\转义字符a\.c"a.c" (不匹配 "abc")
位置锚点^匹配字符串开始^abc"abc" (仅在开头)
$匹配字符串结束abc$"abc" (仅在结尾)
\b单词边界\bword\b"word" (作为独立单词)
\B非单词边界\Bword\B"swordfish" 中的 "word"
量词*匹配前元素0次或多次ab*c"ac", "abc", "abbc"
+匹配前元素1次或多次ab+c"abc", "abbc" (不匹配 "ac")
?匹配前元素0次或1次ab?c"ac", "abc"
{n}匹配前元素恰好n次a{3}"aaa"
{n,}匹配前元素至少n次a{2,}"aa", "aaa", ...
{n,m}匹配前元素n到m次a{2,4}"aa", "aaa", "aaaa"
字符类[]字符集合[aeiou]任意元音字母
[^]否定字符集合[^aeiou]任意非元音字符
-字符范围[a-z]任意小写字母
预定义字符类\d数字字符\d+"123", "45"
\D非数字字符\D+"abc", "!@#"
\s空白字符\s+空格, 制表符, 换行
\S非空白字符\S+"abc", "123"
\w单词字符\w+"hello", "word123"
\W非单词字符\W+"!", "?*"
分组与引用()捕获分组(abc)+"abc", "abcabc"
(?:)非捕获分组(?:abc)+"abc" (不捕获分组)
|或操作cat|dog"cat" 或 "dog"
\n反向引用(a)b\1"aba"
特殊字符\n换行符\n换行
\t制表符\t制表符
\r回车符\r回车

        量词模式表

模式描述示例匹配结果
贪婪匹配默认模式,尽可能多匹配a.*b"axxxbxxxb" → "axxxbxxxb"
懒惰匹配尽可能少匹配a.*?b"axxxbxxxb" → "axxxb"
独占匹配不回溯的匹配a.*+b"axxxb" → 匹配成功

        标志修饰符表

标志简写描述示例
re.IGNORECASEre.I忽略大小写[a-z] 匹配 "A", "B", "C"
re.MULTILINEre.M多行模式^ 匹配每行开头
re.DOTALLre.S.匹配所有字符. 匹配换行符
re.VERBOSEre.X忽略空白和注释允许格式化正则表达式
re.ASCIIre.A仅ASCII字符\w 只匹配ASCII字符

        常用模式示例表

用途正则表达式说明
邮箱^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$基本邮箱验证
URLhttps?://[^\s]+匹配HTTP/HTTPS链接
中文[\u4e00-\u9fff]匹配中文字符
IP地址\b(?:\d{1,3}\.){3}\d{1,3}\b简单IP地址匹配
日期\d{4}-\d{2}-\d{2}YYYY-MM-DD格式
手机号1[3-9]\d{9}中国手机号格式

        转义字符表        

字符正则表达式写法匹配内容示例
.\.句点字符a\.b 匹配 "a.b"
*\*星号字符a\*b 匹配 "a*b"
+\+加号字符a\+b 匹配 "a+b"
?\?问号字符a\?b 匹配 "a?b"
$\$美元符号\$100 匹配 "$100"
^\^脱字符\^start 匹配 "^start"
[\[左方括号\[abc\] 匹配 "[abc]"
]\]右方括号\[abc\] 匹配 "[abc]"
(\(左圆括号\(group\) 匹配 "(group)"
)\)右圆括号\(group\) 匹配 "(group)"
{\{左花括号\{3\} 匹配 "{3}"
}\}右花括号\{3\} 匹配 "{3}"
||竖线字符cat|dog 匹配 "cat" 或 "dog"
\\\\\\反斜杠字符C:\\\\Windows 匹配 "C:\Windows"
        特殊转义序列表
转义序列描述示例匹配结果
\n换行符line1\nline2匹配两行文本
\r回车符\r\nWindows 换行符
\t制表符col1\tcol2制表符分隔的文本
\f换页符\f换页字符
\v垂直制表符\v垂直制表符
\a响铃符\a响铃字符
\e转义符\eESC 字符
\0空字符\0NULL 字符
        字符类转义表
转义序列描述等价写法示例
\d任意数字[0-9]\d+ 匹配 "123"
\D任意非数字[^0-9]\D+ 匹配 "abc"
\s任意空白字符[ \t\n\r\f\v]\s+ 匹配空格和制表符
\S任意非空白字符[^ \t\n\r\f\v]\S+ 匹配 "word"
\w单词字符[a-zA-Z0-9_]\w+ 匹配 "hello_123"
\W非单词字符[^a-zA-Z0-9_]\W+ 匹配 "!@#"
        Unicode 字符类转义
转义序列描述示例
\p{Lu}大写字母匹配大写字母(需 regex 模块)
\p{Ll}小写字母匹配小写字母(需 regex 模块)
\p{N}数字字符匹配数字(需 regex 模块)
\p{P}标点符号匹配标点(需 regex 模块)

        正则表达式方法

        re 模块主要函数表

方法语法功能描述返回值使用场景
re.match()re.match(pattern, string, flags=0)从字符串起始位置匹配模式匹配对象(成功)或 None(失败)验证字符串开头格式
re.search()re.search(pattern, string, flags=0)扫描整个字符串,返回第一个匹配匹配对象(成功)或 None(失败)查找字符串中的第一个匹配项
re.findall()re.findall(pattern, string, flags=0)返回字符串中所有非重叠匹配的列表字符串列表(无分组)或元组列表(有分组)提取所有符合模式的子串
re.finditer()re.finditer(pattern, string, flags=0)返回匹配对象的迭代器匹配对象迭代器处理大量匹配时节省内存
re.sub()re.sub(pattern, repl, string, count=0, flags=0)替换字符串中的匹配项替换后的新字符串文本替换和清洗
re.subn()re.subn(pattern, repl, string, count=0, flags=0)替换匹配项并返回替换次数(新字符串, 替换次数) 元组需要知道替换次数的场景
re.split()re.split(pattern, string, maxsplit=0, flags=0)根据模式分割字符串分割后的字符串列表复杂分隔符的分割操作
re.compile()re.compile(pattern, flags=0)编译正则表达式模式正则表达式模式对象重复使用同一模式时提高效率
re.escape()re.escape(pattern)转义模式中的特殊字符转义后的字符串处理用户输入作为正则表达式时
re.fullmatch()re.fullmatch(pattern, string, flags=0)整个字符串完全匹配模式匹配对象(完全匹配)或 None验证字符串完全符合格式

        正则表达式模式对象 (Pattern) 方法表

方法语法功能描述返回值
Pattern.match()pattern.match(string, pos=0, endpos=-1)从指定位置开始匹配匹配对象或 None
Pattern.search()pattern.search(string, pos=0, endpos=-1)在指定范围内搜索第一个匹配匹配对象或 None
Pattern.findall()pattern.findall(string, pos=0, endpos=-1)返回指定范围内所有匹配字符串列表或元组列表
Pattern.finditer()pattern.finditer(string, pos=0, endpos=-1)返回匹配对象的迭代器匹配对象迭代器
Pattern.sub()pattern.sub(repl, string, count=0)替换匹配项替换后的字符串
Pattern.subn()pattern.subn(repl, string, count=0)替换匹配项并返回次数(新字符串, 替换次数)
Pattern.split()pattern.split(string, maxsplit=0)分割字符串分割后的字符串列表
Pattern.fullmatch()pattern.fullmatch(string, pos=0, endpos=-1)完全匹配字符串匹配对象或 None

        匹配对象 (Match) 方法表

方法语法功能描述返回值
Match.group()match.group([group1, ...])返回一个或多个匹配的子组字符串或字符串元组
Match.groups()match.groups(default=None)返回所有匹配子组的元组字符串元组
Match.groupdict()match.groupdict(default=None)返回命名分组的字典字典 {组名: 匹配值}
Match.start()match.start([group])返回指定组匹配的开始位置整数索引
Match.end()match.end([group])返回指定组匹配的结束位置整数索引
Match.span()match.span([group])返回指定组的 (开始, 结束) 位置(start, end) 元组
Match.expand()match.expand(template)根据模板返回扩展字符串扩展后的字符串

        方法参数详解表

参数适用方法描述默认值示例
pattern所有 re 函数正则表达式模式字符串必需r"\d+"
string所有匹配方法要搜索的目标字符串必需"abc123"
flags所有 re 函数匹配标志(位掩码)0re.IGNORECASE
replsub(), subn()替换字符串或函数必需"replacement"
countsub(), subn()最大替换次数0(无限制)1
maxsplitsplit()最大分割次数0(无限制)2
posPattern 方法搜索起始位置05
endposPattern 方法搜索结束位置-1(到结尾)10
groupMatch 方法分组编号或名称None(整个匹配)1 或 'name'

        标志参数表

标志简写描述示例用法
re.IGNORECASEre.I忽略大小写re.search("abc", "ABC", re.I)
re.MULTILINEre.M多行模式re.findall("^abc", text, re.M)
re.DOTALLre.S让 . 匹配换行符re.search("a.b", text, re.S)
re.VERBOSEre.X忽略空白和注释复杂正则表达式的格式化
re.ASCIIre.A让 \w, \W 等只匹配 ASCIIre.findall(r"\w+", text, re.A)
re.LOCALEre.L依赖本地设置的匹配已不推荐使用
re.DEBUG-显示调试信息re.compile(pattern, re.DEBUG)

        使用示例对比表

场景推荐方法示例代码输出结果
验证字符串格式re.match()re.match(r"\d{3}", "123abc")匹配对象
查找第一个匹配re.search()re.search(r"\d+", "abc123def")<re.Match object>
提取所有数字re.findall()re.findall(r"\d+", "a1b23c456")['1', '23', '456']
处理大文件匹配re.finditer()for match in re.finditer(r"\w+", text):迭代处理
替换文本re.sub()re.sub(r"\d+", "#", "a1b2")"a#b#"
分割复杂文本re.split()re.split(r"[,;]\s*", "a,b; c")['a', 'b', 'c']
重复使用模式re.compile()pattern = re.compile(r"\d+")模式对象

        findall方法中flag参数详解

标志常量缩写数值描述Python版本
re.IGNORECASEre.I2忽略大小写所有版本
re.MULTILINEre.M8多行模式所有版本
re.DOTALLre.S16让 . 匹配换行符所有版本
re.VERBOSEre.X64详细模式,忽略空白和注释所有版本
re.ASCIIre.A256让 \w, \W, \b, \B, \d, \D, \s, \S 只匹配 ASCIIPython 3.6+
re.LOCALEre.L4依赖本地设置(不推荐使用)所有版本
re.DEBUG-128显示调试信息所有版本
re.UNICODEre.U32Unicode 匹配(Python 3 默认)Python 2

        r原串

        r原串是原始字符串,是Python中一种特殊的字符串字面量,以 r 或 R 为前缀,表示字符串中的反斜杠 \ 不会被当作转义字符处理。

        语法格式为:

r"字符串内容"
R"字符串内容"

        尽管转义字符也可以,但是相比之下很麻烦,以下是对比

描述普通字符串写法原始字符串写法实际匹配内容
匹配数字"\\d+"r"\d+"一个或多个数字
匹配单词边界"\\bword\\b"r"\bword\b"独立的单词"word"
匹配反斜杠"\\\\"r"\\"单个反斜杠字符
匹配制表符"\\t"r"\t"制表符(原始字符串中\t仍被解释)

        正则表达式中的应用:

import re# 复杂的正则表达式示例
# 匹配Windows文件路径
path = r"C:\Users\Documents\file.txt"# 错误:普通字符串(反斜杠被转义)
wrong_pattern = "C:\\Users\\Documents\\.*"  # \f 被转义为换页符
# 正确:原始字符串
correct_pattern = r"C:\\Users\\Documents\\.*"result = re.findall(correct_pattern, path)
print(result)  # ['C:\\Users\\Documents\\file.txt']# 匹配邮箱中的特殊字符
email_pattern = r"user\.name@example\.com"
text = "联系 user.name@example.com"
result = re.findall(email_pattern, text)
print(result)  # ['user.name@example.com']

        文件路径处理

import re# Windows 文件路径匹配
windows_path = r"C:\Users\John\Documents\file.txt"
pattern = r"[A-Z]:\\(?:[^\\]+\\)*[^\\]+"
result = re.findall(pattern, windows_path)
print(result)  # ['C:\\Users\\John\\Documents\\file.txt']# Unix 文件路径匹配
unix_path = "/home/user/documents/file.txt"
pattern = r"/(?:[^/]+/)*[^/]+"
result = re.findall(pattern, unix_path)
print(result)  # ['/home/user/documents/file.txt']

json模块      

        JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,具有以下特点:

  • 人类可读:文本格式,易于阅读和编写

  • 语言无关:独立于编程语言

  • 自描述性:数据结构清晰明确

  • 高效:解析和生成速度快

        在python中json可以实现数据的相互交换        

        基础数据类型转换

JSON 数据类型JSON 示例Python 数据类型Python 示例转换说明
object{"name": "John"}dict{"name": "John"}对象直接转换为字典
array[1, 2, 3]list[1, 2, 3]数组转换为列表
string"hello"str"hello"字符串直接对应
number (整数)42int42整数直接对应
number (浮点数)3.14float3.14浮点数直接对应
truetrueboolTruetrue → True
falsefalseboolFalsefalse → False
nullnullNoneTypeNonenull → None

        Python 到 JSON 的特殊类型处理

Python 数据类型默认 JSON 转换结果是否支持直接转换处理方法
tuple转换为 array✅ 支持(1, 2, 3) → [1, 2, 3]
set抛出 TypeError❌ 不支持需先转换为 list
frozenset抛出 TypeError❌ 不支持需先转换为 list
datetime抛出 TypeError❌ 不支持需自定义序列化
date抛出 TypeError❌ 不支持需自定义序列化
time抛出 TypeError❌ 不支持需自定义序列化
decimal.Decimal抛出 TypeError❌ 不支持需转换为 float 或 str
bytes抛出 TypeError❌ 不支持需编码为 base64 或 str
complex抛出 TypeError❌ 不支持需转换为 dict 或 str
range抛出 TypeError❌ 不支持需转换为 list
自定义类对象抛出 TypeError❌ 不支持需实现 __json__ 或自定义序列化

        JSON 到 Python 的转换细节

JSON 输入Python 输出数据类型注意事项
{"a": 1, "b": 2}{'a': 1, 'b': 2}dict键始终转换为字符串
[1, "text", true][1, 'text', True]list保持元素顺序
"unicode文本"'unicode文本'str支持 Unicode 字符
123456789012345123456789012345int支持大整数
1.23e-101.23e-10float科学计数法支持
true / falseTrue / Falsebool布尔值转换
nullNoneNoneType空值转换

        编码参数对转换的影响

json.dumps() 参数对 Python → JSON 转换的影响示例对比
ensure_ascii=True (默认)非ASCII字符被转义"中文" → "\u4e2d\u6587"
ensure_ascii=False非ASCII字符保持原样"中文" → "中文"
indent=None (默认)紧凑格式,无换行缩进单行输出
indent=2格式化输出,2空格缩进多行易读格式
sort_keys=False (默认)保持字典原有键顺序输入顺序保留
sort_keys=True按键名字典序排序稳定输出顺序
separators=(', ', ': ') (默认)标准分隔符{"a": 1, "b": 2}
separators=(',', ':')紧凑分隔符{"a":1,"b":2}

        json转python

        json对象转python分为以下两种

        

import jsonjson_str = '''{"user_profile": {"id": 12345,"username": "john_doe","full_name": "张三","age": 28,"is_active": true,"is_premium": false,"registration_date": "2023-05-15","last_login": null}
}'''rs = json.loads(json_str)
print(rs)
print(type(rs))
print(type(rs["user_profile"]))
#打开json文件转为python数据
with open('data.txt') as fppython_list =json.load(fp)print(python_list)print(type(python_list))print(type(python_list[0]))

        python转json

        转换形式类似于这样

import json
json_str = '''{"user_profile": {"id": 12345,"username": "john_doe","full_name": "张三","age": 28,"is_active": true,"is_premium": false,"registration_date": "2023-05-15","last_login": null}
}'''rs = json.loads(json_str)
print(rs)
#rs为python数据
#python转json
json_str= json.dumps(rs)
#默认为TRUE,这个状态下无法显示中文
print(json_str)
#默认为TRUE,这个状态下无法显示中文
# json_str= json.dumps(rs,ensure_ascii=True)
json_str= json.dumps(rs,ensure_ascii=False)
print(json_str)
#将构建对象写入文件
with open('data.txt','w') as fp:json_str=json.dumps(rs,fp,ensure_ascii=False)

项目测试:爬取图片

        以下代码为AI创作,仅供参考。

import requests
from bs4 import BeautifulSoup
import os
import time
from urllib.parse import urljoin, urlparse
import reclass ImageCrawler:"""图片爬虫类,用于从多个网页爬取图片并保存到本地"""def __init__(self, save_folder="downloaded_images"):"""初始化爬虫参数:save_folder: 图片保存的文件夹路径"""self.save_folder = save_folder# 设置请求头,模拟浏览器访问,避免被网站屏蔽self.headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'}# 创建会话对象,可以保持cookie和连接,提高效率self.session = requests.Session()self.session.headers.update(self.headers)# 创建保存文件夹,如果不存在则创建if not os.path.exists(self.save_folder):os.makedirs(self.save_folder)print(f"✅ 创建保存文件夹: {self.save_folder}")def download_image(self, img_url, filename=None):"""下载单张图片到本地参数:img_url: 图片的完整URL地址filename: 自定义文件名,如果为None则自动生成返回:(成功状态, 文件名或错误信息)"""try:# 如果没有提供文件名,从URL中提取文件名if not filename:parsed_url = urlparse(img_url)filename = os.path.basename(parsed_url.path)# 如果提取的文件名无效,使用时间戳生成唯一文件名if not filename or '.' not in filename:filename = f"image_{int(time.time())}.jpg"# 处理文件名,确保在文件夹中唯一,避免覆盖base_name, ext = os.path.splitext(filename)counter = 1final_filename = filenamesave_path = os.path.join(self.save_folder, final_filename)# 如果文件名已存在,添加数字后缀while os.path.exists(save_path):final_filename = f"{base_name}_{counter}{ext}"save_path = os.path.join(self.save_folder, final_filename)counter += 1# 发送请求下载图片print(f"⬇️  正在下载: {img_url}")response = self.session.get(img_url, timeout=10)response.raise_for_status()  # 检查请求是否成功# 将图片内容写入文件with open(save_path, 'wb') as f:f.write(response.content)return True, final_filenameexcept Exception as e:# 下载失败,返回错误信息return False, str(e)def crawl_page(self, url, max_images=50):"""爬取单个页面的所有图片参数:url: 要爬取的网页URLmax_images: 单页最大下载图片数量返回:成功下载的文件名列表"""try:print(f"🔍 正在解析页面: {url}")# 发送HTTP请求获取网页内容response = self.session.get(url, timeout=10)response.raise_for_status()  # 如果请求失败会抛出异常# 使用BeautifulSoup解析HTML内容soup = BeautifulSoup(response.text, 'html.parser')# 查找页面中所有的img标签img_tags = soup.find_all('img')print(f"📷 在页面中找到 {len(img_tags)} 个图片标签")downloaded_count = 0successful_downloads = []  # 记录成功下载的文件名# 遍历所有图片标签for img in img_tags:# 如果达到最大下载数量,停止处理if downloaded_count >= max_images:break# 获取图片URL,优先考虑src属性,其次是常见的懒加载属性img_url = img.get('src') or img.get('data-src') or img.get('data-original')if not img_url:continue  # 如果没有找到图片URL,跳过这个标签# 处理相对URL,将其转换为绝对URL# 例如: '/images/pic.jpg' -> 'https://example.com/images/pic.jpg'img_url = urljoin(url, img_url)# 检查URL是否为图片格式,过滤掉非图片链接if not self.is_image_url(img_url):continue# 下载图片success, result = self.download_image(img_url)if success:downloaded_count += 1successful_downloads.append(result)print(f"✅ 成功下载第 {downloaded_count} 张图片: {result}")else:print(f"❌ 下载失败: {result}")# 添加延迟,避免请求过于频繁被封IPtime.sleep(0.3)print(f"📊 页面爬取完成,成功下载 {downloaded_count} 张图片")return successful_downloadsexcept Exception as e:print(f"💥 页面爬取失败: {str(e)}")return []def crawl_multiple_pages(self, urls, max_images_per_page=20):"""批量爬取多个页面的图片参数:urls: 要爬取的URL列表max_images_per_page: 每个页面最大下载图片数量返回:所有成功下载的文件名列表"""all_downloads = []  # 存储所有下载成功的文件名# 遍历URL列表,enumerate用于同时获取索引和URLfor i, url in enumerate(urls, 1):print(f"\n{'='*50}")print(f"🌐 正在处理第 {i}/{len(urls)} 个页面: {url}")print(f"{'='*50}")# 爬取单个页面downloads = self.crawl_page(url, max_images_per_page)all_downloads.extend(downloads)  # 将结果添加到总列表中# 如果不是最后一个页面,添加页面间的延迟if i < len(urls):print("⏳ 页面间延迟中...")time.sleep(1)  # 页面间延迟,避免请求过于密集# 输出最终统计信息print(f"\n🎉 所有页面爬取完成!")print(f"📈 总计下载 {len(all_downloads)} 张图片")print(f"💾 图片保存在: {os.path.abspath(self.save_folder)}")return all_downloads@staticmethoddef is_image_url(url):"""静态方法:检查URL是否为图片链接参数:url: 要检查的URL返回:布尔值,True表示是图片URL"""# 定义常见的图片文件扩展名模式image_patterns = [r'\.jpg$',    # 匹配以.jpg结尾r'\.jpeg$',   # 匹配以.jpeg结尾  r'\.png$',    # 匹配以.png结尾r'\.gif$',    # 匹配以.gif结尾r'\.bmp$',    # 匹配以.bmp结尾r'\.webp$',   # 匹配以.webp结尾r'\.jpg\?',   # 匹配.jpg后带参数的情况r'\.jpeg\?',  # 匹配.jpeg后带参数的情况r'\.png\?',   # 匹配.png后带参数的情况r'\.gif\?',   # 匹配.gif后带参数的情况r'\.bmp\?',   # 匹配.bmp后带参数的情况r'\.webp\?'   # 匹配.webp后带参数的情况]# 检查URL是否匹配任何图片模式,re.I表示忽略大小写return any(re.search(pattern, url, re.I) for pattern in image_patterns)# 使用示例和演示
if __name__ == "__main__":"""主程序入口,演示如何使用ImageCrawler类"""# 创建爬虫实例,指定图片保存文件夹crawler = ImageCrawler("my_downloaded_images")# 定义要爬取的页面URL列表# 注意:请将这些示例URL替换为实际要爬取的网站urls_to_crawl = ["https://example.com/page1",  # 替换为实际URL"https://example.com/page2",  # 替换为实际URL  "https://example.com/page3"   # 替换为实际URL]# 开始批量爬取# 参数1: URL列表# 参数2: 每个页面最多下载15张图片downloaded_files = crawler.crawl_multiple_pages(urls_to_crawl, max_images_per_page=15)# 打印下载结果摘要if downloaded_files:print(f"\n📋 下载文件列表:")for file in downloaded_files:print(f"   📄 {file}")else:print("\n⚠️  没有成功下载任何图片")

        本期内容就到这里了,喜欢请点个赞谢谢

封面图自取:

http://www.dtcms.com/a/471170.html

相关文章:

  • 如何使用Prosys OPC UA SDK for Java在 Android 上开发 OPC UA 应用程序?
  • 网站制作软件排行榜网站开发结构有
  • 重庆公司网站建设步骤优化大师有必要安装吗
  • 医院网站建设报价网站更换ip地址
  • 大学网站建设的目标与思路珍爱网建设网站的目的
  • 网站规划的注意事项网络推广网站首页大图
  • 陕西省住房和城乡建设部网站官网建晨网站建设
  • 核辐射检测仪中的抗辐照MCU芯片应用探索与挑战应对
  • 无人机中继通信链路技术要点分析
  • 2025年ASOC SCI2区TOP,基于两种平衡机制的异构无人机群路径规划多目标进化算法,深度解析+性能实测,深度解析+性能实测
  • STM32CubeMX + HAL 库:定时器输入捕获的应用,PWM波的占空比(频率/周期)测量
  • 【解决】OSError: We couldn‘t connect to ‘https://huggingface.co‘ to load this file
  • 湖北营销网站建设联系方式装修估价网
  • 数据库系列之:SQL Server 事务日志
  • UE5 在运行状态下,可以显示出移动,旋转,缩放轴的功能基础上,新增框选,以及打组解组和从组中单独移除某一个actor的功能
  • 凡科网做网站教程家居装修设计平台
  • 网站后台页面进不去做外贸的有些什么网站
  • 学校网站功能python购物网站开发流程
  • 大数据成矿预测系列(四) | 成矿预测的“主力军”:随机森林与支持向量机深度解析
  • 企业网站优化费用iis 网站后台
  • 工业可视化监控平台GENESIS64核心能力与架构解析
  • 网站建设公司位置广东做网站的公司有哪些
  • 石家庄科技网站建设ppt制作平台
  • 如何自建网站做淘客常州网站专业制作
  • 纯分享!2026届计算机毕业设计选题全攻略(选题+技术栈+创新点+避坑),这80个题目覆盖所有方向,计算机毕设选题大全收藏
  • 网安面试题收集(2)
  • 西宁建设网站运维兼职平台
  • Java--网络编程(一)
  • 购物网站建设教程中国十大网站建设公司排名
  • web后端开发——原理