从大众点评评论到文本分析:一个完整的数据挖掘项目流程

在数字化时代,用户评论数据已成为商业决策的重要依据。以餐饮行业为例,大众点评平台积累了海量用户评价,这些非结构化的文本数据蕴含着消费者偏好、服务质量、产品口碑等宝贵信息。本文将带领读者从零开始,完成一个完整的文本挖掘项目,涵盖数据采集、清洗存储到初步分析的每个环节,为初学者提供端到端的实战指南。

1. 数据采集:高效爬虫设计与实现

获取大众点评评论数据是项目的第一步,需要解决反爬机制、数据解析等核心问题。不同于简单的网页抓取,商业平台的评论采集需要更精细的策略。

1.1 网页结构与URL分析

大众点评的评论页面遵循特定URL模式:

http://www.dianping.com/shop/[店铺ID]/review_all/p[页码]

每个店铺有唯一ID,评论分页显示,每页约20条。通过分析多个店铺,我们发现页面结构具有以下特征:

  • 用户信息包含在<a class="name">标签中
  • 评论内容位于<div class="review-words">
  • 评分通过<span class="sml-rank-stars">的class属性表示

关键解析代码示例

from bs4 import BeautifulSoup
import re

def parse_page(html):
    soup = BeautifulSoup(html, 'html.parser')
    comments = []
    for item in soup.find_all('div', 'main-review'):
        try:
            comment = {
                'user': item.find('a', 'name').get_text(strip=True),
                'time': item.find('span', 'time').get_text(strip=True),
                'content': item.find('div', 'review-words').get_text(strip=True),
                'rating': item.find('span', class_=re.compile('sml-rank-stars'))['class'][1]
            }
            comments.append(comment)
        except Exception as e:
            print(f"解析出错: {e}")
    return comments

1.2 反爬策略实战方案

大众点评采用多层次反爬机制,需要组合应对策略:

反爬类型解决方案实现要点
UA检测动态User-Agent使用fake_useragent库轮换
频率限制随机延迟time.sleep(random.uniform(3,8))
Cookie验证会话保持获取有效Cookie并定期更新
IP限制代理IP池付费代理服务更稳定

提示:实际项目中建议控制爬取速度在每分钟5-8次请求,避免触发风控系统。

2. 数据存储:MySQL优化实践

采集到的数据需要持久化存储,关系型数据库适合结构化评论数据的长期管理。

2.1 数据库设计规范

创建符合第三范式的数据表结构:

CREATE TABLE `shop_reviews` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `shop_id` varchar(20) NOT NULL COMMENT '店铺ID',
  `user_id` varchar(50) DEFAULT NULL COMMENT '用户ID',
  `review_time` datetime DEFAULT NULL COMMENT '评论时间',
  `rating` tinyint(1) DEFAULT NULL COMMENT '评分(1-5星)',
  `content` text COMMENT '评论内容',
  `taste_score` varchar(10) DEFAULT NULL COMMENT '口味评分',
  `env_score` varchar(10) DEFAULT NULL COMMENT '环境评分',
  `service_score` varchar(10) DEFAULT NULL COMMENT '服务评分',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `idx_shop` (`shop_id`),
  KEY `idx_time` (`review_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

2.2 高效批处理写入

使用pymysql的executemany方法提升写入效率:

import pymysql
from contextlib import contextmanager

@contextmanager
def mysql_connection():
    conn = pymysql.connect(
        host='localhost',
        user='root',
        password='your_password',
        database='review_db',
        charset='utf8mb4'
    )
    try:
        yield conn
    finally:
        conn.close()

def batch_insert(comments):
    sql = """INSERT INTO shop_reviews 
             (shop_id, user_id, review_time, rating, content) 
             VALUES (%s, %s, %s, %s, %s)"""
    with mysql_connection() as conn:
        with conn.cursor() as cursor:
            cursor.executemany(sql, comments)
        conn.commit()

3. 文本预处理关键技术

原始评论数据包含大量噪声,需要进行系统清洗才能用于分析。

3.1 中文文本清洗流程

  1. 编码统一化:转换所有文本为UTF-8编码
  2. 特殊字符处理:移除表情符号、HTML标签等非文本内容
  3. 文本规范化
    • 繁体转简体
    • 全角转半角
    • 拼音/英文处理

清洗函数示例

import re
from zhon.hanzi import punctuation

def clean_text(text):
    # 移除HTML标签
    text = re.sub(r'<[^>]+>', '', text)
    # 移除特殊符号
    text = re.sub(f'[{punctuation}]+', '', text)
    # 合并连续空格
    text = re.sub(r'\s+', ' ', text)
    return text.strip()

3.2 中文分词与停用词处理

使用jieba分词结合自定义词典提升效果:

import jieba
from jieba import analyse

# 加载自定义词典
jieba.load_userdict('custom_dict.txt')

def tokenize(text):
    words = jieba.lcut(text)
    # 加载停用词表
    with open('stopwords.txt', encoding='utf-8') as f:
        stopwords = set(f.read().splitlines())
    return [w for w in words if w not in stopwords]

4. 基础分析方法与可视化

完成数据准备后,可以开展多种维度的分析挖掘用户反馈价值。

4.1 评分分布分析

使用pandas快速计算评分统计数据:

import pandas as pd
import matplotlib.pyplot as plt

df = pd.read_sql('SELECT rating, COUNT(*) as count FROM shop_reviews GROUP BY rating', con=conn)
plt.bar(df['rating'], df['count'])
plt.title('评分分布')
plt.xlabel('星级')
plt.ylabel('评论数')
plt.show()

4.2 词云与关键词提取

通过词频分析发现消费者关注点:

from wordcloud import WordCloud
from collections import Counter

text = ' '.join(df['content'].tolist())
words = tokenize(text)
word_freq = Counter(words)

wc = WordCloud(
    font_path='simhei.ttf',
    background_color='white',
    max_words=100
).generate_from_frequencies(word_freq)

plt.imshow(wc)
plt.axis('off')
plt.show()

4.3 情感分析初步

基于SnowNLP实现简单情感倾向分析:

from snownlp import SnowNLP

def analyze_sentiment(text):
    s = SnowNLP(text)
    return s.sentiments

df['sentiment'] = df['content'].apply(analyze_sentiment)
print(df.groupby('rating')['sentiment'].mean())

5. 项目优化与扩展方向

基础流程完成后,可以考虑以下进阶优化方案:

  1. 分布式爬虫架构

    • 使用Scrapy-Redis实现分布式爬取
    • 结合RabbitMQ实现任务队列
  2. 数据质量监控

    # 数据完整性检查
    def check_data_quality(df):
        missing = df.isnull().sum()
        dup_rate = df.duplicated().mean()
        return pd.DataFrame({
            'missing': missing,
            'dup_rate': dup_rate
        })
    
  3. 分析模型升级

    • 使用BERT等预训练模型提升情感分析准确率
    • 引入LDA主题模型发现潜在话题

实际项目中,我们发现在处理10万条以上评论时,使用Dask替代Pandas可以显著提升处理效率。对于需要长期运行的系统,建议将核心流程封装为Airflow任务,实现自动化调度。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐