写好一个爬虫最基本的是做好页面分析,找到链接和规律,这样在写爬虫的时候就可以有方向和目的性。接下来,我们就以爬虫最常用的豆瓣评分TOP250的内容作为爬虫的demo,以此来学习使用相关知识。
在开始编写爬虫之前,第一步的操作并不是直接写代码,而是做好前面的分析,就像是项目开发一样,最重要的其实并不是写代码的环节,而是前期的需求调研和功能分析。下面我们打开豆瓣电影TOP250的链接:https://movie.douban.com/top250
在点开第一页评分最高的这部电影《肖申克的救赎》,这里面我们可以看到电影导演、评分、类型等等一些的信息,在页面下方还有一些剧情简介,影片评论等等。
所以,在开始之前我们制定好需求,爬取豆瓣TOP250电影的信息,内容包括电影名称、导演、电影类型(多类型按第一个)、制片国家/地区(多国家按第一个)、语言、上映年份、电影评分,评价人数。
在这些信息中我们就可以做一些简单的数据分析,比如说:什么样的类型的电影评分高。哪个国家的电影制作水平高等,在这之前虽然或多或少的知道一些大体的结论,但是如果让你拿出数据来证明你的结论,还真的未必可以有相关的数据,那么现在我们就可以通过自己抓取相关信息,来进行数据分析。
可以在浏览器中右键查看页面源代码,找到页面位置的代码,代码内容:
从中可以得到,当前网页翻页的方式使用的start参数来控制,每一页固定的25条。所以翻页可以使用页码就是start参数为25*(n-1),n为页数。
找到翻页的方法后,在去寻找每一页的详情怎么获取,在首页中是25部电影的list,而我们想获取的信息是这25部电影详情的链接,找到之前《肖申克救赎》的源代码,部分截取如下,可以发现a标签中href属性值就是电影详情页的链接https://movie.douban.com/subject/1292052/
往下翻看查看一些其他的电影详情链接:比如《霸王别姬》的链接为https://movie.douban.com/subject/1291546/,简单分析一下,可以发现电影的详情页面链接前面都是以 https://movie.douban.com/subject/开头,后面的数字是电影在豆瓣中的id,链接使用的是restful风格的API。
现在我们可以开始编写爬虫,但是现在不能把全部的内容都写完,现在先把需要爬取的链接拿到,然后在每个链接进行爬取。在前面的分析中知道,其实就是获取页面中https://movie.douban.com/subject/开头的链接就可以了。这里选择是用BeautifulSoup模块,在find_all()方法,搜索所有a标签,而且href符合要求的内容。在之前章节已经学习了requests库,所以可以使用requests和BeautifulSoup来完整,示例代码如下:
爬取豆瓣电影TOP250
代码结果:
我们通过一段简洁的代码获取到首页中25部电影的详情链接,但是还有剩余10页的内容,不能每次改变参数重新运行一次,这样不符合代码的开发规范,而这个方法可以提取成为一个公共方法,只需要将url作为传参,返回的是当前url页面中的所有电影详情的链接的list。所以还得需要将此方法改造一下:
代码结果:
分析详情页面
获取到页面链接后下面就是按照详情页面中寻找信息,一般的分析思路上,先在浏览器页面中找信息的位置,然后在找到源代码中的对应的位置,然后在按照标签和属性中的值来一一分析需要的内容怎么获取。
找到当前位置的源代码,电影信息和评分信息的代码内容如下
根据需求中的内容我们需要获得内容是:电影名称、导演、电影类型(多类型按第一个)、制片国家/地区(多国家按第一个)、上映年份、电影评分,评价人数。
下面我们一一分析各个元素在页面中的位置并且确定获取值的方法
电影名称:在span标签并且属性property="v:itemreviewed",可以使用BeautifulSoup.find()
上映年份:在span标签并且属性class="year",可以使用BeautifulSoup.select()
导演:在a标签并且属性rel="v:directedBy",可以使用BeautifulSoup.find()
电影类型:在span标签并且属性property="v:genre",可以使用BeautifulSoup.find()
电影评分:在strong标签并且属性property="v:average",可以使用BeautifulSoup.find()
评价人数:在span标签并且属性property="v:votes",可以使用BeautifulSoup.find()
制片国家/地区和语言并没有直接在标签中,只是在id为info的div中的文本信息。所以无法使用标签定位的方法获取到,但是可以通过把info中的文本信息通过换行符切分成一个字符串list,然后遍历这个list按照指定字符串匹配的方法来确定这些信息。示例代码如下:
爬取《肖申克的救赎》相关信息
代码结果:
有时候find()方法和select()方法都可以达到相同的目标,选择其中一个使用即可,以上仅仅举例使用,并不代表唯一方法,感兴趣的读者可以使用其他的方式抓取。
现在的方法每次也只能爬取一个页面链接,但是我们需要爬取25页,所以需要先将此方法封装成通用的方法。为了方便后面的储存,我们先设计一个豆瓣电影的类。
电影信息对象
然后把前面的信息封装到一个方法中,设置好入参和出参,供其他的函数调用。
上面分别进行了对url的获取和页面详细信息的获取,并且对每一块功能进行封装,每个功能模块都有入参和出参,这样才符合完整的开发规范。
但是作为一个完整的爬虫程序来说,只需要有一个main方法入口,然后可以将所有需要的信息都爬取完成,所以我们还需要将上面的两个小节的内容合成起来,做到一个完整的流程,写好一个完整的爬虫。
至此,我们已经完成了最终的爬虫,这样只需要运行main方法,就可以实现对豆瓣电影TOP250的信息的采集。
从上面的内容中我们可以梳理出基础爬虫的编写思路,大致分为四部分: