Python 爬虫实战:租房平台房源信息结构化采集
前言
伴随着城市流动人口增加与住房租赁市场持续发展,租房平台汇聚了海量房源基础信息、户型配置、租金价格、配套设施、地理位置、房东信息等公开数据,是城市租房市场调研、区域房价走势分析、居住配套评估、用户租房需求画像研究的核心数据源。租房类网站页面结构繁杂,数据分布碎片化,同时叠加多层级反爬策略、动态样式标签、非标准文本内容,是锻炼爬虫综合能力、结构化数据处理能力的优质实战场景。
本次项目聚焦主流租房平台,完成整租、合租、公寓等不同类型房源的自动化采集工作,提取房源标题、户型、面积、月租金、租赁方式、所在小区、地理位置、配套设施、房源描述、发布时间等全维度信息,同时完成数据清洗、格式统一与本地持久化存储。项目全程恪守网络数据采集相关法律法规与平台运营规范,仅抓取页面公开展示内容,严格控制请求频次,不获取租客隐私、房东联系方式等涉密信息,所有代码与采集数据仅用于技术学习与数据分析研究。
本项目所依赖的开发库及官方文档链接如下,可直接跳转查阅安装方法、接口用法与技术文档:
- Requests:HTTP 请求库官方文档
- BeautifulSoup4:HTML 网页解析库官方文档
- lxml:高性能解析器官方文档
- pandas:结构化数据处理与存储库官方文档
- re:Python 内置正则表达式模块(无需安装)
- time:Python 内置时间控制模块(无需安装)
- random:Python 内置随机数模块(无需安装)
一、项目环境搭建与采集合规规范
1.1 运行环境要求
本项目兼容 Windows、macOS、Linux 三大主流操作系统,环境配置标准统一,保障代码稳定运行:
- Python 版本:3.8 及以上稳定版本,推荐 3.9、3.10、3.11,规避低版本语法及库兼容问题;
- 网络环境:网络连接稳定,可正常访问目标租房平台,无地域访问限制;
- 开发工具:PyCharm、VS Code、IDLE 等常规 Python 代码编辑器均可使用。
1.2 依赖库安装
项目功能实现依托网络请求、网页解析、正则处理、数据存储类第三方库,打开系统终端,执行以下pip命令完成批量安装:
bash
运行
pip install requests beautifulsoup4 lxml pandas若官方源下载速度缓慢、出现连接超时,可切换清华大学开源软件镜像源加速安装,命令示例如下:
bash
运行
pip install requests beautifulsoup4 lxml pandas -i https://pypi.tuna.tsinghua.edu.cn/simple安装完成后执行pip list命令,核对已安装库列表,确认无版本冲突、安装失败等问题。
1.3 数据采集合规准则
租房平台包含大量房源、个人及社区相关信息,开展数据采集必须严格遵守以下规则: 第一,仅采集页面公开展示的房源户型、面积、租金、小区名称等非隐私数据,严禁抓取手机号、微信、身份证、详细住址等个人隐私信息; 第二,严格遵守站点robots.txt协议,不访问协议明确禁止爬虫抓取的页面与目录; 第三,设置随机间隔时间分散请求节奏,禁止短时间内高频、并发请求,避免对平台服务器造成负载压力; 第四,本项目代码及采集数据仅限个人技术学习、市场调研分析使用,不得用于恶意引流、信息倒卖、商业推广等违规场景。
二、页面结构、URL 规则与反爬机制分析
代码开发前需完成页面拆解、链接规则梳理、反爬特征识别,本次项目分为房源列表页与房源详情页两大核心采集页面,二者分工不同,数据层级存在明显差异。
2.1 页面 URL 与分页规则
租房平台列表页采用标准分页机制,同时支持城市、区域、户型、价格区间等筛选条件,核心 URL 规则整理如下表:
表格
| 页面类型 | 基础 URL 格式 | 核心参数 | 单页数据量 | 页面功能说明 |
|---|---|---|---|---|
| 房源列表页 | https:// 域名 / 租房 / 区域 /?page = 页码 | page:分页编号,从 1 开始递增 | 每页 30 条房源数据 | 展示房源标题、租金、户型、面积、小区名称、房源详情链接 |
| 房源详情页 | https:// 域名 /rent/ 房源 ID.html | 房源 ID:房源唯一标识,无分页参数 | 单页展示单套房源完整信息 | 提取租赁方式、朝向、楼层、配套设施、房源描述、发布时间等深度数据 |
区域参数可自定义替换,实现不同城市、不同片区房源定向采集;房源 ID 由列表页链接解析获取,是串联列表页与详情页的核心标识。
2.2 HTML 页面结构解析
使用浏览器 F12 开发者工具查看网页源代码,分层拆解标签层级与数据对应关系:
房源列表页所有房源条目统一放置在外层容器标签内,单条房源数据独立封装在块状 div 标签中。房源标题、租金价格位于页面视觉核心区域的标签内;户型、面积、朝向等基础参数集中在同级子标签;小区名称、所在商圈、发布时间分布在附属标签;房源详情链接存储在标题 a 标签的 href 属性中。部分文本夹杂换行、空格、全角符号,需要结合正则表达式完成清洗。
房源详情页页面采用分区布局,顶部汇总房源核心价格与基础户型信息;中部为房屋配置、楼层、装修情况、周边配套、交通设施等结构化数据;底部为房东发布的房源详细描述、租房须知、看房时间等长文本内容。长文本内容分段较多、符号繁杂,是数据清洗的重点环节。
2.3 平台反爬策略及应对方案
租房平台用户访问量高,反爬防护体系完善,主要反爬手段及对应解决方案如下:
- 请求头校验:服务器识别客户端请求标识,缺少标准
User-Agent的请求会直接返回 403 禁止访问状态码。解决方案为构造完整浏览器请求头,模拟正常用户访问行为。 - 请求频率限制:短时间内连续高频请求,会触发临时 IP 封禁、人机验证码、页面跳转拦截。解决方案为设置随机休眠时间,打散请求节奏,降低单位时间请求数量。
- 动态 Class 类名:平台会不定期修改标签 class 属性值,导致原有解析规则失效。解决方案为增加多层异常判断、空值兜底逻辑,提升代码容错能力。
- 碎片化文本展示:房源描述、配套信息拆分在多个子标签中,文本格式混乱。解决方案为统一封装文本清洗函数,结合正则表达式剔除无效字符。
三、模块化代码实现
本项目采用模块化编程思想,将功能拆分为全局配置模块、通用请求模块、文本清洗模块、列表页解析模块、详情页解析模块、数据存储模块、主调度模块,各模块职责独立、耦合度低,便于后期维护、迭代与功能拓展。
3.1 模块导入与全局配置
统一导入项目所需库文件,集中定义请求头、目标区域、分页范围、休眠时长、文件存储路径等全局常量。
python
运行
# 导入内置模块与第三方库 import requests from bs4 import BeautifulSoup import pandas as pd import re import time import random # 伪造完整浏览器请求头,绕过基础反爬校验 HEADERS = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Accept-Language": "zh-CN,zh;q=0.9", "Referer": "https://www.xxx.com/", "Connection": "keep-alive" } # 基础爬取配置 # 租房区域,可自行修改 AREA_NAME = "北京朝阳区" # 列表页基础URL BASE_URL = "https://www.xxx.com/zufang/{}/page{}" # 分页范围 START_PAGE = 1 END_PAGE = 4 # 随机休眠时间区间,单位:秒 SLEEP_MIN = 2 SLEEP_MAX = 5 # 数据存储路径 SAVE_FILE = "租房房源结构化数据.csv"代码原理
- 整合网络请求、网页解析、正则匹配、数据处理、时间控制全系列依赖库,覆盖项目所有功能需求;
- 构建标准化浏览器请求头,补充 Referer、Connection 等参数,高度还原真实访问特征,降低被识别为爬虫的概率;
- 全局配置项统一管理,切换采集区域、调整分页、修改存储路径时,仅修改常量即可,无需改动业务代码;
- 随机休眠区间设置为 2 至 5 秒,有效规避基于访问频率的反爬检测。
3.2 通用网络请求模块
封装统一的 GET 请求函数,集成状态码判断、编码设置、分层异常捕获逻辑,所有页面请求统一调用该函数,减少代码冗余。
python
运行
def get_page_html(url: str) -> str: """ 发送HTTP GET请求,获取网页源代码 :param url: 目标页面链接 :return: 网页源码字符串,请求失败返回空字符串 """ try: # 设置15秒超时,防止网络异常导致程序卡死 resp = requests.get(url, headers=HEADERS, timeout=15) if resp.status_code == 200: resp.encoding = "utf-8" return resp.text else: print(f"请求异常,状态码:{resp.status_code} 链接:{url}") return "" except requests.exceptions.Timeout: print(f"请求超时:{url}") return "" except requests.exceptions.ConnectionError: print(f"网络连接失败:{url}") return "" except Exception as e: print(f"未知错误 {str(e)} 链接:{url}") return ""代码原理
- 分层捕获请求超时、连接失败、未知异常三类问题,精准定位故障,同时保证程序不会因单次请求错误终止运行;
- 强制指定页面编码为 utf-8,统一全站编码规则,彻底解决中文乱码问题;
- 仅放行 200 状态码的正常请求,其余状态码统一判定为请求失败并返回空字符串。
3.3 文本清洗工具模块
针对房源数据中存在的换行、空格、制表符、特殊符号、全角字符等干扰内容,基于正则表达式编写通用清洗函数,标准化所有文本格式。
python
运行
def clean_text(raw_content: str) -> str: """通用文本清洗,去除空白字符与特殊符号""" if not raw_content: return "无" # 清除所有空白字符 content = re.sub(r"\s+", "", raw_content.strip()) # 清除项目符号、全角空格等特殊字符 content = re.sub(r"[●■◆\u3000]", "", content) return content def extract_rent_price(raw_price: str) -> str: """提取标准化月租金""" if not raw_price: return "价格面议" return clean_text(raw_price)代码原理
- 正则表达式
\s+匹配并清除所有连续空白字符,统一处理换行、空格、制表符; - 针对性过滤房源描述中高频出现的装饰符号、全角空格,保证文本整洁规范;
- 单独封装租金处理函数,空值统一赋值为 “价格面议”,贴合租房平台数据特征。
3.4 房源列表页解析模块
遍历列表页所有房源条目,提取房源标题、月租金、户型、面积、小区名称、房源详情链接等基础信息。
python
运行
def parse_rent_list(html: str) -> list: """ 解析房源列表页数据 :param html: 列表页源代码 :return: 单页房源数据列表 """ rent_list = [] soup = BeautifulSoup(html, "lxml") # 定位所有房源条目 rent_items = soup.find_all("div", class_="list-item") for item in rent_items: rent_info = {} # 房源标题与详情链接 title_node = item.find("a", class_="title") rent_info["房源标题"] = clean_text(title_node.get_text()) if title_node else "未知房源" rent_info["房源详情链接"] = title_node["href"] if title_node else "" # 月租金 price_node = item.find("span", class_="price") rent_info["月租金"] = extract_rent_price(price_node.get_text()) if price_node else "价格面议" # 户型与面积 house_type_node = item.find("p", class_="house-type") rent_info["户型面积"] = clean_text(house_type_node.get_text()) if house_type_node else "暂无数据" # 小区及商圈 community_node = item.find("div", class_="community") rent_info["小区商圈"] = clean_text(community_node.get_text()) if community_node else "未知小区" rent_list.append(rent_info) return rent_list代码原理
- 使用
find_all批量获取所有房源条目,循环遍历完成逐条解析,是列表类页面标准解析逻辑; - 所有文本字段提取后统一调用清洗函数,保证全项目数据格式统一;
- 对标签缺失、文本为空的场景设置默认兜底值,避免程序触发属性错误、索引错误。
3.5 房源详情页解析模块
根据列表页提取的详情链接,进入二级页面抓取租赁方式、楼层、朝向、装修情况、配套设施、房源描述、发布时间等深度信息,完善数据维度。
python
运行
def parse_rent_detail(html: str) -> dict: """ 解析房源详情页补充信息 :param html: 详情页源代码 :return: 详情数据字典 """ detail_data = {} soup = BeautifulSoup(html, "lxml") # 租赁方式(整租/合租) rent_mode_node = soup.find("span", class_="rent-mode") detail_data["租赁方式"] = clean_text(rent_mode_node.get_text()) if rent_mode_node else "未知" # 楼层与朝向 floor_node = soup.find("div", class_="floor-dir") detail_data["楼层朝向"] = clean_text(floor_node.get_text()) if floor_node else "暂无信息" # 装修情况 decorate_node = soup.find("span", class_="decorate") detail_data["装修情况"] = clean_text(decorate_node.get_text()) if decorate_node else "未知" # 配套设施 facility_node = soup.find("div", class_="facility-list") detail_data["配套设施"] = clean_text(facility_node.get_text()) if facility_node else "无配套" # 房源详细描述 desc_node = soup.find("div", class_="house-desc") detail_data["房源描述"] = clean_text(desc_node.get_text()) if desc_node else "无描述" # 发布时间 time_node = soup.find("span", class_="publish-time") detail_data["发布时间"] = clean_text(time_node.get_text()) if time_node else "未知时间" return detail_data代码原理
- 筛选租房场景核心分析字段,兼顾数据价值与解析效率;
- 长文本描述、多标签组合数据统一复用清洗函数,消除分段、符号干扰;
- 多层级空值判断,适配部分房源无配套、无详细描述、未标注朝向等特殊场景。
3.6 数据存储模块
将采集完成的结构化数据转换为表格形式,保存为 CSV 文件,兼容 Excel、WPS、各类数据分析工具直接读取使用。
python
运行
def save_rent_data(data: list, file_path: str): """将房源数据保存为CSV文件""" if not data: print("未采集到有效房源数据,跳过保存") return df = pd.DataFrame(data) # utf-8-sig编码解决Windows系统中文乱码,关闭默认行索引 df.to_csv(file_path, index=False, encoding="utf-8-sig") print(f"数据保存完成,累计采集{len(data)}条房源信息,文件路径:{file_path}")代码原理
- 优先校验数据列表是否为空,避免生成无效空白文件;
- 借助 pandas 的 DataFrame 结构,快速将字典列表转为二维表格,字段自动映射匹配;
- 采用 utf-8-sig 编码,适配 Windows 平台主流办公软件,彻底解决中文乱码问题。
3.7 主调度函数
作为程序入口,串联分页遍历、页面请求、数据解析、数据合并、定时休眠、文件存储全流程,实现自动化批量采集。
python
运行
def main(): total_rent_data = [] print(f"开始采集【{AREA_NAME}】房源数据,爬取页码范围:{START_PAGE} - {END_PAGE}") # 遍历所有分页 for page in range(START_PAGE, END_PAGE + 1): print(f"正在爬取第 {page} 页房源列表") page_url = BASE_URL.format(AREA_NAME, page) page_html = get_page_html(page_url) if not page_html: print(f"第{page}页请求失败,跳过当前页面") time.sleep(random.randint(SLEEP_MIN, SLEEP_MAX)) continue page_rent_list = parse_rent_list(page_html) if not page_rent_list: print(f"第{page}页未解析到房源数据") time.sleep(random.randint(SLEEP_MIN, SLEEP_MAX)) continue # 遍历单页所有房源,爬取详情信息 for rent in page_rent_list: rent_url = rent["房源详情链接"] if not rent_url: total_rent_data.append(rent) continue detail_html = get_page_html(rent_url) detail_dict = parse_rent_detail(detail_html) # 合并基础信息与详情信息 full_rent_data = {**rent, **detail_dict} total_rent_data.append(full_rent_data) # 单套房源采集完成后随机休眠 time.sleep(random.randint(SLEEP_MIN, SLEEP_MAX)) # 单页采集完成后随机休眠 time.sleep(random.randint(SLEEP_MIN, SLEEP_MAX)) # 统一保存全部数据 save_rent_data(total_rent_data, SAVE_FILE) print("所有房源数据采集任务执行完毕!") # 程序入口 if __name__ == "__main__": main()代码原理
- 外层循环实现分页遍历,动态拼接分页 URL,完成多页房源列表批量抓取;
- 内层循环逐个访问房源详情页,实现列表页与详情页二级联动爬取;
- 使用字典解包语法合并两组数据,保证单条房源数据字段完整统一;
- 在分页切换、单房源采集两个节点分别设置随机休眠,多层级控制请求频率,降低被拦截概率;
- 全量数据采集完成后统一执行存储操作,减少文件 IO 次数,提升程序整体运行效率。
四、程序运行测试与数据结果展示
4.1 运行操作步骤
- 将完整代码复制至 Python 编辑器,保存文件并命名为
rent_spider.py; - 根据采集需求修改
AREA_NAME、START_PAGE、END_PAGE等全局配置,切换采集区域与爬取页数; - 确认网络正常,直接运行代码,终端实时输出爬取页码、运行状态等日志信息;
- 任务结束后,代码同级目录生成 CSV 格式房源数据文件。
4.2 终端运行日志示例
plaintext
开始采集【北京朝阳区】房源数据,爬取页码范围:1 - 4 正在爬取第 1 页房源列表 正在爬取第 2 页房源列表 正在爬取第 3 页房源列表 正在爬取第 4 页房源列表 数据保存完成,累计采集120条房源信息,文件路径:租房房源结构化数据.csv 所有房源数据采集任务执行完毕!4.3 结构化数据展示
生成的 CSV 文件字段完整、格式规范,无乱码与无效字符,具体数据样式如下表:
表格
| 房源标题 | 房源详情链接 | 月租金 | 户型面积 | 小区商圈 | 租赁方式 | 楼层朝向 | 装修情况 | 配套设施 | 房源描述 | 发布时间 |
|---|---|---|---|---|---|---|---|---|---|---|
| 精装两居 近地铁 采光好 | https://xxx/rent/998877.html | 5800 元 / 月 | 2 室 1 厅 | 望京小区 望京商圈 | 整租 | 中层 / 朝南 | 精装修 | 空调、热水器、冰箱、洗衣机 | 房屋采光充足,交通便利,周边配套成熟,拎包入住 | 2026-06-08 |
| 温馨单间 合租 家电齐全 | https://xxx/rent/665544.html | 2200 元 / 月 | 1 室 0 厅 | 国贸公寓 国贸商圈 | 合租 | 高层 / 朝东 | 简装修 | 宽带、衣柜、桌椅 | 单间出租,室友作息规律,小区安保严格,出行方便 | 2026-06-07 |
五、代码优化与功能扩展方向
5.1 性能优化方案
- 异步请求改造:引入
aiohttp异步请求库,替换传统同步请求,大幅提升多页、多房源场景下的爬取效率,严格控制并发数量,避免触发反爬。 - 日志系统升级:使用 Python 内置
logging模块替换原生 print 输出,分级记录运行日志、警告日志、错误日志,并落地至本地日志文件,便于长期运行后的故障排查。 - 断点续爬开发:新增本地文本或 JSON 文件记录已爬取页码、房源链接,程序意外中断后可从断点位置继续采集,避免重复抓取浪费资源。
- 流式写入优化:海量数据采集场景下,取消全量数据内存缓存,采用逐行写入 CSV 的方式,有效降低内存占用。
5.2 功能拓展开发思路
- 多区域批量采集:定义城市及区域列表,循环遍历不同片区,实现多区域房源一站式采集。
- 数据入库存储:对接 SQLite、MySQL 等关系型数据库,将 CSV 数据迁移至数据库,支持复杂条件查询、租金统计、房源筛选等操作。
- 价格区间筛选:结合平台筛选参数,定向采集指定租金范围、户型面积的房源,实现精准数据抓取。
- 数据可视化分析:结合 matplotlib、pandas 实现区域租金分布、户型价格对比、房源数量统计等可视化图表。
- 代理 IP 池接入:大规模分布式采集场景下,接入 IP 代理池动态切换请求 IP,彻底解决高频爬取导致的 IP 封禁问题。
六、常见问题与解决方案
6.1 解析不到房源数据
问题现象:程序正常运行,解析结果为空列表。 解决方案:手动访问目标 URL 确认页面可正常访问;使用开发者工具核对标签 class 名称,平台更新样式后同步修改代码;检查请求头完整性,缺失 User-Agent 会导致页面返回异常内容。
6.2 IP 访问被限制
问题现象:请求返回 403 状态码、验证码页面、空白页面。 解决方案:调大随机休眠时间区间,拉长请求间隔;临时切换网络更换公网 IP;暂停爬取一段时间,等待平台自动解除限制。
6.3 房源描述文本错乱
问题现象:房源描述、配套设施出现大量符号、分段混乱。 解决方案:根据页面最新文本特征调整正则清洗规则;重新核对标签定位层级,确保抓取目标区域文本。
6.4 CSV 文件中文乱码
问题现象:Excel 打开文件中文显示乱码。 解决方案:代码已配置 utf-8-sig 编码,若仍存在乱码,可使用记事本打开文件,另存为 UTF-8 编码格式后再用 Excel 打开。
6.5 依赖库调用报错
问题现象:运行代码提示模块不存在、函数调用异常。 解决方案:重新执行 pip 命令补全依赖库;确认 Python 解释器与库安装环境一致;升级 Python 与 pip 版本,解决版本兼容问题。
