Python实现SMZDM数据处理系统:从爬虫到数据分析的完整实践
前言
在大数据时代,数据获取、清洗和分析已成为数据分析师和开发者必备的技能。本文将通过一个完整的实战项目,带你学习如何使用Python实现一个完整的数据处理系统,包括数据爬取、清洗、分析和可视化。
本项目以SMZDM(什么值得买)网站为例,实现了一个端到端的数据处理流程。通过学习本项目,你将掌握:
- Python爬虫开发技巧
- 数据清洗和预处理方法
- 数据分析和可视化技能
- 完整项目的组织和管理
一、项目概述
1.1 项目简介
本项目是一个完整的Python数据处理系统,主要功能包括:
- 数据爬取:从SMZDM网站爬取商品数据
- 数据清洗:对原始数据进行去重、格式化等处理
- 数据分析:对清洗后的数据进行多维度分析和可视化
1.2 技术栈
- Python 3.7+
- requests:HTTP请求库
- pandas:数据处理和分析库
- matplotlib/seaborn:数据可视化库
- jieba:中文分词库
1.3 项目结构
python_excel/
├── crawler.py # 数据爬取模块
├── data_cleaner.py # 数据清洗模块
├── data_analyzer.py # 数据分析模块
├── main.py # 主程序入口
└── requirements.txt # 依赖包列表
二、环境准备
2.1 安装Python
确保你的系统已安装Python 3.7或更高版本。可以通过以下命令检查:
bash
python --version
2.2 安装依赖包
创建requirements.txt文件,内容如下:
txt
requests>=2.31.0
pandas>=2.0.0
matplotlib>=3.7.0
seaborn>=0.12.0
jieba>=0.42.1
然后执行:
bash
pip install -r requirements.txt
三、核心模块实现
3.1 数据爬取模块(crawler.py)
数据爬取是整个数据处理流程的第一步。我们需要分析目标网站的API接口,然后编写爬虫代码。
3.1.1 分析API接口
通过浏览器开发者工具,我们发现SMZDM使用了API接口来获取数据。主要的请求信息如下:
- 请求URL :
https://damo.smzdm.com/interest/more_page - 请求方法: POST
- 请求参数: 包含页码、分类ID等信息
3.1.2 实现爬虫代码
python
import requests
import json
import pandas as pd
import time
def fetch_page_data(page):
"""爬取单页数据"""
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...',
# 其他请求头...
}
data = {
'sort': '2',
'page': str(page),
'size': '30',
'category_id': '5324',
# 其他参数...
}
try:
response = requests.post(
'https://damo.smzdm.com/interest/more_page',
headers=headers,
data=data,
timeout=10
)
response.raise_for_status()
data_json = json.loads(response.text)
items = []
for row in data_json.get('data', {}).get('rows', []):
interaction = row.get('article_interaction', {})
items.append({
'title': row.get('article_title', ''),
'price': row.get('article_price', ''),
'url': row.get('article_url', ''),
'image': row.get('article_pic', ''),
'content': row.get('article_content', ''),
'like': interaction.get('article_worthy', 0),
'comment': interaction.get('article_comment', 0),
'publish_time': row.get('pubdate') or row.get('article_date', '')
})
return items
except Exception as e:
print(f"爬取第 {page} 页时出错: {e}")
return []
def crawl_data(start_page=1, end_page=10, output_file='smzdm_raw.csv', delay=1):
"""爬取多页数据并保存为CSV"""
all_items = []
for page in range(start_page, end_page + 1):
print(f"正在爬取第 {page} 页...")
items = fetch_page_data(page)
if items:
all_items.extend(items)
print(f"第 {page} 页成功获取 {len(items)} 条数据")
# 延迟,避免请求过快
if page < end_page:
time.sleep(delay)
if all_items:
df = pd.DataFrame(all_items)
df.to_csv(output_file, index=False, encoding='utf-8-sig')
print(f"\n数据爬取完成!共获取 {len(all_items)} 条数据")
return output_file
else:
print("未获取到任何数据")
return None
3.1.3 关键要点
- 请求头设置:模拟真实浏览器请求,避免被反爬
- 延迟机制:每次请求之间添加延迟,避免被封禁
- 错误处理:捕获异常,确保程序稳定性
- 数据解析:从JSON响应中提取所需字段
3.2 数据清洗模块(data_cleaner.py)
原始数据往往包含很多问题,需要进行清洗处理。
3.2.1 主要清洗任务
- 去重处理:去除完全重复的记录和URL重复的记录
- 字段处理:提取价格数字、格式化时间
- 内容清洗:移除HTML标签、特殊字符
- 空值处理:处理缺失值
3.2.2 核心代码实现
python
import pandas as pd
import re
def extract_price(price_str):
"""从价格字符串中提取数字"""
if pd.isna(price_str) or price_str == '':
return None
match = re.search(r'(\d+\.?\d*)', str(price_str))
if match:
try:
return float(match.group(1))
except:
return None
return None
def clean_content(content_str):
"""清洗内容字段,移除HTML标签"""
if pd.isna(content_str) or content_str == '':
return ''
content = str(content_str)
# 移除HTML标签
content = re.sub(r'<[^>]+>', '', content)
# 移除多余空白
content = re.sub(r'\s+', ' ', content).strip()
return content
def clean_data(input_file='smzdm_raw.csv', output_file='smzdm_cleaned.csv'):
"""数据清洗主函数"""
df = pd.read_csv(input_file, encoding='utf-8-sig')
# 1. 去重
df = df.drop_duplicates()
df = df.drop_duplicates(subset=['url'], keep='first')
# 2. 提取价格数字
df['price_num'] = df['price'].apply(extract_price)
# 3. 清洗内容
df['content'] = df['content'].apply(clean_content)
# 4. 处理空值
df = df[df['title'].notna() & (df['title'] != '')]
# 5. 保存清洗后的数据
df.to_csv(output_file, index=False, encoding='utf-8-sig')
return output_file
3.2.3 数据清洗技巧
- 正则表达式 :使用
re模块提取和匹配模式 - pandas函数 :使用
drop_duplicates()去重 - 链式处理 :使用
apply()函数批量处理数据
3.3 数据分析模块(data_analyzer.py)
数据清洗完成后,就可以进行深度分析和可视化了。
3.3.1 分析维度
- 价格分析:价格分布、价格统计
- 互动分析:点赞数、评论数分析
- 时间分析:发布时间趋势
- 关联分析:价格与互动的关系
- 文本分析:高频词统计
3.3.2 可视化实现
python
import matplotlib.pyplot as plt
import seaborn as sns
import jieba
from collections import Counter
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei', 'SimHei']
plt.rcParams['axes.unicode_minus'] = False
def analyze_data(input_file='smzdm_cleaned.csv', output_dir='analysis_results'):
"""数据分析主函数"""
df = pd.read_csv(input_file, encoding='utf-8-sig')
# 1. 价格分布分析
price_df = df[df['price_num'].notna()]
plt.figure(figsize=(12, 6))
plt.hist(price_df['price_num'], bins=50, edgecolor='black', alpha=0.7)
plt.xlabel('价格 (元)')
plt.ylabel('商品数量')
plt.title('商品价格分布')
plt.savefig(f'{output_dir}/price_distribution.png', dpi=300)
plt.close()
# 2. 互动数据分析
fig, axes = plt.subplots(1, 2, figsize=(14, 6))
axes[0].hist(df['like'], bins=30, color='#FF6B6B')
axes[0].set_title('点赞数分布')
axes[1].hist(df['comment'], bins=30, color='#4ECDC4')
axes[1].set_title('评论数分布')
plt.savefig(f'{output_dir}/interaction_distribution.png', dpi=300)
plt.close()
# 3. 热门商品Top10
top_liked = df.nlargest(10, 'like')
plt.figure(figsize=(12, 8))
plt.barh(range(len(top_liked)), top_liked['like'], color='#FF6B6B')
plt.yticks(range(len(top_liked)),
[title[:30] + '...' if len(title) > 30 else title
for title in top_liked['title']])
plt.xlabel('点赞数')
plt.title('热门商品 Top 10')
plt.gca().invert_yaxis()
plt.savefig(f'{output_dir}/top10_liked.png', dpi=300)
plt.close()
# 4. 高频词统计
all_text = ' '.join(df['title'].dropna().astype(str).tolist())
words = jieba.cut(all_text)
# 过滤停用词
stopwords = set(['的', '了', '在', '是', '我', '有', '和', '就', '不'])
filtered_words = [w for w in words if len(w) >= 2 and w not in stopwords]
word_counts = Counter(filtered_words)
top_words = word_counts.most_common(20)
plt.figure(figsize=(14, 8))
words_list = [word for word, count in top_words]
counts_list = [count for word, count in top_words]
plt.barh(range(len(words_list)), counts_list, color='#FFA07A')
plt.yticks(range(len(words_list)), words_list)
plt.xlabel('出现次数')
plt.title('高频词 Top 20')
plt.gca().invert_yaxis()
plt.savefig(f'{output_dir}/word_frequency.png', dpi=300)
plt.close()
print("数据分析完成!")
3.3.3 可视化要点
- 中文字体设置:确保图表能正确显示中文
- 图表美化:使用合适的颜色、标题、标签
- 高质量输出:设置DPI为300,确保清晰度
四、主程序整合(main.py)
将三个模块整合在一起,形成完整的处理流程:
python
from crawler import crawl_data
from data_cleaner import clean_data
from data_analyzer import analyze_data
def main():
"""主函数:执行完整的数据处理流程"""
print("=" * 60)
print("SMZDM 数据处理系统")
print("=" * 60)
# 配置参数
START_PAGE = 1
END_PAGE = 10
RAW_FILE = 'smzdm_raw.csv'
CLEANED_FILE = 'smzdm_cleaned.csv'
# 步骤1: 数据爬取
print("\n【步骤1】开始数据爬取...")
crawl_data(start_page=START_PAGE, end_page=END_PAGE,
output_file=RAW_FILE, delay=1)
# 步骤2: 数据清洗
print("\n【步骤2】开始数据清洗...")
clean_data(RAW_FILE, CLEANED_FILE)
# 步骤3: 数据分析
print("\n【步骤3】开始数据分析...")
analyze_data(CLEANED_FILE, 'analysis_results')
print("\n数据处理流程全部完成!")
if __name__ == '__main__':
main()
五、运行结果
运行程序后,会生成以下文件:
5.1 数据文件
smzdm_raw.csv:原始爬取数据smzdm_cleaned.csv:清洗后的数据
5.2 分析结果
- 价格分布图:展示商品价格的分布情况
- 互动数据图:展示点赞和评论的分布
- 热门商品Top10:展示最受欢迎的商品
- 高频词统计:展示商品标题中的热门词汇
- 统计报告:完整的数据统计分析报告
六、项目总结
6.1 技术要点
-
爬虫开发:
- API接口分析
- 请求头和参数设置
- 数据解析和存储
-
数据处理:
- 数据去重
- 字段提取和格式化
- 空值处理
-
数据可视化:
- 多种图表类型
- 中文显示处理
- 图表美化
6.2 注意事项
- 遵守法律法规:爬虫要遵守网站的robots.txt和法律法规
- 控制爬取频率:避免给服务器造成压力
- 错误处理:完善的异常处理机制
- 代码规范:遵循PEP8编码规范
6.3 扩展方向
- 添加数据库存储功能
- 实现定时任务自动爬取
- 开发Web界面展示结果
- 添加更多分析维度
- 实现实时监控功能
七、完整代码获取
完整的项目代码已上传至GitHub,包括:
- 完整源代码
- 依赖包列表
- 详细README文档
结语
通过本项目的学习,相信你已经掌握了完整的数据处理流程。数据处理是一个需要不断实践的技能,建议大家在掌握基础后,尝试处理不同类型的数据,不断提升自己的数据处理能力。
如果本文对你有帮助,欢迎点赞、收藏和分享!如有问题,欢迎在评论区留言讨论。
作者简介:Python开发爱好者,专注于数据分析和爬虫开发。
标签 :Python 爬虫 数据分析 数据可视化 pandas matplotlib jieba
分类专栏:Python数据分析实战