ImageVerifierCode 换一换
格式:DOCX , 页数:14 ,大小:2.98MB ,
资源ID:9678449      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/9678449.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(摆脱剧荒教你用Python爬取豆瓣电影最新榜单.docx)为本站会员(b****8)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

摆脱剧荒教你用Python爬取豆瓣电影最新榜单.docx

1、摆脱剧荒教你用Python爬取豆瓣电影最新榜单作者 | 吹牛Z来源 | 数据不吹牛 【导读】本文以豆瓣电影(非TOP250)为例,从数据爬取、清洗与分析三个维度入手,详解和还原数据爬取到分析的全链路。阅读全文大概需要5分钟,想直接看结果或下载源码+数据集的旁友可以空降到文末。旁友,暑假,已经过了一大半了。这个遥远而炙热的名词,虽然和小Z这个上班狗已经没有任何关系,但在房间穿着裤衩,吹着空调,吃着西瓜,看着电影,依然是假期最好的打开方式。现在裤衩、空调、西瓜都唾手可得,压力全在电影这边了。关于电影推荐和排行,豆瓣是个好地方,只是电影TOP250排名实在是太经典,经典到有点老套了。小Z想来点新花样

2、,于是按默认的“评分最高”来排序,Emmm,结果好像比较小众:又按年代进行筛选,发现返回的结果和预期差的更远了。怎么办捏?不如我们自己对豆瓣电影进行更全面的爬取和分析,再DIY评分规则,结合电影上映年代做一个各年代TOP100电影排行榜。数据爬取1、网址规律探究听说看的人越多,评分越有说服力,所以我们进入导航页,选择“标记最多”。(虽然标记的多并不完全等于看的多,但也差不多了)要找到网址变化规律,常规的套路就是先右键“审查元素”,然后通过不断的点击“加载更多”刷新页面的方式来找规律。网址规律异常的简单,开头URL不变,每翻一页,start的数值增加20就OK了。一页是20部电影,开头我们立下的

3、FLAG是要爬取9000部电影,也就是爬取450页。2、单页解析+循环爬取豆瓣灰常贴心,每一页都是JSON格式存储的规整数据,爬取和清洗都省了不少事儿:这里我们只需要伪装一下headers里面的user-agent就可以愉快的爬取了:headers = User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/63.0.3239.132 Safari/537.36直接上单页解析的代码:def parse_baxxxxse_info(urlheaders): html =

4、 requests.get(urlheaders = headers) bs = json.loads(html.text) df = pd.Datafrxxxxame()for i in bsdata: casts = icasts #主演 cover = icover #海报 directors = idirectors #导演 m_id = iid #ID rate = irate #评分 star = istar #标记人数 title = ititle #片名 url = iurl #网址 cache = pd.Datafrxxxxame(主演:casts海报:cover导演:dir

5、ectorsID:m_id评分:rate标记:star片名:title网址:url) df = pd.concat(dfcache)return df然后我们写一个循环,构造所需的450个基础网址:#你想爬取多少页,其实这里对应着加载多少次def format_url(num): urls = baxxxxse_url = for i in range(020 * num20): url = baxxxxse_url.format(i) urls.append(url)return urlsurls = format_url(450)两个凑一起,跑起来:result = pd.Datafrxx

6、xxame()#看爬取了多少页count = 1for url in urls:df = parse_baxxxxse_info(urlheaders = headers)result = pd.concat(resultdf)time.sleep(random.random() + 2)print(I had crawled page of:%d % count)count += 1一个大号的功夫,包含电影ID、电影名称、主演、导演、评分、标记人数和具体网址的数据已经爬好了:下面,我们还想要批量访问每一部电影,拿到有关电影各星级评分占比等更丰富的信息,后续我们想结合评分分布来进行排序。3、单

7、部电影详情爬取我们打开单部电影的网址,取巧做法是直接右键,查看源代码,看看我们想要的字段在不在源代码中,毕竟,爬静态的源代码是最省力的。电影名称?在的!导演信息?在的!豆瓣评分?还是在的!一通CTRL+F搜索发现,我们所有需要的字段,全部在源代码中。那爬取起来就太简单了,这里我们用xpath来解析:defparse_movie_info(urlheaders = headersip = ):if ip = : html = requests.get(urlheaders = headers)else: html = requests.get(urlheaders = headersproxie

8、s = ip) bs = etree.HTML(html.text)#片名 title = bs.xpath(/divid = wrapper/div/h1/span)0.text #上映时间 year = bs.xpath(/divid = wrapper/div/h1/span)1.text #电影类型 m_type = for t in bs.xpath(/spanproperty = v:genre): m_type.append(t.text) a = bs.xpath(/divid= info)0.xpath(string()#片长 m_time =aa.find(片长: ) +

9、4:a.find(分钟n) #时长#地区 area = aa.find(制片国家/地区:) + 9:a.find(n 语言) #地区#评分人数try: people = bs.xpath(/aclass = rating_people/span)0.text#评分分布 rating = rate_count = bs.xpath(/divclass = ratings-on-weight/div)for rate in rate_count: ratingrate.xpath(span/title)0 = rate.xpath(spanclass = rating_per)0.textexce

10、pt: people = None rating = #简介try: brief = bs.xpath(/spanproperty = v:summary)0.text.strip(n u3000u3000)except: brief = Nonetry: hot_comment = bs.xpath(/divid = hot-comments/div/div/p/span)0.textexcept: hot_comment = None cache = pd.Datafrxxxxame(片名:title上映时间:year电影类型:m_type片长:m_time地区:area评分人数:peop

11、le评分分布:rating简介:brief热评:hot_comment网址:url)return cache第二步我们已经拿到了9000部电影所有的网址,只需写个循环,批量访问就可以了。然鹅,尽管设置了访问时间间隔,爬取上千个页面我们就会发现,豆娘还是会把我们给BAN(禁)掉。回忆一下,我们没有登录,不需要cookies验证,只是因为频繁的访问骚扰到了豆娘。那这个问题还是比较好解决的,此处不留爷,换个IP就留爷。细心的朋友已经发现了,上面针对单部电影的页面解析,有一个默认IP参数,我们只需要在旧IP被禁后,传入新的IP就可以了。PS:代理IP如果展开讲篇幅太长,网上有许多免费的IP代理(缺点是

12、可用时间短,不稳定)和付费的IP代理(缺点是不免费)。另外,要强调一下这里我们传入的IP长这样:https:movie_result = pd.Datafrxxxxame()ip = #这里构建自己的IP池count2 = 1cw = 1for urlname in zip(result网址.values6000:result片名.values6000:):#for nameurl in wrongs.items():try: cache = parse_movie_info(urlheaders = headersip = ip) movie_result = pd.concat(movie

13、_resultcache)#time.sleep(random.random() print(我们爬取了第:%d部电影-%s % (count2name) count2 += 1except: print(滴滴滴滴滴,第次报错.format(cw) print(ip is:.format(ip) cw += 1 time.sleep(2)continue电影页面数据爬取结果如下:数据清洗1、基本信息表和电影内容表合并baxxxxse_info表里面是我们批量抓取的电影基本信息,movie_info则是我们进入每一部电影,获取到的感兴趣字段汇总,后面的分析是需要依赖两张表进行的,所以我们合并之:

14、2、电影年份数据清洗我们发现之前爬取的上映时间数据不够规整,前面都带了一个“-”:要把前面多余的符号去掉,但发现无论怎么用str.replace返回的都是Nan,原来这里pandas把所有数字默认成负的,所以只需要把这一列所有数字乘-1即可:3、评分分布规整最终我们是希望能够把电影整体评分(如某电影8.9分)和不同评分等级(5星的占比70%)结合起来分析的。而刚才爬取评分数据的时候,为了偷懒,用的是一个字典把各评分等级和对应的占比给包起来了,然鹅,pandas默认把他当成了字符串,不能直接当做字典处理:灵光一闪?这种字典形式的字符串,用JSON解析一下不就变字典了?HAVE A TRY:结果,

15、疯狂报错:报错貌似在提示我们是最外围的引号错误导致了问题,目前我们用的是双引号(a:1)难道只能用单引号(a:1)?先试试吧:报错解决了。接下来,我们把字典形式的评分拆成多列,例如每个星级对应一列,且百分比的格式变成数值型的,写个循环函数,用apply应用一下即可:#把单列字典的评分分布转化成分开的5列,且每一列是数值型的def get_rate(xtypes):try:return float(xtypes.strip(%)except:passmovie_combine5星 = movie_combineformat_评分.apply(get_ratetypes = 力荐)movie_co

16、mbine4星 = movie_combineformat_评分.apply(get_ratetypes = 推荐)movie_combine3星 = movie_combineformat_评分.apply(get_ratetypes = 还行)movie_combine2星 = movie_combineformat_评分.apply(get_ratetypes = 较差)movie_combine1星 = movie_combineformat_评分.apply(get_ratetypes = 很差)现在我们的数据长这样的:OK,清洗到此告一段落。数据分析大家还记得开头的FLAG吗?我们

17、要制作各年代TOP100电影排行榜。所以直接按照年代划分电影,然后按照电影评分排个序不就完事了!然鹅这听起来有点话糙理也糙。如果只按照电影的总的评分来排序,会忽视掉内部评分细节的差异性,举个例子,搏击俱乐部:总评分9.0分,打出5星好评的占比60.9%,4星的有30.5%。同为9分佳作,给美丽心灵打出5星好评的有56.0%,和搏击俱乐部相比少了4.9%,而4星的人数则高出了6%。可以不负责任的做一个概括:两部都是9分经典,但观众给搏击俱乐部的5星倾向要高于美丽心灵。GET到这个点,我们就可以对电影评分排序制定一个简单的规则:先按照总评分排序,然后再对比5星人数占比,如果一样就对比4星,以此类推

18、。这个评分排序逻辑用PYTHON做起来不要太简单,一行代码就搞定:#按照总评分,5星评分人数占比,4星占比,3星.依次类推movie_combine.sort_values(评分5星4星3星2星1星ascending = Falseinplace = True)但是仔细看排序结果,我们会发现这样排序的一些小瑕疵,一些高分电影其实是比较小众的,比如“剧院魅影:25周年纪念演出”和“悲惨世界:25周年纪念演唱会”等。而我们想要找的,是人民群众所喜闻乐见的电影排名,这里只有通过评分人数来代表人民的数量,我们先看一看所有电影的评分人数分布:评分人数跨度极大,为了减少极值对于平均的影响,就让中位数来衡量

19、人民群众是否喜闻乐见,所以我们只留下大于中位数的评分。接着,看看历年电影数量分布情况:直到2000年初,筛选后的电影年上映数才逼近200,更早时期的电影好像20年加起来还不到100部。为了让结果更加直观,我们来按年代统计电影的上映时间。这里涉及到给每部电影上映时间进行归类,有点棘手啊.绞尽脑细胞,终于找到了一个比较讨巧的办法,先构造年代标签,再借用cut函数按十年的间隔切分上映时间,最后把标签传入参数。得勒!数据直观的反映出各年代上映量,20世纪80年代前真的是少得可怜。看到这里,不由想到我们最开始立的那个“制作年代TOP100榜单”的FLAG,因为早期电影量的贫乏,是完全站不住脚的了。不慌,

20、一个优秀的数据分析师,一定是本着具体问题具体分析的精神来调整FLAG的:基于年代上映量数据,我们从20世纪30年代开始制作排名;为了避免有些年代电影过少,优化成各年代TOP 10%的电影推荐;同时,为了避免近年电影过多,每个年代推荐的上限数不超过100部。看到这三个条件,连一向自傲的潘大师(pandas)都不禁长叹了口气。然鹅大师之所以是大师,就是因为在他眼里没有什么是不可能的。思考1分钟后,确定了灵活筛选的套路:final_rank = pd.Datafrxxxxame()for centurycount in zip(century_f.indexcentury_f.values): f1

21、 = movie_f2.locmovie_f年代 = century: #1000部以下的,取TOP10% if count 1000: return_num = int(count * 0.1) #1000部以上的,取前100部 else: return_num = 100 f2 = f1.iloc:return_num: final_rank = pd.concat(final_rankf2)根据上一步构造的century_f变量,结合每个年代上映电影量,不足1000部的筛选前10%,超过1000部的只筛选前100部,结果,就呼之而出了。在附上代码和榜单之前,我预感到大部分旁友是和我一样懒的(不会仔细看榜单),所以先整理出各年代TOP5电影(有些年代不足TOP5),做一个精华版的历史电影排行榜奉上:从峰回路转、结尾让人大呼牛逼的控方证人,到为无罪真理而辩的十二怒汉,再到家庭为重不怒自威的教父系列、重新诠释希望和坚韧的肖申克的救赎以及将励志提升到新高度的阿甘正传(小Z阅片尚浅,榜单上只看过这些)。每一部好的电影,都是一块从高空坠落的石头,它总能在人们的心湖上激起水花和涟漪,引起人们对生活、社会以及人性的思考。而烂片,就是从高空坠落的空矿泉水瓶,它坠势汹汹,但最终只会浮在水面,让看过的人心存芥蒂,感觉灵魂受到污染。有了新的电影排名榜单,再也不用担心剧荒了。

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1