Python 实现 SMZDM 数据处理系统:从爬虫到数据分析
使用 Python 构建 SMZDM 数据处理系统,涵盖数据爬取、清洗、分析及可视化全流程。项目基于 requests 库分析 API 接口进行 POST 请求抓取商品数据,利用 pandas 进行去重、格式化及空值处理,并通过 matplotlib 和 seaborn 展示价格分布、互动趋势及高频词统计。核心模块包括爬虫、清洗与分析,强调反爬策略、错误处理及代码规范,适用于学习端到端数据工程实践。

使用 Python 构建 SMZDM 数据处理系统,涵盖数据爬取、清洗、分析及可视化全流程。项目基于 requests 库分析 API 接口进行 POST 请求抓取商品数据,利用 pandas 进行去重、格式化及空值处理,并通过 matplotlib 和 seaborn 展示价格分布、互动趋势及高频词统计。核心模块包括爬虫、清洗与分析,强调反爬策略、错误处理及代码规范,适用于学习端到端数据工程实践。

在大数据时代,数据获取、清洗和分析已成为数据分析师和开发者必备的技能。本文将通过一个完整的实战项目,带你学习如何使用 Python 实现一个完整的数据处理系统,包括数据爬取、清洗、分析和可视化。
本项目以 SMZDM(什么值得买)网站为例,实现了一个端到端的数据处理流程。通过学习本项目,你将掌握:
本项目是一个完整的 Python 数据处理系统,主要功能包括:
python_excel/
├── crawler.py # 数据爬取模块
├── data_cleaner.py # 数据清洗模块
├── data_analyzer.py # 数据分析模块
├── main.py # 主程序入口
└── requirements.txt # 依赖包列表
确保你的系统已安装 Python 3.7 或更高版本。可以通过以下命令检查:
python --version
创建 requirements.txt 文件,内容如下:
requests>=2.31.0
pandas>=2.0.0
matplotlib>=3.7.0
seaborn>=0.12.0
jieba>=0.42.1
然后执行:
pip install -r requirements.txt
数据爬取是整个数据处理流程的第一步。我们需要分析目标网站的 API 接口,然后编写爬虫代码。
通过浏览器开发者工具,我们发现 SMZDM 使用了 API 接口来获取数据。主要的请求信息如下:
https://damo.smzdm.com/interest/more_pageimport 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
原始数据往往包含很多问题,需要进行清洗处理。
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
re 模块提取和匹配模式drop_duplicates() 去重apply() 函数批量处理数据数据清洗完成后,就可以进行深度分析和可视化了。
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("数据分析完成!")
将三个模块整合在一起,形成完整的处理流程:
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()
运行程序后,会生成以下文件:
smzdm_raw.csv:原始爬取数据smzdm_cleaned.csv:清洗后的数据
微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online