python爬取豆瓣电影数据

目录

一、背景

二、分析网站

1、ajax请求

三、代码实现

1、导包

2、面向对象实现

3、发送请求

4、解析数据

5、保存数据

6、定义主函数

7、实例化对象运行主函数

8、运行效果

四、以下是全部完整代码

五、报错解决

1、数据库连接报错

2、数据插入报错


一、背景

豆瓣这个网站相信大家并不陌生,大家一定想知道哪些电影类型是比较好看的,哪些电影是评分高的,今天的主题就是教大家爬取豆瓣电影的电影数据。豆瓣网址https://movie.douban.com/typerank?type_name=%E5%89%A7%E6%83%85&type=11&interval_id=100:90&action=

二、分析网站

1、ajax请求

由于网站是动态的,数据不在页面源代码里,所以我们需要找到数据的接口,首先我们需要进入这个网站,然后键盘按F12打开调试窗口,准备进行抓包,如下图

然后点击浏览器的刷新,就找到了数据的接口,如下图

接下来就是用代码区发送请求拿到数据了。

三、代码实现

1、导包

我们选择用requests库来发送请求,然后用Mysql来保存数据

import pymysql
import requests

2、面向对象实现

我们还是创建一个类,并且定义类的初始化方法,其中url就是我们找到的接口网址,headers就是我们给爬虫加的伪装,里面有cookie和user-agent,可以去响应接口里复制然后写成字典的形式,

movie_type就是我们要爬取的电影类型,值为什么要用一个列表呢?因为这个接口的参数有电影的类型和页数,但是电影类型不是用字符串去请求,而是豆瓣的后端根据电影的类型来划分的某一个数值,也就是列表中的第一个值,那为什么列表中有2个值呢,因为每种电影类型的数量不一样,所以我们需要找到每种类型的电影数量有多少,然后再去请求,这里小伙伴们就不要就写了,小耶已经帮大家写好了,db和cursor就是我们连接的数据库和游标,这里大家一定要加数据库换成自己的用户名和密码,且必须在运行这个文件前创建名叫douban的数据库。

class Douban:
    def __init__(self):
        self.url = 'https://movie.douban.com/j/chart/top_list?type={0}&interval_id=100%3A90&action=&start={1}&limit=20'
        self.headers = {
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/127.0.0.0',
            'cookie': 'll="108309"; bid=ypF5OtbNlSg; _pk_id.100001.4cf6=76af15049c8cc83a.1723513955.; __yadk_uid=zAARDdLWvW7KZNBKMZVicYIqUHa6uXM6; _vwo_uuid_v2=D3FAC8D3B8E4E71CC8897160A33C91583|6e30c52e71a0b1465cb45852bb98bb8e; _pk_ref.100001.4cf6=%5B%22%22%2C%22%22%2C1723597993%2C%22https%3A%2F%2Fcn.bing.com%2F%22%5D; _pk_ses.100001.4cf6=1; ap_v=0,6.0; __utma=30149280.933405728.1723513952.1723513952.1723597993.2; __utmb=30149280.0.10.1723597993; __utmc=30149280; __utmz=30149280.1723597993.2.2.utmcsr=cn.bing.com|utmccn=(referral)|utmcmd=referral|utmcct=/; __utma=223695111.1611865066.1723513955.1723513955.1723597993.2; __utmb=223695111.0.10.1723597993; __utmc=223695111; __utmz=223695111.1723597993.2.2.utmcsr=cn.bing.com|utmccn=(referral)|utmcmd=referral|utmcct=/'
        }
        self.movie_types = {'剧情': [11, 952], '喜剧': [24, 667], '动作': [5, 412], '爱情': [13, 484],
                            '科幻': [17, 195], '动画': [25, 159],
                            '悬疑': [10, 262], '惊悚': [19, 391], '恐怖': [20, 310], '纪录片': [1, 234],
                            '短片': [23, 336], '情色': [6, 94],
                            '音乐': [14, 78], '歌舞': [7, 60], '家庭': [28, 171], '儿童': [8, 32], '传记': [2, 124],
                            '历史': [4, 132], '战争': [22, 122],
                            '犯罪': [3, 377], '奇幻': [16, 231], '冒险': [15, 255], '灾难': [12, 21], '武侠': [29, 45],
                            '古装': [30, 85], '运动': [18, 53]}
        self.db = pymysql.connect(host='localhost', user='root', password='123456', database='douban', port=3306,
                                  charset='utf8')
        self.cursor = self.db.cursor()

3、发送请求

定义spyder函数来向接口发送请求

    def spyder(self):
        for key, value in self.movie_types.items():
            for page in range(0, value[1], 20):
                print('正在爬取:{0}的第{1}页!'.format(key, page))
                url = self.url.format(value[0], page)
                res = requests.get(url=url, headers=self.headers)
                data = res.json()
                for item in data:
                    item['type'] = key
                    yield item

4、解析数据

定义parse_data来解析我们的数据,解析电影标题,评分,电影排名,电影类型,发行国家,发行日期,演员人数,评价人数,演员名字,电影图片,电影详情页地址这些字段。

    @staticmethod
    def parse_data(data):
        data_dict = {}
        for item in data:
            data_dict['title'] = item['title']
            data_dict['score'] = float(item['score'])
            data_dict['rank'] = item['rank']
            data_dict['types'] = str(item['types'])
            data_dict['regions'] = item['regions'][0]
            data_dict['release_date'] = item['release_date']
            data_dict['actor_count'] = item['actor_count']
            data_dict['vote_count'] = item['vote_count']
            data_dict['actors'] = str(item['actors'])
            data_dict['img'] = item['cover_url']
            data_dict['url'] = item['url']
            data_dict['type']=item['type']
            yield data_dict

5、保存数据

    def save(self, data_dict):
        for item in data_dict:
            sql = """
                    INSERT INTO movieInfo (title ,score, rank_,movie_type, types, regions, release_date, actor_count, vote_count, actors, img, url)
                    VALUES (%s,%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
                    """
            self.cursor.execute(sql, (
                item['title'],
                item['score'],
                item['rank'],
                item['type'],
                item['types'],
                item['regions'],
                item['release_date'],
                item['actor_count'],
                item['vote_count'],
                item['actors'],
                item['img'],
                item['url']
            ))  # 执行sql语句
            print(item)
            self.db.commit()  #提交数据到数据库

6、定义主函数

用一个主函数来运行上面我们所定义的功能函数

    def run(self):
        columns = """CREATE TABLE IF NOT EXISTS movieInfo (
                        id INT AUTO_INCREMENT PRIMARY KEY,title varchar(32), score float, rank_ int, movie_type varchar(4) ,types varchar(64),  regions char(16),
                        release_date date,  actor_count int,  vote_count int,actors VARCHAR(128),  img VARCHAR(128), url varchar(128)) """
        self.cursor.execute(columns)  # 创建表的字段
        data = self.spyder()  # 运行发送请求函数
        data_dict = self.parse_data(data)  # 运行解析数据函数
        self.save(data_dict)  # 运行保存数据函数
        self.cursor.close()  # 关闭游标
        self.db.close()  # 关闭数据库

7、实例化对象运行主函数

if __name__ == '__main__':
    douban = Douban()
    douban.run()

8、运行效果

数据库里的数据,一共有6000多条数据

四、以下是全部完整代码

import pymysql
import requests


class Douban:
    def __init__(self):
        self.url = 'https://movie.douban.com/j/chart/top_list?type={0}&interval_id=100%3A90&action=&start={1}&limit=20'
        self.headers = {
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/127.0.0.0',
            'cookie': 'll="108309"; bid=ypF5OtbNlSg; _pk_id.100001.4cf6=76af15049c8cc83a.1723513955.; __yadk_uid=zAARDdLWvW7KZNBKMZVicYIqUHa6uXM6; _vwo_uuid_v2=D3FAC8D3B8E4E71CC8897160A33C91583|6e30c52e71a0b1465cb45852bb98bb8e; _pk_ref.100001.4cf6=%5B%22%22%2C%22%22%2C1723597993%2C%22https%3A%2F%2Fcn.bing.com%2F%22%5D; _pk_ses.100001.4cf6=1; ap_v=0,6.0; __utma=30149280.933405728.1723513952.1723513952.1723597993.2; __utmb=30149280.0.10.1723597993; __utmc=30149280; __utmz=30149280.1723597993.2.2.utmcsr=cn.bing.com|utmccn=(referral)|utmcmd=referral|utmcct=/; __utma=223695111.1611865066.1723513955.1723513955.1723597993.2; __utmb=223695111.0.10.1723597993; __utmc=223695111; __utmz=223695111.1723597993.2.2.utmcsr=cn.bing.com|utmccn=(referral)|utmcmd=referral|utmcct=/'
        }
        self.movie_types = {'剧情': [11, 952], '喜剧': [24, 667], '动作': [5, 412], '爱情': [13, 484],
                            '科幻': [17, 195], '动画': [25, 159],
                            '悬疑': [10, 262], '惊悚': [19, 391], '恐怖': [20, 310], '纪录片': [1, 234],
                            '短片': [23, 336], '情色': [6, 94],
                            '音乐': [14, 78], '歌舞': [7, 60], '家庭': [28, 171], '儿童': [8, 32], '传记': [2, 124],
                            '历史': [4, 132], '战争': [22, 122],
                            '犯罪': [3, 377], '奇幻': [16, 231], '冒险': [15, 255], '灾难': [12, 21], '武侠': [29, 45],
                            '古装': [30, 85], '运动': [18, 53]}
        self.db = pymysql.connect(host='localhost', user='root', password='123456', database='douban', port=3306,
                                  charset='utf8')
        self.cursor = self.db.cursor()

    def spyder(self):
        for key, value in self.movie_types.items():
            for page in range(0, value[1], 20):
                print('正在爬取:{0}的第{1}页!'.format(key, page))
                url = self.url.format(value[0], page)
                res = requests.get(url=url, headers=self.headers)
                data = res.json()
                for item in data:
                    item['type'] = key
                    yield item

    @staticmethod
    def parse_data(data):
        data_dict = {}
        for item in data:
            data_dict['title'] = item['title']
            data_dict['score'] = float(item['score'])
            data_dict['rank'] = item['rank']
            data_dict['types'] = str(item['types'])
            data_dict['regions'] = item['regions'][0]
            data_dict['release_date'] = item['release_date']
            data_dict['actor_count'] = item['actor_count']
            data_dict['vote_count'] = item['vote_count']
            data_dict['actors'] = str(item['actors'])
            data_dict['img'] = item['cover_url']
            data_dict['url'] = item['url']
            data_dict['type']=item['type']
            yield data_dict

    def save(self, data_dict):
        for item in data_dict:
            sql = """
                    INSERT INTO movieInfo (title ,score, rank_,movie_type, types, regions, release_date, actor_count, vote_count, actors, img, url)
                    VALUES (%s,%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
                    """
            self.cursor.execute(sql, (
                item['title'],
                item['score'],
                item['rank'],
                item['type'],
                item['types'],
                item['regions'],
                item['release_date'],
                item['actor_count'],
                item['vote_count'],
                item['actors'],
                item['img'],
                item['url']
            ))
            print(item)
            self.db.commit()

    def run(self):
        columns = """CREATE TABLE IF NOT EXISTS movieInfo (
                        id INT AUTO_INCREMENT PRIMARY KEY,title varchar(32), score float, rank_ int, movie_type varchar(4) ,types varchar(64),  regions char(16),
                        release_date date,  actor_count int,  vote_count int,actors VARCHAR(128),  img VARCHAR(128), url varchar(128)) """
        self.cursor.execute(columns)
        data = self.spyder()
        data_dict = self.parse_data(data)
        self.save(data_dict)
        self.cursor.close()
        self.db.close()

#  SET @@global.sql_mode= '';


if __name__ == '__main__':
    douban = Douban()
    douban.run()

五、报错解决

1、数据库连接报错

一定在运行这个爬虫文件之前创建叫douban的数据库

​create database douban;

连接数据时一定要换成自己的用户名和密码

self.db = pymysql.connect(host='localhost', user='用户名', password='密码', database='douban', port=3306,charset='utf8')

2、数据插入报错

如果出现一下类似报错,在douban的数据库里输入以下命令,然后在运行爬虫文件

报错:pymysql.err.DataError: (1406, "Data too long for column 'actors' at row 1")

SET @@global.sql_mode= '';

如下图,这样就成功解决了

如果帅哥,美女些觉得小耶这篇文章还不错,可以动动大家发财的小手,帮小耶点个赞

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值