Python项目实战某瓣热门电影分析(爬虫数据分析)
项目需求获取某瓣前100名热门电影详细内容,包括:名称、类型、制片国家、语言、上映时间、片长、评分、评价人数。 根据获取的数据分析,包括:上映时间分布情况、评分分布情况、类型分布情况 项目难点获取数据时,有部分内容保存在
下,无法直接使用Xpath获取 上映时间有多个,按照国内上映时间分布,这里需要处理一下 类型分布中,一个电影多个类型,需要分解处理
这个是本文的重点。 数据抓取在进行实际的数据抓取的过程中,发现数据实际保存在Json数据包中,原网页无法获取,前100名电影的实际地址。 每一页只显示20个数据,且每次以20个为一组的新增。 Json我们需要的url数据保存在 ["subjects"][m]["url"] 中,其中m为循环,每一组循环20次。 代码实例获取前100名电影的实际url地址 def get_move_url(): move_url = [] for i in range(0,100,20): url = f"https://xxx.xxx.xxx/j/search_subjects?type=movie&tag=热门&sort=recommend&page_limit=20&page_start={i}" r_response = get(url=url,headers=headers).json() for m in range(20): move_url.append(r_response["subjects"][m]["url"]) return move_url根据每个url地址,获取相应的内容,注意br下内容、上映时间,这里全部处理,并保存excel文件。 def get_data(): move_url = get_move_url() df = pd.DataFrame(columns=["电影名","电影类型","制片国家","语言","上映时间","片长","评分","评价人数"]) for m in range(len(move_url)): r_resopnse = get(url=move_url[m],headers=headers).text res = Selector(r_resopnse) name = res.xpath("//*[@id="content"]/h1/span[1]/text()").get() move_type = res.xpath("*//span[@property="v:genre"]/text()").getall() # ! 上映时间需要处理,以第一个时间为基准,且还要去掉()里面的内容 move_time = res.xpath("*//span[@property="v:initialReleaseDate"]/text()").getall() move_time = Move_Time(move_time=move_time) move_len = res.xpath("*//span[@property="v:runtime"]/text()").get() move_len = Move_Len(move_len=move_len) move_score = res.xpath("//*[@id="interest_sectl"]/p[1]/p[2]/strong/text()").get() move_people_num = res.xpath("//*[@id="interest_sectl"]/p[1]/p[2]/p/p[2]/a/span/text()").get() # ! 语言与制片地区在
下,需要特殊处理 move_br = res.xpath("/html/body/p[3]/p[1]/p[2]/p[1]/p[1]/p[1]/p[1]/p[2]/descendant-or-self::text()").getall() for i in range(len(move_br)): if move_br[i] == "制片国家/地区:": country = move_br[i+1] # ? 去除里面所有的空格 move_country = country.replace(" ","") elif move_br[i] == "语言:": language = move_br[i+1] move_language = language.replace(" ","") # ! 后面就不需要了 break df.loc[m]=[name,move_type,move_country,move_language,move_time,move_len,move_score,move_people_num] df.to_excel("./result.xlsx",index=False) 上映时间的处理(以中国上映时间为基准,其他的取消) def Move_Time(move_time): # ? 以中国上映时间为基准,去掉()与里面中文的内容 time = re.sub("[一-龥]","",move_time[0]) # ? 测试时,发现有些数据不是很全面,用下列方法,多次删除无用数据 time = time.strip("(").strip(")").strip(r"/").strip("(") return time时长处理,取消 分钟和() def Move_Len(move_len): # ! 注意 时长类型 byte 需要修改为 str len = re.sub("[一-龥]","",str(move_len)) len = len.strip("()") return len 数据分析 上映时间分布
df2 = df["上映时间"].value_counts() 评分情况分布 plt.figure(figsize=(20,8),dpi=80) plt.hist(df["评分"].values,bins=20) max_ = df["评分"].max() min_ = df["评分"].min() t1 = np.linspace(min_,max_,21) plt.xticks(t1) plt.show()电影类型分布(重点) # ! 电影类型分布 move_type = df["电影类型"].str.split(",") move_type = move_type.apply(pd.Series) move_type = move_type.apply(pd.value_counts) move_type.unstack() move_type = move_type.unstack().dropna().reset_index() move_type.columns =["level_0","type","counts"] movie_type_m = move_type.drop(["level_0"],axis=1).groupby("type").sum().sort_values(by=["counts"],ascending=False).reset_index() # print(movie_type_m["counts"].to_list()) size= movie_type_m["counts"].to_list() name = movie_type_m["type"].to_list() colors = ["steelblue","#9999ff","red","indianred", "green","yellow","orange"] plot = squarify.plot( sizes=size, # 指定绘图数据 color = colors,# 指定 定义颜 label=name,# 指定标签 value=size,# 添加数值标签 alpha = 0.6,# 指定透明度 edgecolor = "white",# 设置边界框为 linewidth =3 # 设置边框宽度为3 ) plt.rc("font", size=12) # 设置标题 plot.set_title("电影类型分布情况",fontdict = {"fontsize":20}) # 去除坐标轴 plt.axis("off") # 去除上边框和右边框刻度 plt.tick_params(top = "off", right = "off") plt.rcParams["font.sans-serif"]=["SimHei"] plt.rcParams["axes.unicode_minus"] = False # 显 图形 plt.show()重点提示显示中文时,出现了中文乱码的情况,这里给出处理方法 plt.rcParams["font.sans-serif"]=["SimHei"] plt.rcParams["axes.unicode_minus"] = False获取br里的内容是全部的,需要根据实际情况分析,获取指定内容 move_br = res.xpath("/html/body/p[3]/p[1]/p[2]/p[1]/p[1]/p[1]/p[1]/p[2]/descendant-or-self::text()").getall() for i in range(len(move_br)): if move_br[i] == "制片国家/地区:": country = move_br[i+1] # ? 去除里面所有的空格 move_country = country.replace(" ","") elif move_br[i] == "语言:": language = move_br[i+1] move_language = language.replace(" ","") # ! 后面就不需要了 break在数据获取时,发现了一些数据缺失的情况,这里没有进行处理,后续需要修正 在进行电影类型分类分析时,存在 科幻感 [科幻] 同时存在的情况,这里没有处理,后续需要更正 未对每个类型的评分情况,进行分析,后续需要添加,在此记录一下。