【摘要】本节中,我们利用requests库和正则表达式来抓取猫眼电影TOP100的相关内容。requests比urllib使用更加方便,而且目前我们还没有系统学习HTML解析库,所以这里就选用正则表达式来作为解析工具。

1. 本节目标

本节中,我们要提取出猫眼电影TOP100的电影名称、时间、评分、图片等信息,提取的站点URL为http://maoyan.com/board/4,提取的结果会以文件形式保存下来。

2. 准备工作

在本节开始之前,请确保已经正确安装好了requests库。如果没有安装,可以参考第1章的安装说明。

3. 抓取分析

我们需要抓取的目标站点为http://maoyan.com/board/4,打开之后便可以查看到榜单信息,如图3-11所示。

图3-11 榜单信息

排名第一的电影是霸王别姬,页面中显示的有效信息有影片名称、主演、上映时间、上映地区、评分、图片等信息。

将网页滚动到最下方,可以发现有分页的列表,直接点击第2页,观察页面的URL和内容发生了怎样的变化,如图3-12所示。

图3-12 页面URL变化

可以发现页面的URL变成http://maoyan.com/board/4?offset=10,比之前的URL多了一个参数,那就是offset=10,而目前显示的结果是排行11~20名的电影,初步推断这是一个偏移量的参数。再点击下一页,发现页面的URL变成了http://maoyan.com/board/4?offset=20,参数offset变成了20,而显示的结果是排行21~30的电影。

由此可以总结出规律,offset代表偏移量值,如果偏移量为n,则显示的电影序号就是n+1到n+10,每页显示10个。所以,如果想获取TOP100电影,只需要分开请求10次,而10次的offset参数分别设置为0、10、20、…90即可,这样获取不同的页面之后,再用正则表达式提取出相关信息,就可以得到TOP100的所有电影信息了。

4. 抓取首页

接下来用代码实现这个过程。首先抓取第一页的内容。我们实现了get_one_page()方法,并给它传入url参数。然后将抓取的页面结果返回,再通过main()方法调用。初步代码实现如下:

import requestsdef get_one_page(url):response = requests.get(url)if response.status_code == 200:return response.textreturn Nonedef main():url = 'http://maoyan.com/board/4'html = get_one_page(url)print(html)main()

这样运行之后,就可以成功获取首页的源代码了。获取源代码后,就需要解析页面,提取出我们想要的信息。

5. 正则提取

接下来,回到网页看一下页面的真实源码。在开发者模式下的Network监听组件中查看源代码,如图3-13所示。

图3-13 源代码

注意,这里不要在Elements选项卡中直接查看源码,因为那里的源码可能经过JavaScript操作而与原始请求不同,而是需要从Network选项卡部分查看原始请求得到的源码。

查看其中一个条目的源代码,如图3-14所示。

图3-14 源代码

可以看到,一部电影信息对应的源代码是一个dd节点,我们用正则表达式来提取这里面的一些电影信息。首先,需要提取它的排名信息。而它的排名信息是在class为board-index的i节点内,这里利用非贪婪匹配来提取i节点内的信息,正则表达式写为:

<dd>.*?board-index.*?>(.*?)</i>

随后需要提取电影的图片。可以看到,后面有a节点,其内部有两个img节点。经过检查后发现,第二个img节点的data-src属性是图片的链接。这里提取第二个img节点的data-src属性,正则表达式可以改写如下:

<dd>.*?board-index.*?>(.*?)</i>.*?data-src="(.*?)"

再往后,需要提取电影的名称,它在后面的p节点内,class为name。所以,可以用name做一个标志位,然后进一步提取到其内a节点的正文内容,此时正则表达式改写如下:

<dd>.*?board-index.*?>(.*?)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>

再提取主演、发布时间、评分等内容时,都是同样的原理。最后,正则表达式写为:

<dd>.*?board-index.*?>(.*?)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>.*?star.*?>(.*?)</p>.*?releasetime.*?>(.*?)</p>.*?integer.*?>(.*?)</i>.*?fraction.*?>(.*?)</i>.*?</dd>

这样一个正则表达式可以匹配一个电影的结果,里面匹配了7个信息。接下来,通过调用findall()方法提取出所有的内容。

接下来,我们再定义解析页面的方法parse_one_page(),主要是通过正则表达式来从结果中提取出我们想要的内容,实现代码如下:

def parse_one_page(html):pattern = re.compile('<dd>.*?board-index.*?>(.*?)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>.*?star.*?>(.*?)</p>.*?releasetime.*?>(.*?)</p>.*?integer.*?>(.*?)</i>.*?fraction.*?>(.*?)</i>.*?</dd>',re.S)items = re.findall(pattern, html)print(items)

这样就可以成功地将一页的10个电影信息都提取出来,这是一个列表形式,输出结果如下:

[('1', 'http://p1.meituan.net/movie/20803f59291c47e1e116c11963ce019e68711.jpg@160w_220h_1e_1c',
'霸王别姬', '\n                主演:张国荣,张丰毅,巩俐\n        ', '上映时间:1993-01-01(中国香港)','9.', '6'), ('2', 'http://p0.meituan.net/movie/__40191813__4767047.jpg@160w_220h_1e_1c', '肖申克的救赎','\n                主演:蒂姆·罗宾斯,摩根·弗里曼,鲍勃·冈顿\n        ', '上映时间:1994-10-14(美国)','9.', '5'), ('3', 'http://p0.meituan.net/movie/fc9d78dd2ce84d20e53b6d1ae2eea4fb1515304.jpg@160w_220h_1e_1c','这个杀手不太冷', '\n                主演:让·雷诺,加里·奥德曼,娜塔莉·波特曼\n        ', '上映时间:1994-09-14(法国)', '9.', '5'), ('4', 'http://p0.meituan.net/movie/23/6009725.jpg@160w_220h_1e_1c','罗马假日', '\n                主演:格利高利·派克,奥黛丽·赫本,埃迪·艾伯特\n     ', '上映时间:1953-09-02(美国)', '9.', '1'), ('5', 'http://p0.meituan.net/movie/53/1541925.jpg@160w_220h_1e_1c','阿甘正传', '\n                主演:汤姆·汉克斯,罗宾·怀特,加里·西尼斯\n       ', '上映时间:1994-07-06(美国)', '9.', '4'), ('6', 'http://p0.meituan.net/movie/11/324629.jpg@160w_220h_1e_1c','泰坦尼克号', '\n                主演:莱昂纳多·迪卡普里奥,凯特·温丝莱特,比利·赞恩\n     ', '上映时间:1998-04-03', '9.', '5'), ('7', 'http://p0.meituan.net/movie/99/678407.jpg@160w_220h_1e_1c','龙猫', '\n                主演:日高法子,坂本千夏,糸井重里\n        ', '上映时间:1988-04-16(日本)', '9.', '2'),('8', 'http://p0.meituan.net/movie/92/8212889.jpg@160w_220h_1e_1c', '教父', '\n                主演:马龙·白兰度,阿尔·帕西诺,詹姆斯·凯恩\n   ', '上映时间:1972-03-24(美国)', '9.', '3'), ('9', 'http://p0.meituan.net/movie/62/109878.jpg@160w_220h_1e_1c', '唐伯虎点秋香','\n                主演:周星驰,巩俐,郑佩佩\n        ', '上映时间:1993-07-01(中国香港)', '9.', '2'),('10', 'http://p0.meituan.net/movie/9bf7d7b81001a9cf8adbac5a7cf7d766132425.jpg@160w_220h_1e_1c', '千与千寻', '\n                主演:柊瑠美,入野自由,夏木真理\n        ','上映时间:2001-07-20(日本)', '9.', '3')]

但这样还不够,数据比较杂乱,我们再将匹配结果处理一下,遍历提取结果并生成字典,此时方法改写如下:

def parse_one_page(html):pattern = re.compile('<dd>.*?board-index.*?>(.*?)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>.*?star.*?>(.*?)</p>.*?releasetime.*?>(.*?)</p>.*?integer.*?>(.*?)</i>.*?fraction.*?>(.*?)</i>.*?</dd>',re.S)items = re.findall(pattern, html)for item in items:yield {'index': item[0],'image': item[1],'title': item[2].strip(),'actor': item[3].strip()[3:] if len(item[3]) > 3 else '','time': item[4].strip()[5:] if len(item[4]) > 5 else '','score': item[5].strip() + item[6].strip()}

这样就可以成功提取出电影的排名、图片、标题、演员、时间、评分等内容了,并把它赋值为一个个的字典,形成结构化数据。运行结果如下:

{'image': 'http://p1.meituan.net/movie/20803f59291c47e1e116c11963ce019e68711.jpg@160w_220h_1e_1c', 'actor': '张国荣,张丰毅,巩俐','score': '9.6', 'index': '1', 'title': '霸王别姬', 'time': '1993-01-01(中国香港)'}
{'image': 'http://p0.meituan.net/movie/__40191813__4767047.jpg@160w_220h_1e_1c', 'actor': '蒂姆·罗宾斯,摩根·弗里曼,鲍勃·冈顿','score': '9.5', 'index': '2', 'title': '肖申克的救赎', 'time': '1994-10-14(美国)'}
{'image': 'http://p0.meituan.net/movie/fc9d78dd2ce84d20e53b6d1ae2eea4fb1515304.jpg@160w_220h_1e_1c', 'actor':
'让·雷诺,加里·奥德曼,娜塔莉·波特曼', 'score': '9.5', 'index': '3', 'title': '这个杀手不太冷', 'time': '1994-09-14(法国)'}
{'image': 'http://p0.meituan.net/movie/23/6009725.jpg@160w_220h_1e_1c', 'actor': '格利高利·派克,奥黛丽·赫本,埃迪·艾伯特',
'score': '9.1', 'index': '4', 'title': '罗马假日', 'time': '1953-09-02(美国)'}
{'image': 'http://p0.meituan.net/movie/53/1541925.jpg@160w_220h_1e_1c', 'actor': '汤姆·汉克斯,罗宾·怀特,加里·西尼斯',
'score': '9.4', 'index': '5', 'title': '阿甘正传', 'time': '1994-07-06(美国)'}
{'image': 'http://p0.meituan.net/movie/11/324629.jpg@160w_220h_1e_1c', 'actor':'莱昂纳多·迪卡普里奥,凯特·温丝莱特,比利·赞恩', 'score': '9.5', 'index': '6', 'title': '泰坦尼克号', 'time': '1998-04-03'}
{'image': 'http://p0.meituan.net/movie/99/678407.jpg@160w_220h_1e_1c', 'actor': '日高法子,坂本千夏,糸井重里','score': '9.2', 'index': '7', 'title': '龙猫', 'time': '1988-04-16(日本)'}
{'image': 'http://p0.meituan.net/movie/92/8212889.jpg@160w_220h_1e_1c', 'actor': '马龙·白兰度,阿尔·帕西诺,詹姆斯·凯恩','score': '9.3', 'index': '8', 'title': '教父', 'time': '1972-03-24(美国)'}{'image': 'http://p0.meituan.net/movie/62/109878.jpg@160w_220h_1e_1c', 'actor': '周星驰,巩俐,郑佩佩', 'score': '9.2',
'index': '9', 'title': '唐伯虎点秋香', 'time': '1993-07-01(中国香港)'}
{'image': 'http://p0.meituan.net/movie/9bf7d7b81001a9cf8adbac5a7cf7d766132425.jpg@160w_220h_1e_1c', 'actor': '柊瑠美,
入野自由,夏木真理', 'score': '9.3', 'index': '10', 'title': '千与千寻', 'time': '2001-07-20(日本)'}

6. 写入文件

随后,我们将提取的结果写入文件,这里直接写入到一个文本文件中。这里通过JSON库的dumps()方法实现字典的序列化,并指定ensure_ascii参数为False,这样可以保证输出结果是中文形式而不是Unicode编码。代码如下:

def write_to_json(content):with open('result.txt', 'a') as f:print(type(json.dumps(content)))f.write(json.dumps(content, ensure_ascii=False,).encode('utf-8'))

通过调用write_to_json()方法即可实现将字典写入到文本文件的过程,此处的content参数就是一部电影的提取结果,是一个字典。

7. 整合代码

最后,实现main()方法来调用前面实现的方法,将单页的电影结果写入到文件。相关代码如下:

def main():url = 'http://maoyan.com/board/4'html = get_one_page(url)for item in parse_one_page(html):write_to_json(item)

到此为止,我们就完成了单页电影的提取,也就是首页的10部电影可以成功提取并保存到文本文件中了。

8. 分页爬取

因为我们需要抓取的是TOP100的电影,所以还需要遍历一下,给这个链接传入offset参数,实现其他90部电影的爬取,此时添加如下调用即可:

if __name__ == '__main__':for i in range(10):main(offset=i * 10)

这里还需要将main()方法修改一下,接收一个offset值作为偏移量,然后构造URL进行爬取。实现代码如下:

def main(offset):url = 'http://maoyan.com/board/4?offset=' + str(offset)html = get_one_page(url)for item in parse_one_page(html):print(item)write_to_file(item)

到此为止,我们的猫眼电影TOP100的爬虫就全部完成了,再稍微整理一下,完整的代码如下:

import json
import requests
from requests.exceptions import RequestException
import re
import timedef get_one_page(url):try:response = requests.get(url)if response.status_code == 200:return response.textreturn Noneexcept RequestException:return Nonedef parse_one_page(html):pattern = re.compile('<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name"><a'+ '.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>'+ '.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>', re.S)items = re.findall(pattern, html)for item in items:yield {'index': item[0],'image': item[1],'title': item[2],'actor': item[3].strip()[3:],'time': item[4].strip()[5:],'score': item[5] + item[6]}def write_to_file(content):with open('result.txt', 'a', encoding='utf-8') as f:f.write(json.dumps(content, ensure_ascii=False) + '\n')def main(offset):url = 'http://maoyan.com/board/4?offset=' + str(offset)html = get_one_page(url)for item in parse_one_page(html):print(item)write_to_file(item)if __name__ == '__main__':for i in range(10):main(offset=i * 10)time.sleep(1)

现在猫眼多了反爬虫,如果速度过快,则会无响应,所以这里又增加了一个延时等待。

9. 运行结果

最后,我们运行一下代码,输出结果类似如下:

{'index': '1', 'image': 'http://p1.meituan.net/movie/20803f59291c47e1e116c11963ce019e68711.jpg@160w_220h_1e_1c', 'title':
'霸王别姬', 'actor': '张国荣,张丰毅,巩俐', 'time': '1993-01-01(中国香港)', 'score': '9.6'}
{'index': '2', 'image': 'http://p0.meituan.net/movie/__40191813__4767047.jpg@160w_220h_1e_1c', 'title': '肖申克的救赎','actor': '蒂姆·罗宾斯,摩根·弗里曼,鲍勃·冈顿', 'time': '1994-10-14(美国)', 'score': '9.5'}
...
{'index': '98', 'image': 'http://p0.meituan.net/movie/76/7073389.jpg@160w_220h_1e_1c', 'title':'东京物语', 'actor': '笠智众,原节子,杉村春子', 'time': '1953-11-03(日本)', 'score': '9.1'}
{'index': '99', 'image': 'http://p0.meituan.net/movie/52/3420293.jpg@160w_220h_1e_1c', 'title':
'我爱你', 'actor': '宋在河,李彩恩,吉海延', 'time': '2011-02-17(韩国)', 'score': '9.0'}
{'index': '100', 'image': ' 'title': '迁徙的鸟', 'actor': '雅克·贝汉,菲利普·拉波洛,Philippe Labro', 'time': '2001-12-12(法国)', 'score': '9.1'}

这里省略了中间的部分输出结果。可以看到,这样就成功地把TOP100的电影信息爬取下来了。

这时我们再看下文本文件,结果如图3-15所示。

图3-15 运行结果

可以看到,电影信息也已全部保存到了文本文件中了,大功告成!

10. 本节代码

本节的代码地址为https://github.com/Python3WebSpider/MaoYan。

本节中,我们通过爬取猫眼TOP100的电影信息练习了requests和正则表达式的用法。这是一个最基础的实例,希望大家可以通过这个实例对爬虫的实现有一个最基本的思路,也对这两个库的用法有更深一步的了解。

来源:华为云社区  作者:崔庆才丨静觅

【Python3网络爬虫开发实战】3.4-抓取猫眼电影排行相关推荐

  1. [Python3网络爬虫开发实战] --分析Ajax爬取今日头条街拍美图

    [Python3网络爬虫开发实战] --分析Ajax爬取今日头条街拍美图 学习笔记--爬取今日头条街拍美图 准备工作 抓取分析 实战演练 学习笔记–爬取今日头条街拍美图 尝试通过分析Ajax请求来抓取 ...

  2. Python3网络爬虫开发实战,Scrapy 爬取新浪微博

    前面讲解了 Scrapy 中各个模块基本使用方法以及代理池.Cookies 池.接下来我们以一个反爬比较强的网站新浪微博为例,来实现一下 Scrapy 的大规模爬取. 很多人学习python,不知道从 ...

  3. Python3网络爬虫开发实战分析Ajax爬取今日头条街拍美图

    本节中,我们以今日头条为例来尝试通过分析Ajax请求来抓取网页数据的方法.这次要抓取的目标是今日头条的街拍美图,抓取完成之后,将每组图片分文件夹下载到本地并保存下来. 1. 准备工作 很多人学习pyt ...

  4. 《崔庆才Python3网络爬虫开发实战教程》学习笔记(3):抓取猫眼电影榜单TOP100电影,并存入Excel表格

    本篇博文是自己在学习崔庆才的<Python3网络爬虫开发实战教程>的学习笔记系列,如果你也要这套视频教程的话,关注我公众号[小众技术],关注后回复[PYTHON],无套路免费送你一个学习大 ...

  5. 【Python3网络爬虫开发实战】3-基本库的使用-4抓取猫眼电影排行

    本节中,我们利用requests库和正则表达式来抓取猫眼电影TOP100的相关内容.requests比urllib使用更加方便,而且目前我们还没有系统学习HTML解析库,所以这里就选用正则表达式来作为 ...

  6. python3网络爬虫开发实战-抓取猫眼电影排行(正则表达式版)

    抓取猫眼电影排行 目前没有学习HTML解析库,这里先选用正则表达式作为解析工具 目标 提取出猫眼电影top100的电影名称.时间.评分.图片等信息.提取的站点URL为http://maoyan.com ...

  7. [Python3网络爬虫开发实战] 7-动态渲染页面爬取-4-使用Selenium爬取淘宝商品

    在前一章中,我们已经成功尝试分析Ajax来抓取相关数据,但是并不是所有页面都可以通过分析Ajax来完成抓取.比如,淘宝,它的整个页面数据确实也是通过Ajax获取的,但是这些Ajax接口参数比较复杂,可 ...

  8. 《Python3网络爬虫开发实战(第二版)》上市了!!!!

    " 阅读本文大概需要 5 分钟. " 告诉大家一个好消息:我的好朋友崔庆才老师的<Python3网络爬虫开发实战(第二版)>现在正式上市了!!!! 没错,就是这本: 就 ...

  9. 【Python3网络爬虫开发实战】 1.7-App爬取相关库的安装

    [摘要] 除了Web网页,爬虫也可以抓取App的数据.App中的页面要加载出来,首先需要获取数据,而这些数据一般是通过请求服务器的接口来获取的.由于App没有浏览器这种可以比较直观地看到后台请求的工具 ...

最新文章

  1. 不是我放弃AI,是AI放弃了我!!
  2. c程序语言设定定义域,4.22C语言学习日记:变量的定义域及编译预处理
  3. ListView图片不显示 Application.EnableVisualStyle bug
  4. Eureka简介与Eureka Server上
  5. 北理工计算机学院新闻,北理工计算机学子勇夺CVPR 2021 AI安全国际顶级赛事季军...
  6. 基于DBUtils实现数据库连接池
  7. memcache 原理 监测 查看状态 stats 结构
  8. MongoDB基础(3.6安装及多实例)
  9. i = i+1 和 i += 1
  10. ListView的getFirstVisiblePosition等方法返回的是哪个对象
  11. I - Arbitrage(判断是否有无正环 II)
  12. cru使用教程_极客自习室 篇四:「教程向」给你显示器超个频呗!一键提升40%!省下好几百!...
  13. 破产案或加速唯冠与苹果和解
  14. 基于C#(Visual Studio 2013)的AutoCAD2016二次开发(二)创建直线
  15. Python 批量获取今日头条街拍美图
  16. 3D渲染技术分享:用实时反射Shader增强画面颜值
  17. 关于如何使用C++读取.dbf文件
  18. 世界的下一个主宰——人工智能
  19. 【泡泡机器人公开课】公开课链接 机器人俱乐部
  20. Visual Age for Java_VisualAge for Java使用技巧

热门文章

  1. 用java统计任一书名次数_Java入门第三季 借书系统源代码 加入了限制重输次数 欢迎指教交流...
  2. aix查看oracle进程内存,Aix 查看进程占用内存大小(按从大小排列)
  3. 逆向透视表 python_Python实现数据的透视表
  4. java spring配置类_spring 配置 Java配置类装配bean
  5. Java中try catch finally语句中含有return语句的执行情况
  6. 牛客网———二叉树遍历
  7. What is an Operating System?
  8. 父类对象由子类实例化【转载】
  9. 如何dos中查看当前MySQL版本信息?
  10. C语言课后习题(32)