Python 爬虫项目:健身课程与场馆数据爬取

发布时间:2026/6/12 22:06:07

Python 爬虫项目:健身课程与场馆数据爬取 前言全民健身理念持续普及线上健身服务平台、本地生活门户汇聚了海量健身场馆、课程类型、教练信息、收费标准、用户评价等数据资源。这类数据是健身行业市场调研、场馆竞品分析、用户选课参考、线上健身平台内容搭建的核心支撑素材。传统人工整理信息的方式效率低下无法完成多区域、多品类场馆与课程数据的批量汇总也难以实现数据定期更新。依托 Python 开发定向爬虫程序可自动化完成网页请求、节点解析、多维度数据提取、格式清洗与文件存储高效实现健身行业公开数据的规模化采集。本文围绕健身场馆与课程数据采集场景开展全流程实战开发依次完成环境部署、网页结构分析、模块化代码编写、运行原理解读、异常处理、数据优化、问题排查等内容。项目所使用的开发工具、第三方库及官方文档链接整理如下 Python 官方下载地址、requests 库官方文档、BeautifulSoup4 官方文档、lxml 解析库下载与文档、csv 模块官方说明、time 模块官方文档、re 正则表达式模块文档。本项目基于静态网页爬虫技术实现采用模块化编码思路逻辑分层清晰同时融入数据正则清洗、多级页面采集、异常容错、随机延时防爬等工程化设计。代码具备良好的通用性修改页面节点参数后即可适配不同健身类网站适合掌握 Python 基础语法想要深耕行业定向爬虫、结构化数据采集与批量处理的开发者学习使用。一、项目需求分析与数据字段规划1.1 项目采集目标与应用场景本项目以主流健身服务类网站为采集载体实现城市范围内健身场馆、线下课程两大核心数据的自动化爬取。采集内容覆盖场馆基础资质、地理位置、收费体系、营业时间、配套设施以及课程名称、课程类型、授课教练、上课时间、课程价格、学员评价等信息。采集后的结构化数据可应用于多类业务场景健身行业从业者用于商圈场馆分布调研、定价策略分析线上平台运营人员用于内容填充与课程推荐普通用户可借助整合数据完成场馆与课程筛选对比数据分析人员可基于海量数据开展行业发展趋势统计。1.2 核心采集字段明细表结合健身行业数据使用需求将采集内容划分为健身场馆基础信息、场馆经营信息、配套服务信息、健身课程信息四大板块明确各字段含义、数据类型具体规划如下表。表格数据分类采集字段字段说明数据类型健身场馆基础信息场馆名称健身工作室、综合健身房、瑜伽馆等完整名称字符串健身场馆基础信息场馆类型综合健身、瑜伽、搏击、舞蹈、私教专属等分类字符串健身场馆基础信息所在区域所属城市、行政区、商圈、街道字符串场馆经营信息综合评分平台用户综合打分满分 5 分制字符串场馆经营信息营业时间日常营业时段、周末及节假日安排字符串场馆经营信息人均消费单次消费、月卡 / 季卡 / 年卡均价区间字符串配套服务信息配套设施淋浴、储物柜、停车场、运动器材等配套字符串配套服务信息详细地址完整门牌号地址信息字符串配套服务信息咨询电话场馆预约、咨询联系方式字符串健身课程信息课程名称团课、私教课、特色课程具体名称字符串健身课程信息课程类别有氧、力量、瑜伽、舞蹈、格斗等字符串健身课程信息授课教练负责该课程的教练姓名字符串健身课程信息课程时长单节课标准时长字符串健身课程信息课程价格单节售价、团购价、会员价字符串1.3 功能模块拆分为保证采集流程稳定、代码易维护、功能可拓展将整体爬虫程序拆分为八大独立模块各模块按执行顺序联动协作网络请求模块统一封装 HTTP GET 请求逻辑配置浏览器请求头完成身份伪装处理超时、连接失败、状态码异常等网络问题。分页遍历模块识别网页分页参数规则循环生成多页 URL实现全列表数据批量遍历采集。列表页解析模块从场馆列表页提取场馆基础信息并抓取场馆详情页链接作为二级采集入口。详情页解析模块访问场馆详情页面提取经营信息、配套服务、全部课程列表等深层数据。数据清洗模块利用字符串方法与正则表达式剔除空白字符、特殊符号、冗余文本统一数据格式。延时防护模块设置随机时间间隔模拟真人浏览行为降低网站反爬机制的触发概率。异常捕获模块分层设置异常捕获逻辑单条数据、单个页面出错时程序持续运行提升容错能力。数据存储模块将清洗后的结构化数据批量写入 CSV 文件实现数据持久化存储。1.4 运行环境要求项目基于 Python 3.8 及以上版本开发兼容 Windows、Linux、macOS 全平台操作系统。运行设备需保证网络通畅能够正常访问目标健身网站本地磁盘预留存储空间用于存放 CSV 数据文件。运行前需完成 Python 解释器安装以及对应第三方依赖库的部署工作。二、开发环境与依赖库部署2.1 Python 基础环境配置访问Python 官方下载地址根据操作系统选择对应安装包。Windows 系统选择桌面安装程序安装过程中勾选自动添加环境变量选项Linux、macOS 可使用源码包或系统自带包管理器完成安装。安装完成后打开命令行输入python --version正常输出版本号即代表基础环境配置完成。2.2 第三方库安装与功能说明本项目沿用爬虫主流技术组合核心使用requests、BeautifulSoup4、lxml三大第三方库搭配 Python 内置模块完成全部功能各库安装方式与作用说明如下。2.2.1 requests 库作为 Python 生态中主流的 HTTP 请求库语法简洁支持各类请求方式、请求头配置、超时设置是爬虫网络请求的核心工具。在命令行执行以下指令完成安装plaintextpip install requests安装后可查阅requests 库官方文档学习会话保持、代理配置、Cookie 携带等高级用法。2.2.2 BeautifulSoup4 与 lxml 解析库BeautifulSoup4 用于将 HTML 源码解析为树形节点结构快速定位标签并提取文本内容lxml 是高性能 HTML/XML 解析器解析效率与容错性优于内置解析器二者搭配使用是静态网页解析的标准方案。执行以下命令完成安装plaintextpip install beautifulsoup4 pip install lxml参考BeautifulSoup4 官方文档与lxml 解析库下载与文档掌握节点查找、属性提取等语法。2.2.3 Python 内置模块说明以下模块为 Python 标准库无需额外安装随解释器自带csv 模块实现 CSV 文件创建、表头写入、批量数据存储详情查看csv 模块官方说明。time、random 模块组合生成随机延时规避基础反爬策略参考time 模块官方文档。re 模块正则表达式模块用于清洗特殊符号、规整文本格式详细用法查阅re 正则表达式模块文档。三、目标网页结构分析正式编写代码前需对目标健身网站的请求规则、页面节点、分页逻辑、数据干扰项进行全面分析这是保证解析规则准确有效的前提。3.1 网页请求方式分析使用浏览器打开目标健身场馆列表页面按下 F12 打开开发者工具切换至 Network 面板并刷新页面。页面所有数据均直接渲染在 HTML 源码中属于标准静态网页主请求为 GET 请求无需处理 JavaScript 动态渲染、异步接口等复杂场景。查看请求头中的 User-Agent 字段网站会识别客户端类型若检测为 Python 原生请求会直接返回 403 禁止访问。因此爬虫必须配置合法的浏览器请求头完成客户端伪装部分高防护站点可额外补充 Referer、Accept 等请求字段提升伪装效果。3.2 场馆列表页节点分析页面主体为健身场馆列表每一个场馆对应一组独立的 HTML 标签块所有条目统一包裹在父级容器标签内。场馆名称、场馆类型、所在区域、综合评分等浅层数据均存放在 class 属性固定的 div、span 标签中标签层级稳定可通过类选择器精准定位。每个场馆条目内均包含详情页超链接链接分为绝对路径与相对路径两种形式这是进入场馆详情页、提取课程数据的核心入口采集过程中需要对链接格式进行判断与拼接。3.3 场馆详情页节点分析场馆详情页承载了营业时间、人均消费、配套设施、地址、电话以及全部健身课程数据。场馆经营与服务信息分布在独立标签中结构规则统一课程数据以列表形式展示单条课程为独立子标签同一场馆下会存在多条课程记录解析时需要循环遍历课程标签。课程价格、时长等字段常夹杂符号与空格后续需要配合正则完成清洗。3.4 分页规则分析页面底部设有标准分页导航栏切换不同页码观察 URL 变化可总结分页规则基础 URL 后拼接page数字参数页码从 1 开始递增。本项目采用手动设置起止页码的方式控制采集范围灵活性更强同时也可拓展为自动解析总页码实现全站全自动爬取。3.5 数据干扰项分析网页原始文本普遍存在换行符、制表符、连续空格、HTML 转义字符、装饰符号等干扰内容。如果直接提取文本会导致最终数据格式杂乱因此在数据提取环节需要统一调用清洗逻辑剔除无效字符标准化文本内容。四、完整代码实现与逐段原理解析结合前期环境配置、页面分析与功能规划按照模块化思路编写全套爬虫代码依次完成模块导入、全局配置、请求函数、数据清洗、列表页解析、详情页解析、数据存储、主程序调度八大板块每段代码配套原理讲解。4.1 模块导入集中导入项目所需的所有库与内置模块代码如下python运行# 网络请求库 import requests # 网页解析类 from bs4 import BeautifulSoup # CSV文件操作 import csv # 时间与随机数模块实现随机延时 import time import random # 正则表达式模块用于数据清洗 import re代码原理解析代码头部统一导入所有依赖组件符合 Python 工程化编码规范。requests负责网络交互BeautifulSoup4负责 HTML 节点解析csv实现表格数据存储time与random配合完成延时防爬re模块专门处理复杂文本清洗工作。集中管理导入模块便于后期维护与修改。4.2 全局参数配置定义全局变量统一管理请求地址、请求头、文件路径、延时区间、页码范围、正则规则集中配置便于批量修改适配不同网站代码如下python运行# 健身场馆列表基础URL拼接分页参数 BASE_URL https://www.fitnessdemo.com/gym?page # 浏览器请求头伪装客户端 HEADERS { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 } # 数据存储文件名称 SAVE_FILE 健身场馆与课程数据.csv # 随机延时区间 2-4秒 SLEEP_MIN 2 SLEEP_MAX 4 # 爬取页码范围 START_PAGE 1 END_PAGE 12 # 预编译正则匹配换行、制表、连续空格等空白字符 CLEAN_PATTERN re.compile(r[\r\n\t]|\s{2,})代码原理解析BASE_URL拆分基础域名与分页参数循环采集时仅需拼接数字即可生成完整 URL切换同结构网站只需修改该字段。HEADERS配置标准浏览器 UA绕过网站基础客户端检测避免请求被拦截。延时参数设置 2 至 4 秒随机间隔相比固定延时更贴近真人浏览行为降低反爬识别概率。预编译正则表达式CLEAN_PATTERN提前编译可减少重复编译开销提升批量数据清洗的运行效率用于过滤各类无效空白字符。4.3 通用网页请求函数封装统一的 GET 请求函数处理网络请求、编码、状态码、各类网络异常实现代码复用代码如下python运行def get_html(url): 发起网络请求获取网页HTML源码 :param url: 目标网页链接 :return: 成功返回源码文本失败返回None try: resp requests.get(url, headersHEADERS, timeout15) resp.encoding utf-8 if resp.status_code 200: return resp.text else: print(f请求异常状态码{resp.status_code} 链接{url}) return None except requests.exceptions.Timeout: print(f链接 {url} 请求超时) return None except requests.exceptions.ConnectionError: print(f链接 {url} 网络连接失败) return None except Exception as e: print(f链接 {url} 未知异常{str(e)}) return None代码原理解析该函数为项目通用请求接口列表页、详情页均可调用。timeout15设置 15 秒超时时间防止网络卡顿导致程序卡死。手动指定utf-8编码解决中文网页乱码问题。通过status_code判断请求结果分层捕获超时、连接失败、未知异常三类错误单个链接故障不会终止整体程序大幅提升程序稳定性。请求成功返回 HTML 文本失败统一返回None方便上层逻辑做判断。4.4 数据清洗函数独立封装清洗函数统一处理所有提取的文本内容标准化数据格式代码如下python运行def clean_text(text): 清洗文本去除多余空白字符 :param text: 原始文本 :return: 清洗后文本 if not text: return # 正则替换匹配内容为单个空格 new_text CLEAN_PATTERN.sub( , text) # 去除首尾空格 new_text new_text.strip() return new_text代码原理解析首先做空值判断避免空字符串引发解析错误。调用预编译正则将换行、制表符、连续多个空格统一替换为单个空格再通过strip()去除文本首尾空格。全项目统一调用该函数保证所有字段格式标准一致是批量数据采集项目中标准化处理的核心环节。4.5 列表页解析函数解析场馆列表页提取场馆基础信息与详情页链接代码如下python运行def parse_gym_list(html): 解析场馆列表页数据 :param html: 列表页源码 :return: 当前页场馆数据列表 gym_list [] if not html: return gym_list soup BeautifulSoup(html, lxml) # 定位所有场馆条目 gym_items soup.find_all(div, class_gym-item) for item in gym_items: gym_dict {} try: # 场馆名称 gym_name item.find(h3, class_gym-name).get_text() gym_dict[场馆名称] clean_text(gym_name) # 场馆类型 gym_type item.find(span, class_gym-type).get_text() gym_dict[场馆类型] clean_text(gym_type) # 所在区域 area item.find(span, class_gym-area).get_text() gym_dict[所在区域] clean_text(area) # 综合评分 score item.find(em, class_score).get_text() gym_dict[综合评分] clean_text(score) # 详情链接 detail_href item.find(a, class_gym-detail)[href] if detail_href.startswith(http): gym_dict[详情链接] detail_href else: gym_dict[详情链接] https://www.fitnessdemo.com detail_href gym_list.append(gym_dict) except Exception: continue return gym_list代码原理解析先判断源码是否为空空值直接返回空列表终止解析流程。实例化 BeautifulSoup 对象使用find_all批量获取所有场馆标签条目。遍历单条场馆数据通过find方法定位对应字段标签提取文本后立即调用清洗函数。对详情链接做路径判断相对路径拼接域名转为完整可访问链接解决链接失效问题。内部设置异常捕获单条场馆解析失败则跳过不影响同页面其他数据采集。最终返回列表嵌套字典格式的数据集便于后续整合处理。4.6 详情页解析函数访问场馆详情页提取经营信息、配套服务以及全部课程数据代码如下python运行def parse_gym_detail(detail_url): 解析场馆详情页提取经营、服务、课程数据 :param detail_url: 场馆详情链接 :return: 详情信息字典 课程列表 # 初始化场馆信息 gym_info { 营业时间: , 人均消费: , 配套设施: , 详细地址: , 咨询电话: } course_list [] detail_html get_html(detail_url) time.sleep(random.uniform(SLEEP_MIN, SLEEP_MAX)) if not detail_html: return gym_info, course_list try: soup BeautifulSoup(detail_html, lxml) # 提取场馆经营与服务信息 open_time soup.find(div, class_open-time).get_text() gym_info[营业时间] clean_text(open_time) avg_cost soup.find(div, class_avg-cost).get_text() gym_info[人均消费] clean_text(avg_cost) facility soup.find(div, class_facility).get_text() gym_info[配套设施] clean_text(facility) address soup.find(div, class_address).get_text() gym_info[详细地址] clean_text(address) phone soup.find(div, class_phone).get_text() gym_info[咨询电话] clean_text(phone) # 提取所有健身课程 course_items soup.find_all(div, class_course-item) for course in course_items: course_dict {} course_name course.find(h4, class_course-name).get_text() course_dict[课程名称] clean_text(course_name) course_type course.find(span, class_course-type).get_text() course_dict[课程类别] clean_text(course_type) coach course.find(span, class_coach).get_text() course_dict[授课教练] clean_text(coach) duration course.find(span, class_duration).get_text() course_dict[课程时长] clean_text(duration) price course.find(span, class_course-price).get_text() course_dict[课程价格] clean_text(price) course_list.append(course_dict) except Exception: pass return gym_info, course_list代码原理解析提前初始化场馆信息字典保证字段完整性即使解析失败也不会出现字段缺失。调用请求函数获取详情页源码执行随机延时规避连续请求带来的反爬风险。分两部分解析页面内容第一部分提取场馆固定信息第二部分循环遍历课程标签提取多条课程数据。所有文本提取后统一执行清洗操作保证数据格式统一。捕获解析异常出现错误时保留空字段程序继续运行。函数同时返回场馆信息与课程列表实现一次请求提取两类数据。4.7 数据存储函数整合所有数据批量写入 CSV 文件适配主流办公软件代码如下python运行def save_to_csv(total_data): 将全量数据写入CSV文件 :param total_data: 整合后的完整数据集 # 定义CSV表头 header [ 场馆名称, 场馆类型, 所在区域, 综合评分, 营业时间, 人均消费, 配套设施, 详细地址, 咨询电话, 课程名称, 课程类别, 授课教练, 课程时长, 课程价格 ] with open(SAVE_FILE, w, encodingutf-8-sig, newline) as f: writer csv.DictWriter(f, fieldnamesheader) writer.writeheader() writer.writerows(total_data) print(f采集完成共获取 {len(total_data)} 条数据文件已保存至本地)代码原理解析表头字段与前期规划一一对应保证数据与列名精准匹配。使用with上下文管理器操作文件代码执行完毕自动关闭文件流避免文件占用、数据丢失。utf-8-sig编码解决 Excel 打开中文乱码问题newline消除 CSV 文件多余空行。采用DictWriter字典写入器writerows方法支持批量写入多条数据提升大批量数据存储效率。4.8 主程序调度函数整合所有功能模块实现分页循环、数据合并、全流程调度为程序入口代码如下python运行def main(): all_data [] # 遍历所有页码 for page in range(START_PAGE, END_PAGE 1): print(f正在采集第 {page} 页健身场馆数据...) page_url BASE_URL str(page) page_html get_html(page_url) if not page_html: print(f第 {page} 页请求失败跳过) continue # 解析列表页 gym_page_data parse_gym_list(page_html) for gym in gym_page_data: detail_url gym[详情链接] gym_detail, course_list parse_gym_detail(detail_url) # 合并场馆基础信息与详情信息 gym.pop(详情链接) gym.update(gym_detail) # 遍历单场馆下所有课程生成单条完整数据 for course in course_list: full_data gym.copy() full_data.update(course) all_data.append(full_data) # 页间延时 time.sleep(random.uniform(SLEEP_MIN, SLEEP_MAX)) # 写入文件 save_to_csv(all_data) if __name__ __main__: main()代码原理解析main函数作为总调度中心初始化列表存储全部整合数据。通过range遍历设定页码区间逐一生成分页 URL 并发起请求。单页请求失败则直接跳过继续执行下一页采集。解析列表数据后逐个访问场馆详情页同时获取场馆信息与课程列表。删除冗余的详情链接字段合并场馆基础信息与详情信息同一场馆多条课程分别生成独立数据行保证每条数据一一对应单门课程。单页采集完成后执行页间延时模拟翻页行为。全部页面采集完毕后统一调用存储函数完成数据落地。标准程序入口判断仅在直接运行文件时启动爬虫作为模块导入时不自动执行。五、项目优化、问题排查与功能拓展5.1 常见问题与解决方案结合本项目场景整理运行过程中的高频问题、成因及解决办法如下表所示。表格问题现象产生原因解决方案请求返回 403 访问拒绝未配置浏览器请求头被识别为爬虫补充完整 User-Agent 请求头Excel 打开文件中文乱码文件编码设置错误写入文件使用 utf-8-sig 编码无法提取场馆 / 课程数据标签名、class 类名与网页实际结构不符重新查看网页源码修正节点定位参数程序运行卡顿、长时间无响应未设置请求超时在 requests 请求中增加 timeout 参数部分课程数据缺失课程标签层级识别错误重新分析课程列表节点结构调整查找规则CSV 文件出现大量空行文件打开未配置 newline 参数打开文件时添加 newline5.2 反爬策略进阶优化项目基础防护为 UA 伪装 随机延时面对高防护健身网站可叠加以下方案提升稳定性多 UA 池轮换构建多个浏览器 UA 字符串列表每次请求随机选取避免单一标识被封禁。完善请求头新增 Referer、Accept、Accept-Language 等字段完整模拟浏览器请求特征。代理 IP 应用大批量高频采集时接入代理 IP 池轮换 IP防止 IP 被限制访问。Cookie 携带部分网站需要登录状态才能查看完整课程与电话信息手动抓取有效 Cookie 加入请求头。5.3 功能迭代与拓展方向基于现有框架可根据业务需求拓展更多实用功能自动识别总页码解析分页区域标签动态获取全站最大页码无需手动修改结束页码。分类筛选采集增加筛选参数单独采集瑜伽馆、搏击馆、私教工作室等单一类型场馆数据。数据库存储将 CSV 存储替换为 MySQL、MongoDB 等数据库适配海量数据存储与查询场景。多线程并发采集引入 threading 模块实现多线程请求大幅提升整体采集速度。增量爬取对比历史采集数据仅爬取新增场馆与新课程减少重复请求。

相关新闻