Bootstrap

python爬虫项目(一百一十三):票务网站演出信息爬取及票价走势分析

引言

随着文娱行业的迅速发展,票务网站成为了购票的主要渠道。对于演出行业而言,掌握票价走势和演出信息至关重要。本文将详细介绍如何抓取票务网站的演出信息,并分析票价走势。我们将使用Python编程语言,并结合现代的爬虫技术实现这个过程。

目录

引言

1. 数据需求与目标网站

1.1 数据需求

2. 确定抓取策略

2.1 分析目标网页

2.2 确定爬取方式

3. 环境准备

4. 数据抓取

4.1 使用requests和BeautifulSoup进行数据抓取

4.1.1 导入库并设置请求头

4.1.2 抓取演出信息

4.2 抓取多个页面

5. 数据清洗与存储

5.1 数据清洗

5.2 数据存储

6. 数据分析

6.1 基本统计分析

6.2 可视化分析

7. 票价走势分析

7.1 时间序列分析

7.2 演出类型分析

8. 预测模型构建

8.1 数据准备

8.2 选择模型

8.3 进行预测

8.4 评估模型性能

9. 高级分析与模型优化

9.1 结合更多特征进行预测

9.2 使用更复杂的算法

10. 结论

附录

完整代码示例


1. 数据需求与目标网站

1.1 数据需求

在进行演出信息抓取时,我们希望获取以下信息:

  • 演出名称:演出的标题或名称。
  • 演出日期:演出的具体日期。
  • 演出地点:演出所在的地点或场馆。
  • 票价:不同票种的价格信息。
  • 可用座位:演出可供出售的座位信息。
  • 演出类型:如音乐会、话剧、舞蹈等。

2. 确定抓取策略

2.1 分析目标网页

使用浏览器的开发者工具,分析猫眼电影的演出信息页面,确定所需信息的HTML结构。我们需要抓取的演出信息通常在特定的标签和类名下。

2.2 确定爬取方式

猫眼电影有一定的反爬虫机制,因此我们需要模拟浏览器请求,使用requestsBeautifulSoup库进行数据抓取。

3. 环境准备

在开始编写代码之前,请确保安装以下Python库:

pip install requests beautifulsoup4 pandas matplotlib seaborn

4. 数据抓取

4.1 使用requests和BeautifulSoup进行数据抓取

4.1.1 导入库并设置请求头
 
import requests
from bs4 import BeautifulSoup
import pandas as pd

# 设置请求头
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'
}

4.1.2 抓取演出信息

我们定义一个函数来抓取指定页面的演出信息。

 
def fetch_show_data(page_url):
    response = requests.get(page_url, headers=headers)
    soup = BeautifulSoup(response.text, 'html.parser')

    shows = []
    for item in soup.find_all('div', class_='show-info'):
        title = item.find('h3', class_='show-title').text.strip()
        date = item.find('span', class_='show-date').text.strip()
        venue = item.find('span', class_='show-venue').text.strip()
        price = item.find('span', class_='show-price').text.strip()

        shows.append({
            'title': title,
            'date': date,
            'venue': venue,
            'price': price
        })

    return shows

# 示例抓取
url = 'https://maoyan.com/show'
shows_data = fetch_show_data(url)
print(shows_data)

4.2 抓取多个页面

对于分页抓取,我们可以在函数中添加分页逻辑。

 
def fetch_all_shows(base_url, pages):
    all_shows = []
    for page in range(1, pages + 1):
        page_url = f'{base_url}?page={page}'
        shows = fetch_show_data(page_url)
        all_shows.extend(shows)
    
    return all_shows

# 抓取多页数据
base_url = 'https://maoyan.com/show'
all_shows_data = fetch_all_shows(base_url, 5)
print(f'总共抓取到的演出数据: {len(all_shows_data)}')

5. 数据清洗与存储

5.1 数据清洗

抓取完成后,我们需要对数据进行清洗,包括处理缺失值和转换数据类型。

 
# 转换为DataFrame
df_shows = pd.DataFrame(all_shows_data)

# 检查缺失值
print(df_shows.isnull().sum())

# 处理缺失值
df_shows.fillna('N/A', inplace=True)

# 处理票价为数字类型
df_shows['price'] = df_shows['price'].str.replace('元', '').astype(float)

5.2 数据存储

将抓取的数据保存到CSV文件中,以便后续分析和处理。

 
# 保存到CSV文件
df_shows.to_csv('shows_data.csv', index=False)
print('演出数据已保存为shows_data.csv')

6. 数据分析

6.1 基本统计分析

对演出的基本信息进行统计分析,包括票价分布、演出类型等。

 
# 读取数据
df_shows = pd.read_csv('shows_data.csv')

# 基本统计信息
stats = df_shows.describe()
print(stats)

# 票价分布
price_distribution = df_shows['price'].value_counts()
print(price_distribution)

6.2 可视化分析

使用Matplotlib和Seaborn可视化演出的票价走势和数量分布。

 
import matplotlib.pyplot as plt
import seaborn as sns

# 设置绘图风格
sns.set(style="whitegrid")

# 绘制票价分布图
plt.figure(figsize=(12, 6))
sns.histplot(df_shows['price'], bins=20, kde=True)
plt.title('演出票价分布')
plt.xlabel('票价 (元)')
plt.ylabel('数量')
plt.show()

7. 票价走势分析

7.1 时间序列分析

我们可以按日期分析票价走势。

 
# 将日期列转换为日期类型
df_shows['date'] = pd.to_datetime(df_shows['date'])

# 按日期分组,计算平均票价
price_trend = df_shows.groupby('date')['price'].mean().reset_index()

# 绘制票价走势图
plt.figure(figsize=(14, 7))
plt.plot(price_trend['date'], price_trend['price'], label='平均票价', color='blue')
plt.title('演出票价走势')
plt.xlabel('日期')
plt.ylabel('平均票价 (元)')
plt.legend()
plt.show()

7.2 演出类型分析

对不同演出类型的票价进行分析和可视化。

 
# 演出类型分布
plt.figure(figsize=(12, 6))
sns.boxplot(x='venue', y='price', data=df_shows)
plt.title('不同场馆演出票价对比')
plt.xlabel('场馆')
plt.ylabel('票价 (元)')
plt.xticks(rotation=45)
plt.show()

8. 预测模型构建

8.1 数据准备

为了构建预测模型,我们需要选择适合的特征,并将数据拆分为训练集和测试集。

 
from sklearn.model_selection import train_test_split

# 选择特征和目标
features = df_shows[['date', 'venue']]
target = df_shows['price']

# 将日期转为数值型
features['date'] = features['date'].map(pd.Timestamp.toordinal)

# 拆分数据集
X_train, X_test, y_train, y_test = train_test_split(features, target, test_size=0.2, random_state=42)

8.2 选择模型

我们将使用线性回归模型进行票价预测。

from sklearn.linear_model import LinearRegression

# 初始化模型
model = LinearRegression()

# 训练模型
model.fit(X_train, y_train)

8.3 进行预测

使用训练好的模型进行票价预测。

 
# 进行预测
predictions = model.predict(X_test)

# 将预测结果与真实结果进行对比
predicted_df = pd.DataFrame({'真实票价': y_test, '预测票价': predictions})
print(predicted_df.head())

8.4 评估模型性能

使用均方误差(MSE)和决定系数(R²)来评估模型的性能。

 
from sklearn.metrics import mean_squared_error, r2_score

# 计算均方误差和R²
mse = mean_squared_error(y_test, predictions)
r2 = r2_score(y_test, predictions)

print(f'均方误差: {mse}')
print(f'R²: {r2}')

9. 高级分析与模型优化

9.1 结合更多特征进行预测

可以引入更多特征,如演出类型、城市等,构建更复杂的模型。

9.2 使用更复杂的算法

尝试使用随机森林、XGBoost等更复杂的算法,提高预测的准确性。

 
from sklearn.ensemble import RandomForestRegressor

# 初始化随机森林模型
rf_model = RandomForestRegressor(n_estimators=100, random_state=42)

# 训练模型
rf_model.fit(X_train, y_train)

# 进行预测
rf_predictions = rf_model.predict(X_test)

# 计算评估指标
rf_mse = mean_squared_error(y_test, rf_predictions)
rf_r2 = r2_score(y_test, rf_predictions)

print(f'随机森林均方误差: {rf_mse}')
print(f'随机森林 R²: {rf_r2}')

10. 结论

本文详细介绍了如何使用Python抓取票务网站的演出信息,并进行票价走势分析。我们使用requestsBeautifulSoup库完成了数据的抓取,通过数据清洗和分析,获得了有价值的见解。此外,我们还构建了基本的预测模型,并探讨了如何通过引入更多特征和使用更复杂的算法来提高预测效果。

在未来的工作中,可以考虑以下方向:

  • 数据更新:定期更新抓取的数据,以保持分析的时效性。
  • 模型改进:探索更多的机器学习和深度学习算法,提高票价预测的准确性。
  • 用户界面:为数据分析结果开发用户友好的可视化界面,方便用户查看和使用分析结果。

希望本文能为读者在票务数据分析方面提供有价值的参考。如有疑问或进一步讨论,请随时联系我!

附录

完整代码示例

 
import requests
from bs4 import BeautifulSoup
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.ensemble import RandomForestRegressor

# 设置请求头
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'
}

# 抓取演出信息
def fetch_show_data(page_url):
    response = requests.get(page_url, headers=headers)
    soup = BeautifulSoup(response.text, 'html.parser')

    shows = []
    for item in soup.find_all('div', class_='show-info'):
        title = item.find('h3', class_='show-title').text.strip()
        date = item.find('span', class_='show-date').text.strip()
        venue = item.find('span', class_='show-venue').text.strip()
        price = item.find('span', class_='show-price').text.strip()

        shows.append({
            'title': title,
            'date': date,
            'venue': venue,
            'price': price
        })

    return shows

# 抓取多个页面
def fetch_all_shows(base_url, pages):
    all_shows = []
    for page in range(1, pages + 1):
        page_url = f'{base_url}?page={page}'
        shows = fetch_show_data(page_url)
        all_shows.extend(shows)
    
    return all_shows

# 数据处理
base_url = 'https://maoyan.com/show'
all_shows_data = fetch_all_shows(base_url, 5)

# 转换为DataFrame
df_shows = pd.DataFrame(all_shows_data)
df_shows.fillna('N/A', inplace=True)
df_shows['price'] = df_shows['price'].str.replace('元', '').astype(float)
df_shows['date'] = pd.to_datetime(df_shows['date'])

# 保存到CSV文件
df_shows.to_csv('shows_data.csv', index=False)

# 可视化票价分布
plt.figure(figsize=(12, 6))
sns.histplot(df_shows['price'], bins=20, kde=True)
plt.title('演出票价分布')
plt.xlabel('票价 (元)')
plt.ylabel('数量')
plt.show()

# 时间序列分析
price_trend = df_shows.groupby('date')['price'].mean().reset_index()
plt.figure(figsize=(14, 7))
plt.plot(price_trend['date'], price_trend['price'], label='平均票价', color='blue')
plt.title('演出票价走势')
plt.xlabel('日期')
plt.ylabel('平均票价 (元)')
plt.legend()
plt.show()

# 数据准备
features = df_shows[['date', 'venue']]
target = df_shows['price']
features['date'] = features['date'].map(pd.Timestamp.toordinal)
X_train, X_test, y_train, y_test = train_test_split(features, target, test_size=0.2, random_state=42)

# 线性回归模型
model = LinearRegression()
model.fit(X_train, y_train)
predictions = model.predict(X_test)

# 评估模型
mse = mean_squared_error(y_test, predictions)
r2 = r2_score(y_test, predictions)
print(f'线性回归均方误差: {mse}, R²: {r2}')

# 随机森林模型
rf_model = RandomForestRegressor(n_estimators=100, random_state=42)
rf_model.fit(X_train, y_train)
rf_predictions = rf_model.predict(X_test)

# 评估随机森林模型
rf_mse = mean_squared_error(y_test, rf_predictions)
rf_r2 = r2_score(y_test, rf_predictions)
print(f'随机森林均方误差: {rf_mse}, R²: {rf_r2}')

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;