前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python爬虫--爬取豆瓣 TOP250 电影排行榜

Python爬虫--爬取豆瓣 TOP250 电影排行榜

作者头像
Flaneur
发布2020-03-25 11:22:05
3.1K0
发布2020-03-25 11:22:05
举报
文章被收录于专栏:Flaneur的文章分享

前言

本篇讲介绍一个简单的Python爬虫案例–爬取豆瓣 TOP250 电影排行榜。 很多朋友在看一部电影前都喜欢先找一下网友们对该片的评价。

说到电影评分的网站,除了国外的 IMDB 和烂番茄,国内要数豆瓣最为出名。

主要原因是豆瓣有一套完整的评分和防水军机制 。

在这套机制下,豆瓣评分高的电影不一定是所有人都喜欢的,但是豆瓣评分低的电影,一定是实打实的烂片!

虽然每个人的喜好偏爱不同,但通常豆瓣评分 8 分以上的电影,都是值得一看的。

豆瓣还专门提供了一个 TOP250 的电影链接 -> https://movie.douban.com/top250

爬取思路

爬取的过程很好理解,这里只需要两个过程: ① 从服务器上下载所需页面 ② 解析这个页面,得到自己需要有用的内容

①抓取页面

有的人可能会利用 urllib 模块实现网络抓取功能。但在 Python 中,有一个更好地替代者——Requests。Requests 简化了 urllib 的诸多冗杂且无意义的操作,并提供了更强大的功能。 所以在这里我们使用 Requests 模块的 get() 方法从服务器上来下载这个页面。

代码语言:javascript
复制
import requests

url = "https://movie.douban.com/top250"
headers = {
    "User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3314.0 Safari/537.36 SE 2.X MetaSr 1.0"
    }

res = requests.get(url,headers=headers)

res就是我们需要的这个页面的资源,我们不妨打开来看看是不是

代码语言:javascript
复制
with open("豆瓣电影.txt",'w',encoding='utf-8') as f:
    f.write(res.text)

打开文本如下图

我们可以看出这确实是当前网页的资源,所以我们就抓取成功了。

②解析页面

解析网页内容推荐使用 BeautifulSoup 模块,它可以化腐朽为神奇,将一个复杂的网页结构转化为书籍目录的形式供你浏览。 例如,我们现在需要解析提取出当前页面的电影名字

代码语言:javascript
复制
import bs4
soup = bs4.BeautifulSoup(res.text,"html.parser")
targets = soup.find_all("div",class_="hd")
for each in targets:
    print(each.a.span.text)

可以得到如下结果

肖申克的救赎 霸王别姬 阿甘正传 这个杀手不太冷 美丽人生 泰坦尼克号 千与千寻 辛德勒的名单 盗梦空间 忠犬八公的故事 海上钢琴师 机器人总动员 三傻大闹宝莱坞 楚门的世界 放牛班的春天 星际穿越 大话西游之大圣娶亲 熔炉 疯狂动物城 无间道 龙猫 教父 当幸福来敲门 怦然心动 触不可及

这里你可能就会有疑问,这些数据是怎么得来的呢? 我们先来看下 HTML 源代码:

发现每个电影的标题都是位于 <div class="hd">...</div> 标签中的,它的从属关系是:div -> a -> span

所以我们先调用 find_all() 方法,找到所有 class=”hd” 的 div 标签,然后按照从属关系即可直接取出电影名。 同理,我们借用此发方法来解析提取出电影的评分、介绍等需要的信息。

附加问题

我们刚才解析提取的仅仅是第一页的页面,那么还有第二、第三、第四页……呢?

其实,解决起来也很简单,我们可以使用for循环来对每一页进行上述的两个过程。

但,我们此时又有新的问题,我们不可能每抓取一次,就重新输入下一网页的链接地址,这样很麻烦,效率也不高。

我们可以分析每一页的链接:

第一页:https://movie.douban.com/top250 第二页:https://movie.douban.com/top250?start=25 第三页:https://movie.douban.com/top250?start=50 第四页:https://movie.douban.com/top250?start=75 第五页:https://movie.douban.com/top250?start=100 … … …. …

我们可以发现这样的规律: 每一次的更新的 url = https://movie.douban.com/top250 + '/?start=' + str(25*i)其中i可以表示为页数-1

咦,这个时候,你可能会有疑问,我们怎么知道一共有多少页呢,不能一直for循环无穷吧。

那当然不可能的了,我们可以按第二步解析网页方式来获取页数

代码语言:javascript
复制
depth = soup.find('span',class_='next').previous_sibling.previous_sibling.text

注意,这个返回的depth是给字符串形式,需要int()

这样结合刚才的过程,就可以迭代每一页了

代码清单

感兴趣的话,可以试一试哦

代码语言:javascript
复制
import requests
import bs4

#抓取网页
def open_url(url):
    headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3314.0 Safari/537.36 SE 2.X MetaSr 1.0"}
    res = requests.get(url,headers=headers)
    
    return res

#得到总页数
def find_depth(res):
    soup = bs4.BeautifulSoup(res.text,'html.parser')
    depth = soup.find('span',class_='next').previous_sibling.previous_sibling.text

    return int(depth)

#解析网页,提取内容
def find_movies(res):
    soup = bs4.BeautifulSoup(res.text,'html.parser')

    names = []
    target = soup.find_all('div',class_='hd')
    for i in target:
        names.append(i.a.span.text)

    ranks = []
    target = soup.find_all('span',class_='rating_num')
    for i in target:
        ranks.append(i.text)

    messages = []
    target = soup.find_all('div',class_='bd')
    for i in target:
        try:
            messages.append(i.p.text.split('\n')[1].strip() + i.p.text.split('\n')[2].strip())
        except:
            continue

    result = []
    length = len(names)
    for i in range(length):
        result.append(names[i] + ',' +ranks[i] + ',' + messages[i] + '\n')

    return result

def main():
    host = "https://movie.douban.com/top250"
    res = open_url(host)
    depth = find_depth(res)

    result = []
    for i in range(depth):
        url = host + '/?start=' + str(25*i)
        res = open_url(url)
        result.extend(find_movies(res))

    with open("豆瓣TOP250电影.txt",'w',encoding='utf-8') as f:
        for each in result:
            f.write(each)

if __name__=="__main__":
    main()

嘟嘟

我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=3c2lknoq16w4k

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-03-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 爬取思路
    • ①抓取页面
      • ②解析页面
        • 附加问题
        • 代码清单
          • 嘟嘟
          相关产品与服务
          云服务器
          云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档