爬虫豆瓣电影

import requests
from bs4 import BeautifulSoup
from pandas import DataFrame

'''
    最后成功提取了
    '电影排名','电影名','上映时间','导演','主演','电影类型','电影评分','评价人数','电影链接'
    最后将结果输出到了 豆瓣电影Top250.xlsx 
    但是还存在问题:就是提取语言和制片国家/地区时,出现没有selector的情况。
    要解决该问题可能需要xpath
'''

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'}


start_num = [i for i in range(0, 226, 25)]

list_url_mv = []  # 所有电影的URL

for start in start_num:
    url = 'https://movie.douban.com/top250?start={}&filter='.format(start)
    print('正在处理url:', url)

    response = requests.get(url=url, headers=headers)
    soup = BeautifulSoup(response.text, 'html.parser')

    url_mv_list = soup.select('#content > div > div.article > ol > li > div > div.info > div.hd > a')
    # print(url_mv_list)
    for index_url in range(len(url_mv_list)):
        url_mv = url_mv_list[index_url]['href']
        list_url_mv.append(url_mv)
        # print(url_mv)


# 对每部电影进行处理
def loading_mv(url, number):
 list_mv = []
    print('-----正在处理第{}部电影-----'.format(number + 1))
    list_mv.append(number + 1)  # 排名

    # 解析网页
    response_mv = requests.get(url=url, headers=headers)
    soup_mv = BeautifulSoup(response_mv.text, 'html.parser')

    # 爬取电影名
    mv_name = soup_mv.find_all('span', attrs={'property': 'v:itemreviewed'})  # 电影名
    mv_name = mv_name[0].get_text()
    list_mv.append(mv_name)
    # print(mv_name)

    # 爬取电影的上映时间
    mv_year = soup_mv.select('span.year')  # 电影上映时间
    mv_year = mv_year[0].get_text()[1:5]
    list_mv.append(mv_year)
    # print(mv_year)

    # 爬取导演信息
    list_mv_director = []  # 导演
    mv_director = soup_mv.find_all('a', attrs={'rel': "v:directedBy"})
    for director in mv_director:
        list_mv_director.append(director.get_text())
    string_director = '/'.join(list_mv_director)  # 重新定义格式
    list_mv.append(string_director)
    # print(list_mv_director)

    # 爬取主演信息
    list_mv_star = []  # 主演
    mv_star = soup_mv.find_all('a', attrs={'rel': 'v:starring'})
    if mv_star == []:  # 在第210部时没有主演
        list_mv.append(None)
    else:
        mv_star = mv_star[0].get_text().strip().split('/')
        mv_first_star = mv_star[0].split(':')
        list_mv_star.append(mv_first_star[-1].strip())
        del mv_star[0]  # 去除'主演'字段
        for star in mv_star:
            list_mv_star.append(star.strip())
        string = '/'.join(list_mv_star)  
 list_mv.append(string)

    # 爬取电影类型
    list_mv_type = []  # 电影类型
    mv_type = soup_mv.find_all('span', attrs={'property': 'v:genre'})
    for type in mv_type:
        list_mv_type.append(type.get_text())
    string_type = '/'.join(list_mv_type)
    list_mv.append(string_type)
    # print(list_mv_type)

    # 爬取电影评分
    mv_score = soup_mv.select('strong.ll.rating_num')  # 评分
    mv_score = mv_score[0].get_text()
    list_mv.append(mv_score)

    # 爬取评价人数
    mv_evaluation_num = soup_mv.select('a.rating_people')  # 评价人数
    mv_evaluation_num = mv_evaluation_num[0].get_text().strip()
    list_mv.append(mv_evaluation_num)

    # 爬取剧情简介
    mv_plot = soup_mv.find_all('span', attrs={"class": "all hidden"})  # 剧情简介
    if mv_plot == []:
        list_mv.append(None)
    else:
        string_plot = mv_plot[0].get_text().strip().split()
        new_string_plot = ' '.join(string_plot)
        list_mv.append(new_string_plot)

    mv_pictures_url = soup_mv.find('a', class_='nbgnbg')
    if mv_pictures_url:
        img_tag = mv_pictures_url.find('img')
        if img_tag:
            mv_pictures_url = img_tag['src']
        else:
            mv_pictures_url = None
    else:
        mv_pictures_url = None

list_mv.append(mv_pictures_url)

return list_mv

    return list_mv
list_all_mv = []

dict_mv_info = {}
for number in range(len(list_url_mv)):
    mv_info = loading_mv(list_url_mv[number], number)
    list_all_mv.append(mv_info)
print('-----运行结束-----')

pd = DataFrame(list_all_mv, columns=['电影排名', '电影名', '上映时间', '导演', '主演', '电影类型', '电影评分', '评价人数', '电影简介', '电影链接'])
# print(pd)

pd.to_excel(r'D:\111\豆瓣电影Top250.xlsx')

import pandas as pd
import matplotlib.pyplot as plt
import re
import matplotlib as mpl
import wordcloud
import imageio

#读取Excel
print('----------读取Excel----------')
def excel_to_dataframe(excel_path):
    df = pd.read_excel(excel_path, keep_default_na=False)  # keep_default_na=False 得到的结果是'',而不是nan
    return df
excel_path = r'D:\111\豆瓣电影Top250.xlsx'
data_mv = excel_to_dataframe(excel_path)
rows_with_na = data_mv[data_mv.isnull().values]
print(rows_with_na)
print('')

#清洗数据
print('----------清洗数据----------')
df_cleaned=data_mv.dropna()
print(df_cleaned.info())
print(df_cleaned.head())
print('')
#读取前10部电影名
print('----------读取前10部电影名-----------')
movie_name=df_cleaned['电影名'][0:10]
print(movie_name)
m=[]
for mn in movie_name:
    mnlist=mn.split('/')
    m.append(mnlist[0].strip())
#读取前十部电影评分
ratelist=df_cleaned['电影评分'][0:10]
#任选10部电影名称-评分 柱状图
print('----------绘制10部电影名称-评分 柱状图----------')
#柱状图
def make_Histogram(list_x, list_y):
    # 解决中文显示问题
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    plt.bar(list_x, list_y)
    plt.title('电影名称-评分 柱状图')
    plt.xlabel('电影名')
    plt.ylabel('电影评分')
    plt.show()
make_Histogram(m,ratelist)

#任选4位导演-上榜电影数量 柱状图
print('----------任选4位导演-上榜电影数量 柱状图----------')
#提取导演和电影排名的数据
# 假设'导演'列名为'director'
directors = data_mv['导演']
#计算每位导演的上榜电影数量
director_counts = directors.value_counts().reset_index()
director_counts.columns = ['director', 'movie_count']
#对导演按照电影数量进行排序并取前四名
top_directors = director_counts.sort_values(by='movie_count', ascending=False).head(4)
#柱状图
def make_directors(list_x, list_y):
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    plt.figure(figsize=(10, 6))  # 设置图形大小
    plt.bar(list_x, list_y)
    plt.title('4位导演-上榜电影数量 柱状图')
    plt.xlabel('导演')
    plt.ylabel('上榜电影数量')
    plt.xticks(rotation=45)  # 如果导演名字很长,旋转x轴标签
    plt.tight_layout()  # 自动调整子图参数,使之填充整个图像区域
    plt.show() 
make_directors(top_directors['director'], top_directors['movie_count'])

top_movies = data_mv['电影名'].head(10).tolist()
selected_data = data_mv[data_mv['电影名'].isin(top_movies)]
# 绘制折线图比较评论人数
print('----------绘制折线图比较评论人数 折线图----------')
# 提取评论人数列中的整数部分
def extract_int_from_string(s):
    match = re.search(r'\d+', s)
    return int(match.group()) if match else 0
selected_data['评价人数'] = selected_data['评价人数'].apply(extract_int_from_string)  # 假设列名为'评价人数'
selected_data = selected_data.head(10)
# 绘制折线图
def make_evaluate():
    plt.figure(figsize=(12, 6))
    # 使用电影的索引作为x轴的位置(这里假设电影名已经是排序的)
    x_positions = selected_data.index
    # 绘制每部电影的评论人数
    plt.plot(x_positions, selected_data['评价人数'], marker='o', linestyle='-', color='blue')# 设置x轴的标签为电影名
    plt.ticklabel_format(style='plain', axis='y') # 设置y轴标签格式,禁用科学计数法
    plt.xticks(x_positions, selected_data['电影名'])
    # 设置中文标签
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    plt.title('10部电影的评论人数(折线图表示)')
    plt.xlabel('电影名')
    plt.ylabel('评价人数')
    # 旋转x轴标签以便更好地显示
    plt.xticks(rotation=45)
    # 显示图形
    plt.show()
make_evaluate()

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值