爬取豆瓣应该是每个萌新学习爬虫要爬的第一个网站吧,谁让豆瓣的网页写的这么规范吗(哈哈哈哈哈哈哈哈),长话短说,整起!
爬取目标:爬取影片片名、影片链接、影片上映日期、影片上映地点、影片导演、影片主演、类型、评分、评价人数、好评率、影片评价
输入:豆瓣top250url(https://movie.douban.com/top250)
输出:包含影片信息的excel表格
技术路线: 爬取:使用了request库对网页信息进行整体爬取
解析:使用parsel+xpath和bs4+re库进行解析
保存:xlwt库进行excel写入和保存操作
数据分析:通过pyecharts库与百度上的开源库Echarts进行对接,对爬取到的数据进行数据可视化分析
代码1(影片信息的爬取):
import requests #发起请求,指定url,获取网页数据
import re
from bs4 import BeautifulSoup #从bs4库中调用BeautifulSoup
import xlwt
import parsel
def main():
url = 'https://movie.douban.com/top250?start='
#获取解析数据
datalist = getdata(url)
#保存数据
savapath = r'F:\pycharm\project1\core豆瓣Top2501.xls'
saveData(datalist, savapath)
findnlink = re.compile(r'<a class="" href="(.*?)">') #影片链接
findtitle = re.compile(r'<span property="v:itemreviewed">(.*?)</span>') #影片片名
finddirector = re.compile(r'<a href=".*?" rel="v:directedBy">(.*?)</a>') #导演
findactor = re.compile(r'<a href=".*?" rel="v:starring">(.*?)</a>') #主演
findtype = re.compile(r'<span property="v:genre">(.*?)</span>') #类型
findscore = re.compile(r'<strong class="ll rating_num" property="v:average">(.*?)</strong>') #评分
findpeople = re.compile(r'<span property="v:votes">(.*?)</span>') #观看人数
findrate = re.compile(r'<span class="rating_per">(.*?)%</span>') #好评率
findcomment = re.compile(r'<span class="short">(.*?)</span>') #评论
findtime = re.compile(r'<span class="year">(.*?)</span>')
# findintro = re.compile(r'<span property="v:summary" >(.*?)</span>',re.S)
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.9 Safari/537.36'}
def askurl(url): #反爬虫,模拟浏览器头部信息,向豆瓣发送消息
res = requests.get(url, headers=headers)
res.encoding = 'utf-8'#代码转译
html = res.text
# print(html)
return html
# 获取解析数据
def getdata(url):
nlinklist = []
for i in range(0,1): #一共10页
sumurl = url + str(i*25) #每页25个数据
html = askurl(sumurl)
#解析
soup = BeautifulSoup(html,'html.parser')
for hd in soup.find_all('div',class_="hd"):
hd = str(hd)
nlink = re.findall(findnlink,hd)[0]
nlinklist.append(nlink)
# print(nlink)
datalist = []
for j in range(0,25):
data = []
link = nlinklist[j]
data.append(link)
# print(link)
html1 = askurl(link)
datas = parsel.Selector(html1)
# print(html1)
soup = BeautifulSoup(html1,"html.parser")
for id in soup.find_all('div',id="content"):
ids = str(id)
title = re.findall(findtitle,ids)[0] #影片片名
data.append(title)
# print(title)
time = re.findall(findtime, ids)[0] #影片上映日期
time = time.replace('(', ' ') #删除左括号
time = time.replace(')', ' ') #删除右括号
data.append(time)
place = datas.xpath('//span[@property="v:initialReleaseDate"]/text()').extract()[0] #影片上映地点
place = place[11:].replace(')', ' ')
# print(place)
data.append(place)
director = re.findall(finddirector,ids)[0] #影片导演
data.append(director)
# print(director)
actor = re.findall(findactor,ids) #影片主演
data.append(actor[0:3])
# print(actor[0:3])
type = re.findall(findtype,ids) #影片类型
data.append(type[0:2])
# print(type[0:2])
score = re.findall(findscore,ids)[0] #影片评分
data.append(score)
# print(score)
people = re.findall(findpeople,ids)[0] #影片观看人数
data.append(people)
# print(people)
rate = re.findall(findrate,ids)[0] #好评率
data.append(rate)
# print(rate)
comment = re.findall(findcomment,ids) #影片评价
data.append(comment[0:5])
# print(comment[0:5])
datalist.append(data)
return datalist
#保存数据
def saveData(datalist,savapath):
workbook = xlwt.Workbook(encoding='utf-8',style_compression=0)#创建对象
worksheet = workbook.add_sheet('TOP250',cell_overwrite_ok=True)#创建工作表
col =('电影详情链接','影片中文名及外文名','影片上映日期','国家/地区','影片导演','影片主演','影片类型','影片评分','观看人数','好评率/%','评价')
for j in range(0, 11):
worksheet.write(0,j,col[j]) #列名
for i in range(0,25):
data = datalist[i]
print("第%d条"%(i+1))
for j in range(0,11):
worksheet.write(i+1,j,data[j]) #数据
workbook.save(savapath)
if __name__ == '__main__':
main()
print("爬取完毕")
代码2(对影片数据进行可视化分析)
from pyecharts import options as opts #设置参数
from pyecharts.charts import Pie #饼状图
from pyecharts.charts import Scatter #散点图
from pyecharts.charts import WordCloud #词云
from pyecharts.charts import Bar #柱状图
import pandas as pd
def score(): #创建饼图函数
df_score = df.groupby("影片评分").size().sort_values(ascending=False) # 按照影片评分这一列进行分组,并且查看size数量,同时进行降序排列
datas = list(zip(df_score.index.to_list(), df_score.to_list()))
title = "饼图-评分"
pie = ( #创建一个pie对象
Pie()
.add("",datas) #添加数据
.set_global_opts( #设置全局参数
title_opts=opts.TitleOpts(title=title), #设置标题
legend_opts=opts.LegendOpts(pos_right="right"), #设置标签
)
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{c}:{d}%"))#在每个扇区展现名称数量百分比
)
pie.render("饼图-影片评分.html")
def people_rate(): #创建好评率-观看人数散点图
df.sort_values(by="好评率/%",inplace=True) #将好评率进行升序排列
rate = df["好评率/%"].to_list() #将好评率一列数据提取出来
people = df["观看人数"].to_list() #将观看人数一列数据提取出来
scatter = (
Scatter()
.add_xaxis(
xaxis_data=rate #x轴的数据
)
.add_yaxis(
series_name="观看人数", #图例
y_axis=people, #y轴数据
symbol_size=7,#点大小
label_opts=opts.LabelOpts(is_show=False) #不展示点对应的数据
)
.set_global_opts( #全局变量
xaxis_opts=opts.AxisOpts(type_="value"), #x,y轴的数据都当作数字来处理
yaxis_opts=opts.AxisOpts(type_="value"),
title_opts=opts.TitleOpts(title="(好评率-观看人数)关系图"),#标题居中展示
visualmap_opts=opts.VisualMapOpts(type_="color", max_=2020000, min_=190000,dimension=1),
)
)
scatter.render("散点图-好评率-观看人数.html")
def type():#创建影片类型词云图
df_type = df.groupby("影片类型").size().sort_values(ascending=False) # 按照影片评分这一列进行分组,并且查看size数量,同时进行降序排列
data = list(zip(df_type.index.to_list(), df_type.to_list()))
print(data)
cloud = (
WordCloud()
.add(series_name="影片类型", data_pair=data, word_size_range=[12, 100])
.set_global_opts(
title_opts=opts.TitleOpts(
title="影片类型分析", title_textstyle_opts=opts.TextStyleOpts(font_size=23)
),
tooltip_opts=opts.TooltipOpts(is_show=True),
)
)
cloud.render("词云图-影片类型.html")
def time():
df.sort_values(by="影片上映日期", inplace=True)
df_type = df.groupby("影片上映日期").size()
print(df_type)
x = []
y = []
data = list(zip(df_type.index.to_list(), df_type.to_list()))
print(data)
for i in range(0,len(data)):
datas = data[i]
x.append(datas[0])
y.append(datas[1])
bar = (
Bar()
.add_xaxis(x
)
.add_yaxis("年份:数量",y)
.set_global_opts(
xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=-15)),#标签角度-15
title_opts=opts.TitleOpts(title="影片年份" ),
datazoom_opts=[opts.DataZoomOpts(), opts.DataZoomOpts(type_="inside")],#可缩放
)
)
bar.render("柱状图-影片年份.html")
if __name__ == '__main__':
df = pd.read_excel('F:\pycharm\project1\core豆瓣Top250.xls')
score()
people_rate()
type()
time()
好啦,对豆瓣top250信息的爬取基本上就是这样啦,读者如有问题,可以留言哦!
大家还可以关注一下我自己的公众号,里面定期会推送一些python的小项目,大家可以一起学习交流呀!