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

Python 爬虫项目实战:正则表达式筛选网页数字与标题字段

前言

在爬虫数据解析体系中,BeautifulSoup、XPath 依托 DOM 树形结构完成内容定位,二者高度依赖 HTML 标签完整性,一旦网页标签被混淆嵌套、前端页面采用无规范碎片化代码排版,DOM 解析方案会出现大范围解析失效。正则表达式基于文本字符串的规律匹配逻辑,脱离标签层级束缚,依靠字符排布特征完成标题、数值类字段的精准捕获,在混杂脚本、破碎标签的网页环境中具备不可替代的适配能力。数字与标题是网页最普遍的结构化字段,标题拥有固定首尾字符边界,价格、浏览量、排名、发布年份等数字字段具备阿拉伯数字、小数、正负值等统一字符特征,二者恰好是正则爬虫最典型的落地场景。

本文从正则底层匹配原理、元字符语法分类、Python 内置 re 库 API、标题模糊捕获、多格式数字筛选、脏数据剔除、本地文件存储全链路展开实战教学,串联前文 requests 网页源码获取逻辑,构建「请求获取源码 + 正则规则匹配 + 字段清洗 + 落地存储」完整爬虫工程。

本文涉及依赖官方参考链接:

  1. Python re 模块官方文档:Python 内置正则库原生 API 说明
  2. requests 官方文档:HTTP 请求依赖库文档
  3. PyPI-requests:安装包资源地址

一、环境配置与 re 模块基础概述

1.1 环境依赖说明

re 属于 Python 标准内置库,随 Python 解释器原生安装,无需额外 pip 安装,仅需保留 requests 用于网页源码拉取,若此前未安装 requests,执行安装命令:

bash

运行

pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple

通过import re导入即可调用全部正则接口,是爬虫成本最低的解析组件。

1.2 正则爬虫适用与受限场景

正则依靠文本字符规律匹配,在两类场景优先级高于 DOM 解析工具:

  1. 网页 HTML 标签残缺严重、标签被 JS 碎片化拼接,BS 与 XPath 无法构建完整 DOM 树;
  2. 仅需提取零散数字、短标题等碎片化字段,完整构建 DOM 树资源开销过大。

受限场景:页面字段排布无统一字符规律、字段穿插随机无规则符号,正则编写成本会远超标签解析。

二、正则核心元字符与匹配规则汇总

元字符是正则表达式的语法基础,不同符号对应不同字符匹配逻辑,爬虫抓取标题、数字高频元字符整理如下表:

表格

元字符功能释义爬虫使用场景
.匹配除换行符之外任意单个字符标题中间不定长度文本匹配
*匹配前一个字符出现 0 次或无限次字段首尾冗余字符不定长内容
+匹配前一个字符出现 1 次或无限次连续数字、连续标题文本捕获
?非贪婪匹配,尽可能少抓取字符限定标题终止边界,避免跨字段抓取
\d匹配任意阿拉伯数字 0~9浏览量、价格、排名、年份等数字提取
\D匹配非数字字符剔除混杂在数字中的中文、符号
()分组捕获,括号内内容单独提取精准取出目标标题、目标数字
[]字符集,匹配括号内任意单个字符匹配中英文标点、特殊分隔符号
``或逻辑,匹配左右任意一种表达式兼容两种格式标题与数字写法
\s匹配空白字符(空格、换行、制表符)清洗标题字段多余空白占位符

2.1 贪婪与非贪婪匹配核心原理

爬虫开发中非贪婪匹配是标题提取关键,默认.*为贪婪匹配,会从第一个起始标识抓取至页面最后一个结束标识,造成跨内容抓取;.*?非贪婪匹配,匹配到首个结束标识即终止抓取。

python

运行

import re html = '<h3>星际宇宙科普</h3><h3>深海生物探秘</h3>' # 贪婪匹配 res_greed = re.findall(r'<h3>(.*)</h3>',html) # 非贪婪匹配 res_nogreed = re.findall(r'<h3>(.*?)</h3>',html) print("贪婪结果:",res_greed) print("非贪婪结果:",res_nogreed)
代码原理剖析
  1. 贪婪表达式仅返回一条数据,将两个标题合并为单字符串,匹配逻辑失效;
  2. .*?非贪婪逐个闭合标签,逐条拆分两条标题,是标题正则标准写法。

三、re 库四大核心爬虫方法详解

Python re 模块提供四类高频接口,分别适配单次匹配、批量全量匹配、内容替换、预编译规则,对应不同爬虫字段提取需求:

表格

方法名返回数据使用场景
re.search()单个匹配对象,匹配首个符合规则内容单标题、单数值定点提取
re.findall()列表格式,所有匹配分组内容批量提取全页标题、批量数字,爬虫最常用
re.sub()替换完成后的完整字符串标题字段脏符号、冗余标签清洗
re.compile()正则规则编译对象重复调用同一规则,海量页面抓取优化效率

3.1 re.findall 分组捕获实战(标题提取基础)

findall 遇到表达式内()分组时,仅返回分组内部捕获内容,外围匹配规则仅做边界限定,是爬虫精准提取字段的核心机制:

python

运行

import re raw_html = ''' <div class="news"> <span class="title">【天文科普】银河系星云演化规律</span><span>浏览:1256</span> <span class="title">【地理科普】板块漂移学说详解</span><span>浏览:3689</span> </div> ''' # 括号分组捕获标题正文,前后标签作为匹配边界 pattern = r'<span class="title">(.*?)</span>' title_list = re.findall(pattern,raw_html) print("批量提取标题:",title_list)
代码原理剖析

表达式外层<span class="title"></span>用于锁定标题起止边界,(.*?)分组单独存储标题文本,findall 自动过滤边界标签,仅输出分组内数据。

3.2 re.compile 预编译优化

同一正则规则循环多页面抓取时,compile 提前编译正则表达式,避免循环内重复编译消耗算力:

python

运行

import re # 预编译正则规则 title_pat = re.compile(r'<span class="title">(.*?)</span>') html_list = [raw_html,raw_html,raw_html] all_title = [] for html in html_list: all_title.extend(title_pat.findall(html))
原理剖析

compile 将正则字符串转为编译对象,循环调用直接复用编译结果,海量分页爬虫场景有效缩短解析耗时。

3.3 re.sub 脏数据清洗

网页标题常混杂多余 HTML 标签、特殊符号,sub 方法实现字符替换清洗:

python

运行

raw_title = "<b>【生物科普】&nbsp;昆虫变态发育全解析</b>" # 清除所有标签与空格占位符 clean_title = re.sub(r'<.*?>|&nbsp;','',raw_title) print(clean_title)

四、分场景实战一:各类标题字段正则筛选

网页标题分为带固定前后缀标题、无固定标签零散标题两种场景,分别对应两套正则方案。

4.1 带固定首尾标签的标题批量抓取

沿用 requests 获取在线页面源码,结合正则批量提取栏目标题:

python

运行

import requests,re HEADERS = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0 Safari/537.36"} def get_page_html(url): try: resp = requests.get(url,headers=HEADERS,timeout=5) resp.encoding = resp.apparent_encoding return resp.text except: return "" def extract_title(html): # 预编译标题正则 pat = re.compile(r'<h2 class="art_title">(.*?)</h2>') title_arr = pat.findall(html) # 标题基础清洗 clean_arr = [re.sub(r'\s+','',i) for i in title_arr] return clean_arr if __name__ == "__main__": page_html = get_page_html("https://demo-kepu.com/list") res_title = extract_title(page_html) print("提取有效标题数量:",len(res_title))
代码原理剖析
  1. re.sub(r'\s+','',i)统一清除标题内部各类空白字符,标准化标题格式;
  2. 函数拆分请求与解析逻辑,代码解耦,便于后续批量分页调用。

4.2 无固定标签、依靠关键词边界的标题捕获

部分页面标题无统一包裹标签,仅统一带有【科普】关键词前缀,依靠关键词做匹配边界:

python

运行

raw_text = "随机文本111【科普】火山喷发的地质成因随机字符222【科普】极地冰川融化研究多余符号" pat = r'【科普】(.*?)随机' title_list = re.findall(pat,raw_text)

五、分场景实战二:多格式数字正则筛选

网页数字分为整数(浏览量、评论数)、小数(评分、价格)、带单位混合数字(589 次、9.6 分)三类,分规格编写正则表达式。

5.1 纯整数提取(浏览量、点击量)

使用\d+匹配连续多位阿拉伯数字,适用于全整数类字段:

python

运行

import re content = "文章1浏览3562次,文章2浏览1289次,文章3浏览96次" num_list = re.findall(r'(\d+)',content) # 字符串转数字 num_int = [int(x) for x in num_list] print(num_int)

5.2 小数 + 整数混合提取(科普文章评分)

正则\d+\.?\d*兼容整数、一位小数、多位小数三种格式,适配评分字段:

python

运行

score_text = "文章评分:9.5、8、9.75、7.2" score_list = re.findall(r'(\d+\.?\d*)',score_text)

5.3 带中文单位的数字剥离

数字和汉字绑定(325 阅读、12.9 元),分组单独取出数字部分:

python

运行

unit_str = "325阅读量,9.8分评分,68收藏" num_pat = re.findall(r'(\d+\.?\d+)[阅读收藏分]',unit_str)

5.4 标题 + 数字联动提取(单条数据封装)

页面单条目同时包含标题与对应浏览数字,一条正则双分组同步抓取两个字段:

python

运行

html_frag = ''' <p>宇宙星云探究 | 阅读:1563</p> <p>热带雨林生态 | 阅读:2891</p> ''' # 第一分组标题,第二分组浏览数字 res = re.findall(r'<p>(.*?)\|阅读:(\d+)</p>',html_frag) data_dict = [{"标题":k,"浏览量":int(v)} for k,v in res] print(data_dict)
原理剖析

正则设置两组()分组,findall 会以元组形式返回每组捕获内容,一键完成标题、数字配对,省去二次字段关联操作。

六、完整项目:正则爬虫全流程(请求 - 正则提取 - 清洗 - TXT/CSV 存储)

整合全模块,实现从网页拉取、标题 + 数字联合提取、脏数据清洗、本地双格式存储一体化项目代码:

python

运行

import requests,re,csv HEADERS = { "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36" } # 1.网页请求函数 def fetch_html(url): try: res = requests.get(url,headers=HEADERS,timeout=6) res.encoding = res.apparent_encoding return res.text except Exception as e: print(f"请求异常:{e}") return "" # 2.正则提取+数据清洗函数 def parse_by_re(html): # 预编译正则:同时捕获标题、阅读数字 rule = re.compile(r'<div class="item_title">(.*?)</div>.*?阅读:(\d+)',re.S) raw_data = rule.findall(html) clean_data = [] for title,view in raw_data: # 清洗标题:剔除标签、空白、特殊符号 clear_title = re.sub(r'<.*?>|\s|&nbsp;','',title).strip() view_num = int(view) clean_data.append({"文章标题":clear_title,"浏览数量":view_num}) return clean_data # 3.数据存储函数 def save_data(data_list): # CSV结构化存储 with open("科普标题数字汇总.csv","w",encoding="utf-8-sig",newline="") as f_csv: writer = csv.DictWriter(f_csv,fieldnames=["文章标题","浏览数量"]) writer.writeheader() writer.writerows(data_list) # TXT备份存储 with open("科普数据备份.txt","w",encoding="utf-8") as f_txt: f_txt.write("文章标题|浏览数量\n"+"-"*50+"\n") for item in data_list: f_txt.write(f"{item['文章标题']}|{item['浏览数量']}\n") print("数据已保存至本地CSV与TXT文件") # 主程序入口 if __name__ == "__main__": target_url = "https://demo-kepu.com/regex_list" page_html = fetch_html(target_url) final_data = parse_by_re(page_html) save_data(final_data) print(f"本次采集有效数据条数:{len(final_data)}")
代码原理剖析
  1. re.S参数使.符号匹配换行符,适配标题跨换行排布的页面;
  2. 分函数模块化开发,请求、解析、存储相互独立,便于后续扩展分页循环;
  3. 标题使用多级替换规则,一次性剔除 HTML 标签、空格、占位符三类脏数据。

七、分页批量正则爬虫拓展实现

多数资讯站点分页展示数据,通过页码参数循环请求,批量全栏目采集:

python

运行

import time def crawl_multi_page(start,end,base_url): all_info = [] for page in range(start,end+1): real_url = base_url.format(page=page) print(f"正在抓取第{page}页:{real_url}") html = fetch_html(real_url) page_data = parse_by_re(html) if not page_data: print("当前页面无数据,终止分页抓取") break all_info.extend(page_data) time.sleep(1) save_data(all_info) print(f"全部分页抓取完成,累计采集{len(all_info)}条数据") # 调用 if __name__ == "__main__": base = "https://demo-kepu.com/regex?page={page}" crawl_multi_page(1,4,base)

八、正则爬虫高频异常与排错方案

表格

异常问题形成原因处理方案
匹配结果为空列表正则边界写错、贪婪匹配、页面源码编码错乱切换非贪婪.*?、核对前后匹配标识、使用 apparent_encoding 修正编码
字段混入多余符号页面标题内嵌随机特殊字符re.sub 批量替换指定无用字符
数字无法转 int提取的数字混杂中文符号优化正则,仅分组捕获纯数字内容
跨条目抓取多条内容未使用非贪婪匹配全部标题正则统一替换.为.?

九、正则、BS、XPath 三种解析技术选型对比

结合标题与数字抓取场景做选型参考:

表格

解析方式开发难度解析速度适用场景
正则中等,需要熟记元字符最快,纯文本检索标签破碎、零散数字标题提取
BeautifulSoup简单,语法贴近 Python中等标签规整,少量字段抓取
XPath中等,路径语法记忆较快标签规范,大批量列表结构化数据

十、本章节总结与下一章节预告

10.1 本章核心知识点总结

  1. 正则核心元字符含义、贪婪 / 非贪婪匹配区别与爬虫使用规范;
  2. re 四大常用函数 findall/search/sub/compile 的工程落地用法,分组捕获是字段提取关键;
  3. 标题、整数、小数、带单位数字四类场景正则编写思路;
  4. 正则爬虫全链路封装、分页批量采集与本地文件存储实现。

10.2 下一章节内容预告

下一章节进入 urllib 请求封装与网页编码异常处理,梳理 Python 原生 urllib 标准库架构,对比 requests 与 urllib 底层差异,系统化解决网页 gbk、gb2312、utf-8 多编码乱码、请求头封装、异常捕获等底层问题,补齐 Python 爬虫原生请求技术栈。

http://www.gsyq.cn/news/1476085.html

相关文章:

  • 新手入门指南:在快马平台上从零开始打造你的第一个xbox网页播放器
  • Digital:如何用这款免费开源工具轻松掌握数字电路设计?
  • 不用出门,一键预约!北京丰宝斋天津上门回收,变现更轻松 - 深鉴新闻
  • 连接 连接池完整详解(以数据库连接最常用,Redis/MQ 同理)
  • LabelImg安装后打不开?别慌!5个常见报错排查与修复指南(Windows/Mac)
  • 实战演练:基于快马平台生成可交互的qclow官网全栈项目
  • 从课程作业到项目实战:如何用面向对象思想设计你的连杆机构仿真库(Python版)
  • 探索数据自主管理新维度:重构个人数字记忆的完整方案
  • 构建安全通信的基石:RSA-Library 加密库深度解析
  • 零成本解锁WeMod Pro:开源增强工具全面指南
  • 模板驱动型文档自动化:零代码实现动态填充与品牌合规
  • Java 分布式事务详解:4 大类主流方案(原理、执行流程、优缺点、使用场景、区别对比)
  • 经常寄快递怎么省钱 - 快递物流资讯
  • Inkscape光学设计插件:在矢量绘图中实现专业级光线追踪
  • 51单片机双机串口通信实战套件:带LCD实时状态显示、矩阵键盘交互、C#上位机监控与Proteus一键仿真
  • 3个技巧彻底解决Windows字体限制问题:No!! MeiryoUI零基础5分钟快速上手指南
  • Django搭建的流浪猫狗救助与领养全流程管理后台(含数据库和部署配置)
  • MIFARE Classic Tool终极指南:如何用Android手机轻松管理你的NFC门禁卡
  • LeetCode 337:打家劫舍 III(House Robber III)—— 题解 ✅
  • Python基础:字符串索引与切片操作完全指南
  • 昇腾CANN集群通信库hcomm:多机分布式训练的NCCL兼容通信方案
  • 【限时可复刻】CSDN AI+内容裂变+线索评分三步法:让咨询量暴涨210%的招生闭环(附配置参数表)
  • VidDown:免费视频解析下载 + 开发工具箱
  • 从零构建51单片机最小系统:原理、设计与调试全攻略
  • 从兼职工程师到行业认知:电源设计、3C认证与MCU选型的实战教训
  • 冷门技术内容冷启动难?用CSDN AI做选题挖掘,3步锁定高转化低竞争蓝海选题,错过再等半年!
  • SysDVR技术深度解析:Switch游戏实时串流架构设计与应用实战
  • 纯亚克力浴缸专业公司
  • CANopen协议实战指南:从总线原理到工程调试全解析
  • 智能时代工程师如何应对技术迭代与信息茧房挑战