前言: 跟着B站的一个视频学习了python爬虫的基本内容,学完之后想把爬取豆瓣电影信息的过程记录下来,于是便有了这篇文章。
学习视频网址: https://www.bilibili.com/video/BV12E411A7ZQ/
1、需求分析
爬取豆瓣电影Top250的基本信息,包括电影的名称,豆瓣评分,评价数,电影概况,电影链接等。
爬取网址:https://movie.douban.com/top250?start=
2、获取数据
# askURL函数获取一个页面全部的源代码
def askURL(url):
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.183"
}
req = urllib.request.Request(url, headers=headers) # 发送请求
html = ''
try:
response = urllib.request.urlopen(req) # 获取响应
html = response.read().decode("utf-8") # 读取页面内容
print(html)
except urllib.error.URLError as e:
if hasattr(e, "code"): # hasattr()方法用于判断对象是否包含某一属性
print(e.code) # 输出错误代码
if hasattr(e, "reason"):
print(e.reason) # 输出错误的原因
return html
在访问页面时经常会出现错误,为了程序正常运行,加入异常捕获 try…except… 语句。
# 获取250条一共25页的全部源代码
def getData(baseurl):
for i in range(0, 250, 25):
url = baseurl + str(i) # baseurl中start=0-249,每次增加25
html = askURL(url) # 获取到的一页网页源码
在主函数中调用getData()函数。
# 1、获取数据
baseurl = "https://movie.douban.com/top250?start="
dataList = getData(baseurl)
3、解析内容
使用BeautifulSoup定位特定的标签位置,使用正则表达式找到具体的内容。
在getData()函数中获取到一页的网页源代码之后,解析一页的内容。
# 逐一解析数据
soup = BeautifulSoup(html, "html.parser") # BeautifulSoup库解析获取到的数据内容
for item in soup.findAll("div", class_="item"): # 找到每一个影片项
data = [] # 存储一个影片的各种信息
item = str(item) # 转换成字符串
link = re.findall(findLink, item)[0]
data.append(link) # 添加影片详情链接
imgSrc = re.findall(findImgSrc, item)[0]
data.append(imgSrc) # 添加图片链接
titles = re.findall(findTitle, item)
# 片名可能只有一个中文名,没有外国名
if len(titles) == 2:
ctitle = titles[0]
data.append(ctitle) # 添加中文名
otitle = titles[1].replace("/", "") # 去掉无关符号
data.append(otitle) # 添加外文名
else:
data.append(titles[0])
data.append(' ') # 外国名字留空
rating = re.findall(findRating, item)[0]
data.append(rating) # 添加评分
judgeNum = re.findall(findJudge, item)[0]
data.append(judgeNum) # 添加评价人数
inq = re.findall(findInq, item)
if len(inq) != 0:
inq = inq[0]
data.append(inq) # 添加概述
else:
data.append(" ") # 留空
bd = re.findall(findBd, item)[0] # 找到影片相关内容信息
bd = re.sub("<br(\s+)?/>(\s+)?", " ", bd) # 去掉<br>
data.append(bd.strip()) # 去掉前后空格
data_list.append(data) # 把处理好的一部电影信息放入data_list
3.1、标签解析
BeautifulSoup是一个库,提供一些简单的、python式的用来处理导航、搜索、修改分析树等功能,通过解析文档为用户提供需要抓取的数据。
我们需要的每个电影的数据都在一个<div>标签中,且每个div标签都有一个属性 class=“item”。
soup = BeautifulSoup(html, "html.parser")
for item in soup.findAll("div", class_="item"):
3.2、正则提取
正则表达式,通常被用来检索、替换那些符合某个模式(规则)的文本,是对字符串操作的一种逻辑公式。
python中使用re模块操作正则表达式。
# 找到影片详情链接
findLink = re.compile(r'<a href="(.*?)">')
# 找到影片图片
findImgSrc = re.compile(r'<img.*src="(.*?)"', re.S)
# 找到片名
findTitle = re.compile(r'<span class="title">(.*)</span>')
# 找到评分
findRating = re.compile(r'<span class="rating_num" property="v:average">(.*)</span>')
# 找到评价人数
findJudge = re.compile(r'<span>(\d*)人评价</span>')
# 找到概况
findInq = re.compile(r'<span class="inq">(.*)</span>')
# 找到影片相关内容:导演,主演,年份,地区,类别
findBd = re.compile(r'<p class="">(.*?)</p>', re.S)
4、保存数据
本文提供两种保存数据的方法,一种是将数据保存在excel表格中,另一种是将数据保存到sqlite数据库中。
在主函数中调用savaData()函数或者saveDataToDB()函数。
# 2、保存数据
# 2.1、将数据保存到excel表格
save_path = "./movie_data/doubanTop250.xls"
saveData(save_path, dataList)
# 2.2、将数据保存到数据库
dbpath = "./movie_data/dbTop250.db"
saveDataToDB(dbpath, dataList)
4.1、存储到excel表
利用python库xlwt将抽取的数据列表data_list存入excel表格。
def saveData(save_path, data_list):
book = xlwt.Workbook(encoding="utf-8", style_compression=0) # 创建一个workbook对象
sheet = book.add_sheet("豆瓣电影Top250", cell_overwrite_ok=True) # 创建工作表
col = ("影片详情链接", "图片链接", "中文名", "外国名", "豆瓣评分", "评价数", "电影概述", "相关信息") # 列名
for i in range(0, 8):
sheet.write(0, i, col[i]) # 写入列名
for i in range(0, 250):
data = data_list[i]
for j in range(0, 8):
sheet.write(i+1, j, data[j]) # 写入一条电影的各种数据
book.save(save_path) # 保存
4.2、存储到数据库
初始化数据库,创建一个数据库表movieTop250。
def init_db(dbpath):
sql = '''
create table movieTop250
(id integer primary key autoincrement,
info_link text,
pic_link text,
chinese_name varchar,
english_name varchar,
score numeric,
rated numeric,
introduction text,
info text);
''' # 创建数据表 movieTop250
conn = sqlite3.connect(dbpath) # 通过sqlite3连接该数据库
cursor = conn.cursor() # 获取游标
cursor.execute(sql) # 执行sql语句
conn.commit() # 提交数据库操作
conn.close() # 关闭数据库
将获取到的250条电影数据存入sqlite数据库。
def saveDataToDB(dbpath, data_list):
init_db(dbpath) # 初始化数据库
conn = sqlite3.connect(dbpath) # 通过sqlite3连接该数据库
cursor = conn.cursor()
for data in data_list: # 将每条电影信息插入数据库表
for index in range(len(data)): # 给字符串类型的数据加上双引号
if index == 4 or index == 5: # 数字类型的数据不用加引号
continue
data[index] = '"' + data[index] + '"'
# 写插入语句
sql = '''
insert into movieTop250 (
info_link, pic_link, chinese_name, english_name, score, rated, introduction, info)
VALUES (%s)''' % ",".join(data)
# print(sql)
cursor.execute(sql) # 执行插入语句
conn.commit() # 提交数据库操作
cursor.close()
conn.close()