一.题目:
1.爬取豆瓣电影Iop250电影信息,包括观看链接,名称、图片链接等一系列信息
2.爬取后的结果保存到excel文件、数据库文件
3.进行网页设计,将爬取结果进行flask可视化处理
注:本学习内容来自b站IT私塾,文章末尾附视频链接。
二.设计思路&代码:
1.导入模块
import re # 正则表达式,进行文字匹配
import urllib.error # 指定URL,获取网页数据
import urllib.request
import xlwt # 进行excel操作
from bs4 import BeautifulSoup # 网页解析,获取数据
import sqlite3 # 进行SQlite数据库操作
import ssl
各个模块功能已经注释列出,这里不再细说。
2.爬取网页
要爬取网页内容,我们的主要思路就是模拟浏览器访问网页,网页内容都隐藏在网页代码中,成功访问到网页以后,我们需要对网页的有用信息进行查找,筛选,得到自己需要的数据。
以本程序为例:
我们首先需要打开目标网站分析:
(1)从图中可以看出,排名前250的电影一共有十页,每页25条数据,所以这里我们需要一个for循环,对十个页面进行逐一访问,并将每次访问的返回信息(网页代码)保存在html变量中;
(2)观察网页源代码(快捷键:F12),可以看出每一个
#全局变量
# 找到影片详情链接的规则
findLink = re.compile(r'') # 创建正则表达式对象,表示规则(字符串模式)
# 找到影片图片
findImgSrc = re.compile(r' ', re.S) # re.S 让换行符包含在字符中
# 找到影片名
findTitle = re.compile(r'(.*?)') #
# 找到影片评分
findRating = re.compile(r' ')
# 找到评价人数
findJudge = re.compile(r'(\d*)人评价')
# 找到概况
findInq = re.compile(r'(.*?)') #
# 找到影片相关内容
findBd = re.compile(r'(.*?)
', re.S)
(4)将所提取内容去掉多余的部分(通过replace、sub等模块),并保存在一个datalist列表中:
# 爬取网页
def getDate(baseurl):
datalist = []
for i in range(0, 10): # 调用获取页面信息的函数,10次
url = baseurl + str(i * 25)
html = askURL(url) # 保存获取到的网页源码
# 2.逐一解析数据
soup = BeautifulSoup(html, "html.parser")
for item in soup.find_all('div', class_="item"): # 查找符合要求的字符串,形成一个列表;class为一个类别,需要加下划线
# print(item) # 测试,查看电影item全部信息
data = [] # 保存一部电影的所有信息
item = str(item)
# 影片详情的链接
link = re.findall(findLink, item)[0] # re库用来通过正则表达式查找指定的字符串
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("/", "") # 去掉无关的符号
otitle = otitle.replace(u'\xa0', u' ')
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 inq != 0:
inq = str(inq).replace("。", "") # 去掉句号
inq = inq.replace("'", "")
inq = inq.replace('"', "")
inq = inq.replace("[", "")
inq = inq.replace("]", "")
data.append(inq) # 添加概述
else:
data.append(" ") # 留空
bd = re.findall(findBd, item)[0]
bd = re.sub('
(\s+)?', " ", bd) # 去掉
bd = re.sub('/', " ", bd) # 替换/
bd = bd.replace(u'\xa0', u' ')
data.append(bd.strip()) # 去掉前后的空格
datalist.append(data) # 把处理好的一部电影的信息放入datalist
# print(datalist)
return datalist
3.得到网页信息
在指定网页,访问网页
# 得到指定一个URL的网页信息
def askURL(url):
# 模拟浏览器头部信息,向豆瓣服务器发送消息
# 用户代理,告诉豆瓣服务器,我们是什么类型的机器,浏览器(本质上是告诉浏览器,我们可以接受什么水平的文件内容)
header = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0"
}
# head["U"] #多个用数组
# ssl._create_default_https_context = ssl._create_unverified_context
request = urllib.request.Request(url=url, headers=header)
html = ""
try:
response = urllib.request.urlopen(request)
html = response.read().decode("utf-8")
# print(html)
except urllib.error.URLError as e:
if hasattr(e, "code"): # 判断e这个对象里是否包含code这个属性
print(e.code)
print("code here error")
if hasattr(e, "reason"):
print(e.reason)
print("reason here error")
return html
此处为模仿浏览器的操作,获取访问请求头,进行定义,通过request()函数得到网页返回信息。
4.保存数据
保存到excel表格(通过xlwt模块):
分为创建对象、创建工作表、保存等三步。
# 保存数据
def saveData(datalist, savepath):
print("Excel saveing...")
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):
print("第%d条" % (i + 1))
data = datalist[i]
for j in range(0, 8):
sheet.write(i + 1, j, data[j]) # 数据
book.save(savepath) # 保存数据表
print("保存完毕")
def saveData2DB(datalist, dbpath):
print("Sqlite saveing...")
init_db(dbpath)
conn = sqlite3.connect(dbpath)
cur = conn.cursor()
# cur.execute()
for data in datalist:
for index in range(len(data)):
if index == 4 or index == 5:
continue
data[index] = '"' + data[index] + '"'
sql = '''
insert into movie250(info_link,pic_link,cname,ename,score,rated,instroduction,info)
values(%s)''' % ",".join(data)
# print(sql)
cur.execute(sql)
conn.commit()
cur.close()
conn.close()
保存到Sqlite3数据库:
分为创建数据表、连接、获得游标(指针)、语句执行、提交、关闭数据库等步骤。
def saveData2DB(datalist, dbpath):
print("Sqlite saveing...")
init_db(dbpath)
conn = sqlite3.connect(dbpath)
cur = conn.cursor()
# cur.execute()
for data in datalist:
for index in range(len(data)):
if index == 4 or index == 5:
continue
data[index] = '"' + data[index] + '"'
sql = '''
insert into movie250(info_link,pic_link,cname,ename,score,rated,instroduction,info)
values(%s)''' % ",".join(data)
# print(sql)
cur.execute(sql)
conn.commit()
cur.close()
conn.close()
def init_db(dbpath):
sql = '''
create table if not exists movie250
(
id integer primary key autoincrement,
info_link text,
pic_link text,
cname varchar,
ename varchar,
score numeric,
rated numeric,
instroduction text,
info text
)
''' # 创建数据表 drop table if exists movie250
conn = sqlite3.connect(dbpath)
cursor = conn.cursor()
cursor.execute(sql)
conn.commit()
conn.close()
主程序调用上面所包装的一个个函数,逐一进行访问、提取、保存。
def main():
baseurl = "https://movie.douban.com/top250?start="
# 1.爬取网页
datalist = getDate(baseurl)
# 3.1 保存数据到excle表格中;或者 r“.\”;保存在excle中
savepath = "豆瓣电影Top250.xls"
saveData(datalist, savepath)
print(">>表格保存完毕")
# 3.2 保存到数据库中
dbpath = "movie.db"
saveData2DB(datalist, dbpath)
print(">>数据库保存完毕")
# askURL("https://movie.douban.com/top250?start=0")
# askURL("https: //baidu.com")
if __name__ == "__main__": # 当程序执行时
# 调用函数
main()
print(">>爬取完毕")
# init_db("movietest.db")
# print("数据库创建完成")
6.flask网页可视化
待更新…
三.运行结果:
1.excel列表结果:
2.Sqlite3数据库保存结果:
四.总结:
注意:上述过程建议每进行一步,对所得到内容进行输出,查看自己的目的是否实现,加入try…except…结构,及时对错误信息进行输出,调试
1.关于< no host given >错误
首先,一定要检查自己的标点符号,自己就是因为一个小小的空格,导致出现这个错误,而且,这个问题99%的错误都是因为标点符号的问题,详情如下:
原代码:
askURL("https: //movie.douban.com/top250?start=0")
askURL("https://movie.douban.com/top250?start=0")
所以,出现这个问题,一定记得仔仔细细检查自己url处的连接是否正确
url = "https://movie.douban.com/top250?start=0"
request = urllib.request.Request(url=url,headers=head)
①是不是网址敲错了
②反斜杠还是斜杠
③冒号有没有少
④有没有在链接里插入多余的空格
2.IndentationError: unindent does not match any outer indentation level 错误
遇到这个错误,是因为某行代码未对齐,导致程序运行中途出错
比如:
我这块return 前面多加了个空格,就没法按照逻辑执行下去,删掉即可
3.函数中类名问题
我们使用find_all()函数,找出class="item"的部分,如图:
在程序中,需要在class后加个下划线,表示class为类名
4.sqlite3.OperationalError: near “https”: syntax error报错
属于语法问题,先对数据库execute()进行注释
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210206101906765.png
逐个输出sql语句:
检查发现,电影链接前面有两个("),属于语法错误
回去查看对电影链接的提取部分,
发现少了一个("),加上之后:
该错误消失
5.sqlite3.OperationalError: near “width”: syntax error 报错
同问题4,一样的错误,检查sql输出:
图片链接末尾多了个width=“100”,对比原网页代码,和自己的正则表达式:
修改图片链接提取正则表达式:
问题消失。
6.结果出现&NBSP的处理办法
找到NBSP的出现位置,在添加时,加上一句
string.replace(u'\xa0', u' ') #string为待操作的字符串
即可。
视频链接:python爬虫及数据可视化