目录
一、背景
二、分析网站
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= '';
如下图,这样就成功解决了
如果帅哥,美女些觉得小耶这篇文章还不错,可以动动大家发财的小手,帮小耶点个赞