Python提取数字的3种实用方法
还在为Python正则提取数字而烦恼吗?本文为你提供3种高效方法,轻松搞定文本中的数字提取!利用Python的`re`模块和正则表达式,你可以精确地从各种复杂文本中提取整数、浮点数、带符号数字,甚至是带有单位或特定格式的数字。文章详细讲解了如何使用`re.findall()`和`re.search()`函数,配合灵活的正则表达式模式,例如`r'[-+]?\d+(?:.\d+)?'`,捕获并提取所需数字部分,并将其转换为数值类型进行后续处理。无论你是需要提取订单号、价格、数量,还是日期中的数字信息,本文都能为你提供实用的解决方案和技巧,助你提升数据处理效率。
使用re模块结合正则表达式可精确提取文本中的整数、浮点数、负数及带符号或单位的数字,通过r'[-+]?\d+(?:.\d+)?'等模式匹配,并用findall或search配合捕获组提取所需部分,再转换为数值类型进行处理。

在Python里,要从文本中抓取数字,最直接、也最灵活的工具就是re模块,也就是正则表达式。它能帮你根据预设的模式,把字符串里所有符合条件的数字都找出来。这比你手动去遍历字符串、判断每个字符是不是数字要高效和优雅得多,尤其是在处理复杂文本时。
解决方案
使用Python的re模块提取数字,通常我们会用到re.findall()函数。这个函数会返回一个列表,包含所有匹配到的非重叠字符串。
最基础的数字模式是\d+,它能匹配一个或多个数字字符(0-9)。但实际情况往往更复杂,数字可能包含小数点、正负号,或者混杂在其他文本中。
import re
text1 = "我有100个苹果和20.5公斤的香蕉,还有-5个坏梨。"
text2 = "订单号是123456789,总价为999.99元。"
text3 = "我的身高是175cm,体重是68.3kg。"
# 1. 提取整数
# 模式:\d+ 匹配一个或多个数字
integers = re.findall(r'\d+', text1)
print(f"提取整数 (text1): {integers}") # ['100', '20', '5'] - 注意这里会把20.5的20和5分开
# 2. 提取浮点数和整数(更通用的数字模式)
# 模式:\d+\.\d* 或者 \d*\.\d+ 或者更通用的 \d+\.?\d*
# 考虑到数字可能带小数点,我们用 \d+\.?\d* 来匹配,它会匹配至少一个数字,
# 后面可选地跟着一个小数点,再后面可选地跟着零个或多个数字。
# 这样可以匹配 "100", "20.5", "5." (虽然实际中"5."不常见,但模式会匹配)
numbers_general = re.findall(r'\d+\.?\d*', text1)
print(f"提取通用数字 (text1): {numbers_general}") # ['100', '20.5', '5']
# 3. 提取带正负号的数字
# 模式:[-+]?\d+\.?\d* 匹配可选的正负号,然后是通用数字模式
signed_numbers = re.findall(r'[-+]?\d+\.?\d*', text1)
print(f"提取带符号数字 (text1): {signed_numbers}") # ['100', '20.5', '-5']
# 4. 结合实际场景,提取特定格式的数字
# 比如从"订单号是123456789"中提取订单号
order_id_match = re.search(r'订单号是(\d+)', text2)
if order_id_match:
print(f"提取订单号 (text2): {order_id_match.group(1)}") # group(1) 获取括号内的内容
# 5. 提取带有单位的数字,但只保留数字部分
# 比如从"175cm"中提取175
height_match = re.search(r'(\d+\.?\d*)cm', text3)
if height_match:
print(f"提取身高数字 (text3): {height_match.group(1)}") # '175'说实话,正则表达式这东西,初看会觉得有点像天书,但一旦你掌握了几个核心元字符和量词,它在文本处理上的能力会让你大呼过瘾。上面这些模式,基本能覆盖你日常提取数字的大部分需求了。
如何在复杂文本中精确提取各类数字,包括整数、浮点数和负数?
在真实世界的文本里,数字的形态是多种多样的,比如可能夹杂着单位,或者用逗号做千位分隔符。要精确提取,我们就得构建更精细的正则表达式。这就像给一个模糊的目标画出清晰的轮廓。
一个比较全面的数字匹配模式,可以考虑以下几点:
- 正负号: 数字前面可能有
+或-。用[-+]?来匹配可选的正负号。 - 整数部分: 至少一个数字。
\d+。 - 小数部分: 小数点是可选的,后面可以跟零个或多个数字。
\.?\d*。 - 组合: 将上述部分组合起来,得到
[-+]?\d+\.?\d*。这个模式能捕获像 "123", "12.3", "-45", "+6.78" 这样的数字。
但如果你想更严谨地匹配浮点数,比如确保小数点后有数字,或者小数点前有数字,可以调整为:
[-+]?\d+\.\d+: 匹配 "12.3", "-4.5",但不匹配 "12" 或 "0.5"。[-+]?(?:\d+\.\d*|\d*\.\d+): 匹配 "12.3", "0.5", "12." (如果允许),但不匹配 "12"。- 我个人更倾向于使用
[-+]?\d+(?:\.\d+)?。这个模式是说:可选的正负号,接着至少一个数字,然后是一个非捕获组(?:\.\d+)?,这个组表示可选地匹配一个小数点和至少一个数字。这样既能匹配整数,也能匹配像 "12.3" 这样的浮点数,而且不会匹配单独的 "." 或者 "12." 这种可能不是你想要的浮点数。
import re
complex_text = "今天的气温是-5.5℃,昨天下雨量是20mm,预计明天股价上涨1.23%,订单总额达到1,234,567.89元。"
# 提取所有看起来像数字的字符串
# 使用我偏好的模式:可选正负号,至少一个数字,可选的小数点和至少一个数字
all_numbers_str = re.findall(r'[-+]?\d+(?:\.\d+)?', complex_text)
print(f"从复杂文本中提取的数字字符串: {all_numbers_str}")
# 输出: ['-5.5', '20', '1.23', '1', '234', '567.89']
# 注意:这里会把 "1,234,567.89" 拆分成 "1", "234", "567.89"
# 如果要处理千位分隔符,模式需要更复杂一些
# 匹配可能带逗号的整数或浮点数
# 这里我用一个稍微激进的模式:允许数字之间有逗号,但逗号后必须跟三位数字
# 并且整个数字可以有可选的小数部分
numbers_with_commas = re.findall(r'[-+]?\d{1,3}(?:,\d{3})*(?:\.\d+)?', complex_text)
print(f"处理千位分隔符后的数字字符串: {numbers_with_commas}")
# 输出: ['-5.5', '20', '1.23', '1,234,567.89']
# 这个模式就精确多了,成功地将 "1,234,567.89" 作为一个整体提取出来。
# 这种精细化的匹配,需要你对可能出现的数字格式有清晰的预期。
# 比如,如果数字后面总是跟着单位,而你只想要数字,可以用捕获组:
temperature_match = re.search(r'([-+]?\d+(?:\.\d+)?)℃', complex_text)
if temperature_match:
print(f"提取气温数字: {temperature_match.group(1)}") # '-5.5'这里面的关键在于?(0次或1次)、+(1次或多次)、*(0次或多次)这些量词,以及()捕获组和(?:)非捕获组的灵活运用。构建正确的模式,就像是给你的文本数据量身定制一把钥匙。
提取到的数字是字符串,如何将其转换为数值类型进行后续处理?
re.findall()返回的,或者match.group()捕获到的,都是字符串类型。这很合理,因为正则表达式本身就是处理字符串的。但我们通常提取数字是为了进行计算、比较或者其他数值操作,所以下一步往往就是把它们转换成int(整数)或float(浮点数)。
这个转换过程相对直观,Python提供了内置的int()和float()函数。不过,有几个小细节值得注意:
- 类型选择: 如果你的数字可能包含小数,那就用
float()。如果确定都是整数,用int()会更合适。 - 错误处理: 虽然你的正则表达式应该已经过滤掉了非数字字符,但万一有意外,比如匹配到了一个空字符串或者一个不完全的数字,
int()或float()转换时可能会抛出ValueError。在实际项目中,你可能需要用try-except块来处理这种情况,或者确保你的正则表达式足够健壮。 - 批量转换: 如果
re.findall()返回了一个数字字符串列表,你可以用列表推导式(list comprehension)或者map()函数来高效地批量转换。
import re
text = "价格是100元,折扣后是85.5折,会员价-10元。库存量:500000。"
# 提取所有可能带符号的浮点数或整数
# 这里我们用一个比较通用的模式,能抓取到大部分我们想要的数字形态
# 考虑到可能有千位分隔符,我们先不直接处理,在转换时再去除
numbers_as_strings = re.findall(r'[-+]?\d+(?:,\d{3})*(?:\.\d+)?', text)
print(f"原始提取的数字字符串: {numbers_as_strings}")
# 输出: ['100', '85.5', '-10', '500,000']
# 转换为数值类型
converted_numbers = []
for num_str in numbers_as_strings:
# 在转换前,先去除千位分隔符,否则float()或int()会报错
cleaned_num_str = num_str.replace(',', '')
try:
if '.' in cleaned_num_str:
converted_numbers.append(float(cleaned_num_str))
else:
converted_numbers.append(int(cleaned_num_str))
except ValueError:
print(f"警告: 无法将 '{num_str}' 转换为数值类型,已跳过。")
# 实际项目中,你可能需要更复杂的错误处理逻辑
print(f"转换后的数值列表: {converted_numbers}")
# 输出: [100, 85.5, -10, 500000]
# 使用列表推导式和map()的简洁方式
# 假设我们已经确保了字符串都是干净的数字(无逗号)
cleaned_numbers_str = [s.replace(',', '') for s in numbers_as_strings]
float_numbers = [float(s) for s in cleaned_numbers_str if '.' in s]
int_numbers = [int(s) for s in cleaned_numbers_str if '.' not in s]
print(f"浮点数列表 (通过推导式): {float_numbers}")
print(f"整数列表 (通过推导式): {int_numbers}")
# 如果你知道所有数字都可能是浮点数,直接用map
all_as_floats = list(map(float, cleaned_numbers_str))
print(f"所有数字转换为浮点数 (通过map): {all_as_floats}")这块的重点是replace(',', '')这一步,它是在将字符串转换为数值类型前,处理掉那些可能导致转换失败的非数字字符(比如千位分隔符)。这体现了数据清洗在数据处理流程中的重要性。
面对特殊场景,如带有单位或特定分隔符的数字,正则表达式还能胜任吗?
当然可以,而且这正是正则表达式的强项之一。当数字和单位、特定的前缀或后缀、或者非标准分隔符混在一起时,我们可以通过更精巧的模式来“雕刻”出我们真正想要的数字。这就像在沙子里淘金,需要更细密的筛子。
关键在于使用捕获组 ()。捕获组允许你从整个匹配结果中,只提取模式中特定部分的内容。
import re
special_text = "订单号:XYZ-12345, 金额: $99.99, 生产日期: 2023-10-26, 数量: 100件, 编码: #A-B-C-42."
# 1. 提取订单号中的数字部分 (例如 XYZ-12345 中的 12345)
# 模式:XYZ-后面跟着数字
order_id_match = re.search(r'XYZ-(\d+)', special_text)
if order_id_match:
print(f"订单号数字: {order_id_match.group(1)}") # '12345'
# 2. 提取带货币符号的金额 (例如 $99.99)
# 模式:$后面跟着一个数字模式
amount_match = re.search(r'\$(\d+(?:\.\d+)?)', special_text)
if amount_match:
print(f"金额: {amount_match.group(1)}") # '99.99'
# 3. 提取带有单位的数字 (例如 100件)
# 模式:数字后面跟着单位
quantity_match = re.search(r'(\d+)件', special_text)
if quantity_match:
print(f"数量: {quantity_match.group(1)}") # '100'
# 4. 提取日期中的年份、月份、日期
# 模式:(\d{4})-(\d{2})-(\d{2}) 分别捕获年、月、日
date_match = re.search(r'(\d{4})-(\d{2})-(\d{2})', special_text)
if date_match:
year, month, day = date_match.groups() # groups()返回所有捕获组的元组
print(f"生产日期: 年={year}, 月={month}, 日={day}") # 年=2023, 月=10, 日=26
# 5. 从混合编码中提取最后一个数字 (例如 #A-B-C-42 中的 42)
# 模式:匹配一个非数字或连字符的字符,直到最后一个连字符后跟着数字
code_number_match = re.search(r'-(\d+)$', special_text) # $表示字符串结尾
if code_number_match:
print(f"编码中的数字: {code_number_match.group(1)}") # '42'
# 更复杂的例子:提取所有括号内的数字
text_with_parentheses = "项目A (ID: 123), 项目B (ID: 456), 错误码 (Err: 789)."
numbers_in_parentheses = re.findall(r'\((?:ID|Err):\s*(\d+)\)', text_with_parentheses)
print(f"括号内ID/Err数字: {numbers_in_parentheses}") # ['123', '456', '789']这里面,re.search()和re.findall()的选择也很关键。re.search()只找第一个匹配项,通常用于提取特定格式的唯一信息;而re.findall()则会找出所有非重叠的匹配项,适用于你需要批量提取同类信息的情况。当你的模式中包含捕获组时,re.findall()会直接返回捕获组的内容列表,而不是整个匹配项。这在使用上非常方便。
总的来说,正则表达式在Python中处理数字提取,就像一把瑞士军刀,功能多且强大。关键在于理解你的数据形态,然后构建出恰到好处的模式。多实践,多尝试,你会发现它的乐趣。
今天关于《Python提取数字的3种实用方法》的内容介绍就到此结束,如果有什么疑问或者建议,可以在golang学习网公众号下多多回复交流;文中若有不正之处,也希望回复留言以告知!
高德地图查高速出口技巧分享
- 上一篇
- 高德地图查高速出口技巧分享
- 下一篇
- Windows8卸载预装应用教程
-
- 文章 · python教程 | 6小时前 |
- Python语言入门与基础解析
- 296浏览 收藏
-
- 文章 · python教程 | 6小时前 |
- PyMongo导入CSV:类型转换技巧详解
- 351浏览 收藏
-
- 文章 · python教程 | 6小时前 |
- Python列表优势与实用技巧
- 157浏览 收藏
-
- 文章 · python教程 | 7小时前 |
- Pandas修改首行数据技巧分享
- 485浏览 收藏
-
- 文章 · python教程 | 8小时前 |
- Python列表创建技巧全解析
- 283浏览 收藏
-
- 文章 · python教程 | 9小时前 |
- Python计算文件实际占用空间技巧
- 349浏览 收藏
-
- 文章 · python教程 | 10小时前 |
- OpenCV中OCR技术应用详解
- 204浏览 收藏
-
- 文章 · python教程 | 11小时前 |
- Pandas读取Django表格:协议关键作用
- 401浏览 收藏
-
- 文章 · python教程 | 11小时前 | 身份验证 断点续传 requests库 PythonAPI下载 urllib库
- Python调用API下载文件方法
- 227浏览 收藏
-
- 文章 · python教程 | 11小时前 |
- Windows7安装RtMidi失败解决办法
- 400浏览 收藏
-
- 文章 · python教程 | 11小时前 |
- Python异步任务优化技巧分享
- 327浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- ChatExcel酷表
- ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
- 3182次使用
-
- Any绘本
- 探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
- 3393次使用
-
- 可赞AI
- 可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
- 3424次使用
-
- 星月写作
- 星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
- 4528次使用
-
- MagicLight
- MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
- 3802次使用
-
- Flask框架安装技巧:让你的开发更高效
- 2024-01-03 501浏览
-
- Django框架中的并发处理技巧
- 2024-01-22 501浏览
-
- 提升Python包下载速度的方法——正确配置pip的国内源
- 2024-01-17 501浏览
-
- Python与C++:哪个编程语言更适合初学者?
- 2024-03-25 501浏览
-
- 品牌建设技巧
- 2024-04-06 501浏览

