当前位置: 91看电影 > 影评观感 > 正文

Python奇技淫巧之爬取豆瓣Top250电影榜单并写入Excel文件

2018-09-19 23:30 9

    久违了,距离上次发文过去了大半个月。月初趁着开学季分享了几部电影和一些英语和IT视频教程,第二天就被人举报了,对方显示是某某律师事务所,我想这把完犊子了,怕不是要吃官司了,吓得手哆哆嗦嗦的点了删除,所幸微信爸爸并没有处罚我 ,公众号也并没有受到影响,可能因为我主动认错,点了承认侵权按钮,态度良好,所以放我一马吧。但我想做一点声明,资源全取自网络,确实有侵权的嫌疑,如果损害了您的利益,联系我删除就好了,在此真诚致歉!我一介屁民,也不是什么大V,公众号粉丝也就100多个,实在没必要劳您大驾,兴师动众,亲自点举报,让您费心了,对不起!

    最近Python可谓是异军突起,借着AI这把燎原之火一路高歌猛进,势如破竹,大有挑战Java这个老大哥江湖地位的意思(其实论资排辈,Python算是Java的前辈了,毕竟人家早出生那么几年),我一直没打算学习它,因为我学过php,印象中它跟php很像,比如内置函数命名风格啊,魔术方法啊,二者的设计如出一辙,甚至有些函数名都一毛一样。但是前段时间要使用Splunk的机器学习库进行数据分析,Python无疑是最佳的选择,于是赶鸭子上架,断断续续花了几天时间把廖雪峰老师的博客看了大部分,开始着手进行开发,这一弄不打紧,从此对它青眼有加,被它行云流水、一气呵成的代码风格深深折服。它没有Java的冗长笨重,没有js的纷繁复杂,比php更多了一份飘逸灵动。它让你可以专注于实现业务逻辑,而尽量少花时间纠结语法层面的东西。它提供了像requests 、urllib、xpath、bs4、pillow等一系列让人赞不绝口的库,大大简化了编码流程,提高了编码效率,从此再也不用加班(想的美)

    闲话少叙,这个demo是我入门Python以及爬虫之后自我检验的一个测试案例,代码也不多,除去注释也就50多行,但是麻雀虽小五脏俱全,里边内容还是很丰富的,对于初学者来说,能徒手撸出来,相信肯定会大有收获。最近几周在给公司的几个同事培训Python,为了讲明白一个知识点,在讲之前会把跟这个知识相关的知识点都捋一遍,原本的盲点也豁然开朗了,所以学习的最佳状态就是尝试着讲给别人听,当你能把一个知识以最通俗的方式让一个门外汉在最短的时间内理解,你对它的掌握程度绝对在九成以上,写这篇文章也正是基于这样的目的。我觉得我还是蛮适合当老师的,最喜欢在我举一个通俗易懂的例子后看到大家醍醐灌顶般“哦,原来如此”的表情。现在最主要的问题还是自己技术太菜,有当老师的心,却没有当老师的资格,任重而道远。想起了韩顺平老师讲过的卖油翁的故事,编程无他,唯手熟尔!多敲,多想,日积寸功,月有所进!与君共勉。

    下面对这个demo按代码执行顺序逐行拆解。(温馨提示,阅读需要有一定的html、css基础)

上面是所有的代码,注释占了一半。其中第109行是程序的入口,在系统的main函数中调用了我自己写的main()方法,于是程序转向第10行main()方法定义的位置。

第14行会返回从豆瓣top250电影排行榜中第一页的数据,因为这个url打开之后默认就在第一页。第16行调用了get_page()方法,以第一页返回的数据为入参,返回这个排行榜总共有多少页。因此程序转向第44行

43# 获取总页数的方法
44def get_page(res):
45    # 使用BeautifulSoup对返回的页面信息进行解析
46    soup = bs4.BeautifulSoup(res, 'html.parser')  # 第一个参数为要解析的内容 第二个参数表示使用HTML解析器
47    # 找到class为next的span元素
48    next = soup.find('span', class_='next')
49    # 它的前一个兄弟元素里的内容即为总页数(注意此处需要两个previous_sibling才能获取  因为元素内的空白字符被视作文本,而文本被视作节点。)
50    total_page = next.previous_sibling.previous_sibling.text
51    # 将总页数转换成整数返回
52    return int(total_page)

第46行创建了一个.BeautifulSoup对象,用于对传入的网页文档内容进行解析。我们用浏览器打开网址,按F12查看网页元素,定位到“后页”

就会发现,总共有10页,要拿到数字10,可以先找到class为“next”的span标签,然后往前找它的兄弟节点,也就是前一个a标签里的内容,就是总页数10。至于为什么需要调用两次previous_sibling,注释里已经解释的很清楚了。52行执行完成之后,就会返回调用get_page()方法的位置,也就是main()方法中的16行。

第20 行开始,向每一页的链接发送get请求,获取改该页的电影信息

第2页的url地址如图,可以看出每一页的起始位置就是25*(当前页数-1),由于i是从0开始的,直接乘以25,就可以轻松获取每一页的起始位置。第27行又定义了一个get_movie()方法,它的作用是将当前页的电影信息取出来,因此每循环一次,就会跳到第56行执行get_movie()方法。并且将每一页的电影信息添加到all_movies这个列表中。

54# 获取某一页所有电影信息的方法
55def get_movies(res):
56    soup = bs4.BeautifulSoup(res.text, 'html.parser')
57    # 获取当前页所有的电影名称
58    movie_name = soup.find_all('div', class_='hd')
59    # 获取当前页所有的电影评分
60    movie_score = soup.find_all('span', class_='rating_num')
61    # 获取当前页所有的电影简介
62    movie_intro = soup.find_all('span', class_='inq')
63    # 创建一个空的List用于保存电影信息
64    movie = []
65    for i in range(len(movie_name)):
66        #  将每部电影的信息做成一个dict 放入movie中
67        d = {
68            'movie_name': movie_name[i].a.span.text,
69            'movie_score' : movie_score[i].text,
70            'movie_intro' : movie_intro[i].text
71        }
72        movie.append(d)
73    return movie

同样先创建BeautifulSoup对象,解析页面数据。

可以看到标题全都在class为“hd”的div元素下的a标签中的span标签中

电影评分则直接位于class为“rating_num”的span标签中。

电影简介则位于class为“inq”的span标签中。通过一个简单的循环,配合字典,就可以轻松将电影的信息保存到movie变量中,并返回。代码执行到第32行调用了save_to_excel方法,于是程序跳转到第75行

74# 将电影数据保存到Excel中的方法
75def save_to_excel(all_movies):
76    # 创建一个Excel工作簿
77    wb = Workbook()
78    # 创建一个sheet
79    ws = wb.active
80    # 设置sheet的标题为“豆瓣电影Top250排行榜”
81    ws.title = '豆瓣电影Top250排行榜'
82    # 设置sheet背景为红色
83    ws.sheet_properties.tabColor = colors.RED
84    # 将A1到D1合并单元格
85    ws.merge_cells('A1:D1')
86    # 设置A1的内容为“豆瓣电影Top250排行榜”
87    ws['A1'] = '豆瓣电影Top250排行榜'
88    # 创建一个字体格式 字体大小为18 字体颜色为红色
89    font = Font(sz=18, color=colors.RED)
90    # 给A1设置为该字体
91    ws['A1'].font = font
92    # 设置第2行的内容
93
94    ws['A2'] = '排名'
95    ws['B2'] = '电影名称'
96    ws['C2'] = '电影评分'
97    ws['D2'] = '电影简介'
98
99    # 从第3行开始将电影数据逐行写入到Excel文件中
100    # 定义起始位置
101    start_pos = 3
102    for (i, movie) in enumerate(all_movies):
103        ws['A{0}'.format(start_pos + i)] = 'Top{0}'.format(i + 1)
104        ws['B{0}'.format(start_pos + i)] = movie['movie_name']
105        ws['C{0}'.format(start_pos + i)] = movie['movie_score']
106        ws['D{0}'.format(start_pos + i)] = movie['movie_intro']
107    # 保存工作簿
108    wb.save('./豆瓣电影Top250排行.xlsx')

第77行打开了一个工作簿,就类似于我们用电脑打开一个空白的Excel文档,79行会默认将第一个sheet激活。第80行到第91行是设置Excel文件中第一行大标题的内容和样式,第92行到第97行是设置xcel文件中第2行的表头信息。第101行到第106行是将all_movie中的电影数据依次取出,将排名拼接后,放在A3-A253的位置,将电影名称放在A3-A252的位置,依次类推。第108行将这个工作簿保存为名称为“豆瓣电影Top250排行.xlsx”的文件,至此大功告成!最后的效果如下:

50多行代码就可以拿下Java几百行代码才能做的事,而且条理清晰,逻辑简单,十分容易理解,此刻我对龟叔的敬仰之情如滔滔江水连绵不绝,就一个字,大写的服!

欢迎 发表评论:

Copyright © 2018 91看电影