目标
提取出猫眼电影 TOP100 的电影名称、时间、评分、图片等信息,提取的站点为 http://maoyan.com/board/4
,并将提取的结果以文件的形式保存下来。
抓取分析
打开抓取的站点,发现第一页显示排行1-10的电影,第二页显示排行11-20的电影,但是url发生明显改变变为https://maoyan.com/board/4?offset=10
比之前的多了一个参数offset=10
,再点击第三页发现offset=20
,可以推断出规律,offset
代表偏移量值,如果偏移量为n,那么电影序号就为(n+1) ~(n+10),所以当我们想获取top100的电影,就需要分开10次请求,这样获取不同的页面后,再通过正则表达式提取出相关的信息,就可以了获取TOP100的所有电影信息了。
抓取首页
抓取首页的源代码
1 | import requests |
正则提取
获取首页的源代码之后,通过正则提取我们需要的信息。回到浏览器,再开发者模式下的Network监听组件中,查看源代码,我们可以发现一部电影的信息对应的源代码就是一个dd节点,我们用正则表达式来提取这里的一些电影信息。
- 提取它的排名信息,排名第一的电影为“霸王别姬”,它的排名信息在 class 为 board-index / board-index-1 的 i 节点内,这里采用非贪婪匹配提取 i 节点内的信息,正则表达式为:
<dd>.*board-index.*?>(.*?)</i>
- 提取电影的图片,在后边的 a 标签内发现有两个 img 节点,经检查后发现,第二个 img 节点是电影封面,故这里提取第二个节点的 data-src 属性,正则表达式为:
<dd>.*board-index.*?>(.*?)</i>.*?data-src="(.*?)"
- 提取电影的名称,可以发现在后边的 class 为 name 的 p 节点中,其实这里有好几个地方都可以进行提取,书上提取了 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>
接下来,通过调用findall()方法提取出所有的内容:
1 | def parse_one_page(html): |
可以看出当前提取出来的数据,还十分的乱,所以我们需要将匹配结果再处理一下,遍历提取结果并生成字典:
1 | def parse_one_page(html): |
写入文件
将提取的结果写入文件,通过 JSON库的 dumps() 方法实现字典的序列化,并指定 ensure_ascii 参数为 False,这样可以保证输出结果是中文形式而不是 Unicode编码。
1 | import json |
run()
通过 run() 方法来调用前面实现的方法,将单页的电影结果写入文件。
1 | def main(): |
分页爬取
因为抓取的是 猫眼TOP100 的电影,所以还需要遍历一下,给这个链接传入offset的参数
1 | def main(offset): |
整合代码
1 | import json |