# 基于python的网络爬虫-猫眼top100实践 **Repository Path**: jiaxiaozi/python_project ## Basic Information - **Project Name**: 基于python的网络爬虫-猫眼top100实践 - **Description**: 本文采用Windows 10系统及JetBrains PyCharm 2019.2.5 x64,实现了面向猫眼电影的网络爬虫,实现对猫眼Top100电影的爬取,并对得到的数据进行可视化分析及展示。 - **Primary Language**: Python - **License**: Not specified - **Default Branch**: master - **Homepage**: https://space.bilibili.com/44784041 - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 2 - **Created**: 2022-03-17 - **Last Updated**: 2022-03-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ### 一、 开发背景与环境介绍 - 豆瓣、猫眼、微博、B站等社交网络逐渐兴起,传统的网络爬虫无法满足人们对社交网络信息的爬取及分析的需求,故爬取特定主题内容的网络爬虫便应运而生,本文采用Windows 10系统及JetBrains PyCharm 2019.2.5 x64,实现了面向猫眼电影的网络爬虫,实现对猫眼Top100电影的爬取,并对得到的数据进行可视化分析及展示。 ### 二、 程序功能分析 - 运行本程序,即可实现自动爬取猫眼Top100,并将所得数据存入sqlite3数据库,之后通过Flask将数据呈现在网页端。 ### 三、 总体设计 1. 寻找爬虫入口,使用BeautifulSoup库解析爬取数据,将爬取到的信息保存到数据库。 2. 通过使用python的第三方库对数据库中的电影数据进行划分,提取各个属性有价值的部分,再利用html中的Flask,Echarts、WordCloud等技术,将其合理的展现在页面上,并添加”首页”,”电影”,”评分”,”词云”,”关于”标题,最后再对每个header进行一个html设计单击相关元素时进行相关页面跳转。 ### 四、 详细设计 - 寻找爬取入口 在Chrome浏览器中打开猫眼电影TOP100,其Url为:https://maoyan.com/board/4?offset= 。通过观察可以发现,目标数据是存在于网页源代码中的,直接请求网页Url即可获得。同时,第1页仅显示了10部电影,相比于第2页的Url:https://maoyan.com/board/4?offset=10,故可推断offset为偏移值。 所以在抓取信息时,只需改变offset所赋予的参数(第page页的 offset=10*(page-1))就可以实现自动翻页爬取。再通过 urllib.request 获取 html,向header中添加cookie和User-Agent实现伪装,以免出现美团滑块验证,最后将数据保存在html中,以便后续利用正则表达式对数据进行分析。 - 解析数据 解析保存的html文件,使用BeautifulSoup库,根据规则找到所需的内容所在位置,把电影的各类信息解析出来(先定位到每个电影的标签,再定位到各类信息的标签,最后将各类信息从标签中提取出来)。在解析过程中应结合re正则表达式提取所需内容。 设置askURL(url)方法,并将URL作为Request()方法的参 数,构造Request对象;将Request对象作为urlopen()方法的参数,发送给远程服 务器,获取网页内容返回列表;使用read( )方法读取远程服务器返回的页面信息执行完后返回 HTML网页内容。 - 保存数据 根据前面得到的解析结果datalist将所需内容保存到sqlite3数据库中,首先建立数据库,之后再进行连接,通过for循环对datalist进行遍历,以每列的属性值作为游标,并将所有数据转换为列表,最后按数组下标对属性值实施逐行插入操作。 - 可视化数据 Python 为我们提供了用来制作图表的库函数如,matplotlib,pandas等。事实证明这些方法已经十分成功,而本文使用apache开源web可视 化库 Echarts,集合 python 语言自动生成 Echarts 图表。它不但 可以绘制图表,还可以嵌入到独立的HTML网页。具有良好的性 能,并且使用方便。 ### 五、 部分源码及运行界面 ``` # -*- codeing =utf-8 -*- # @Time : 2020/12/5 20:44 # @Author : 三千xc # @File : maoYanSpider.py # @Software: PyCharm import sqlite3 # 获取网页数据 import requests # 正则表达式 import re # 网页解析,获取数据 from bs4 import BeautifulSoup # 保存为excel import xlwt #正则表达式规则 *表示多个字符,?表示0个到多个 #影片排名链接的规则 findIndex = re.compile(r'board-index.*?>(\d+).*?') #影片图片的链接 findImage = re.compile(r'class="board-img".*?src="(.*?)"') #影片片名 findTitle = re.compile(r'title="(.*?)">') #影片主演 findActor = re.compile(r'class="star">(.|\n)(.*)') #影片上映时间 findTime = re.compile(r'class="releasetime">(.*?)

') #猫眼评分 findScore1 = re.compile(r'class="integer">(.*?)') findScore2 = re.compile(r'class="fraction">(.*?)') # 爬取网页 # 解析数据 # 保存数据 def main(): baseurl = "https://maoyan.com/board/4?offset=" #1.爬取网页 datalist = getData(baseurl) #3.保存数据 # savepath = "猫眼TOP100.xls" dbpath = "movie2.db" # saveData(datalist, savepath) saveData2DB(datalist,dbpath) def getData(baseUrl): datalist = [] for i in range(0, 10): url = baseUrl + str(i * 10) html = askUrl(url) # 解析数据 soup = BeautifulSoup(html, "html.parser") for item in soup.find_all("dd"): # 测试 # print(item) data = [] item = str(item) # 排名 index = re.findall(findIndex, item)[0] data.append(index) # 图片地址 image = re.findall(findImage, item)[0] data.append(image) # 标题 title = re.findall(findTitle, item)[0] data.append(title) # 作者 actor = re.findall(findActor, item)[0] actorList = list(actor) for i in actorList: actorNew = "".join(i).strip() data.append(actorNew) # 上映时间 time = re.findall(findTime, item)[0] data.append(time) # 分数 score1 = re.findall(findScore1, item)[0] # data.append(score1) score2 = re.findall(findScore2, item)[0] # data.append(score2) score = score1 + score2 data.append(score) # print(data) datalist.append(data) #print(datalist) return datalist # 爬取网页 def askUrl(url): #模拟浏览器头部消息,向猫眼浏览器发送消息 headers = { "Accept":"* / *", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36", "Cookie":"BIDUPSID=E53D8374080760C7A143C4FD57FD9FC0; PSTM=1578902890; HMACCOUNT=6B314F8B0EFA06B7; BAIDUID=600AD9DA4AECD6C574A62250C5383D41:FG=1; BDRCVFR[Fz5t0nreVcc]=mk3SLVN4HKm; delPer=0; PSINO=6; H_PS_PSSID=; BA_HECTOR=ah0101ak2ka48k2hb31fu57qk0r; HMVT=6bcd52f51e9b3dce32bec4a3997715ac|1608687465|"} html = "" try: response = requests.get(url, headers=headers) html = response.content.decode("utf-8") # print(html) except requests.exceptions as e: if hasattr(e, "code"): print(e.code) if hasattr(e, "reason"): print(e.reason) return html # 保存数据到excel中 def saveData(datalist, savepath): # 创建book对象 book = xlwt.Workbook(encoding="utf-8") # 创建工作表 sheet = book.add_sheet("猫眼TOP100", cell_overwrite_ok=True) col = ("电影排名", "图片地址", "电影名称", "演出人员", "上映时间", "电影评分") for i in range(0, 6): sheet.write(0, i, col[i]) #col[i]代表列名 for i in range(0, 100): print("第%d条" % (i + 1)) try: data = datalist[i] except: continue for j in range(0, 6): #向表中写入数据 sheet.write(i + 1, j, data[j]) book.save(savepath) # 保存数据到数据库中 def saveData2DB(datalist, dbpath): init_db(dbpath) conn = sqlite3.connect(dbpath) cur = conn.cursor() for data in datalist: for index in range(len(data)): if index == 4: data[index] = '"' + str(data[index]) + '"' continue data[index] = '"' + data[index] + '"' sql = ''' insert into movie100( movie_rank,image_link,name,actor,time,score ) values(%s)''' % ",".join(data) # values(%s)'''%",". join('%s' %a for a in data) print(sql) cur.execute(sql) conn.commit() cur.close() conn.close() def init_db(dbpath): # 创建数据表 sql = """ create table movie100 ( movie_rank integer , image_link text , name varchar, actor varchar, time text, score numeric ) """ conn = sqlite3.connect(dbpath) # 获取游标 cursor = conn.cursor() # 执行sql语句 cursor.execute(sql) conn.commit() # 关闭数据库 conn.close() if __name__ == '__main__': # 当程序执行时调用函数 main() # init_db("movietest.db") print('爬取完成') # -*- codeing =utf-8 -*- # @Time : 2020/12/14 21:05 # @Author : 三千xc # @File : wordCloud.py # @Software: PyCharm #分词 import jieba #绘图,数据可视化 from matplotlib import pyplot as plt #词云 from wordcloud import WordCloud #图片处理 from PIL import Image #矩阵运算 import numpy as np #数据库 import sqlite3 #准备词云所需的文字 con = sqlite3.connect('movie.db') cur = con.cursor() sql = 'select instroduction from movie250' data = cur.execute(sql) text = "" for item in data: text = text + item[0] # print(item[0]) cur.close() con.close() #分词 cut = jieba.cut(text) string = ' '.join(cut) # print(len(string)) #打开遮罩图片 img = Image.open(r'.\static\images\spiderman.jpg') # 将图片转换为数组 img_array = np.array(img) wc = WordCloud( background_color='white', mask = img_array, font_path="MFQingShu_Noncommercial-Regular.otf" ) wc.generate_from_text(string) #绘制图片 fig = plt.figure(1) plt.imshow(wc) plt.axis('off') # plt.show() plt.savefig(r'.\static\images\word.jpg') # -*- codeing =utf-8 -*- # @Time : 2020/12/5 20:44 # @Author : 三千xc # @File : wechat.py.py # @Software: PyCharm import sqlite3 from flask import Flask,render_template import datetime app = Flask(__name__) # 路由解析,跳转主页 @app.route('/') def index(): return render_template("index.html") @app.route('/index') def home(): # return render_template("index.html") return index() # 跳转电影页面 @app.route('/movie') def movie(): datalist = [ ] con = sqlite3.connect("movie.db") cur = con.cursor() sql = "select * from movie250" data = cur.execute(sql) for item in data: datalist.append(item) cur.close() con.close() return render_template("movie.html",movies = datalist) # 跳转评分页面 @app.route('/score') def score(): #评分 score = [ ] #评分相同的电影数量 num = [ ] con = sqlite3.connect("movie2.db") cur = con.cursor() sql = "select score,count(score) from movie100 group by score" data = cur.execute(sql) for item in data: score.append(str(item[0])) num.append(item[1]) cur.close() con.close() return render_template("score.html",score = score,num = num) # 跳转关于页面 @app.route('/team') def team(): return render_template("team.html") # 跳转词云页面 @app.route('/word') def word(): return render_template("word.html") ''' #路由解析,通过用户访问相应的路径,匹配相应的函数 # @app.route('/') # def hello_world(): # return 'Hello World!!!!!!!!!222222!!!' #通过访问路径,获取用户的字符串参数 @app.route("/user/") def welcome(name): return "你好,%s"%name #通过访问路径,获取用户的整型参数 @app.route("/user/") def welcome2(id): return "你好,%d 好"%id # 路由路径不能重复,用户通过唯一的路径来访问特定的函数 # 返回给用户渲染后的网页文件 # @app.route("/") # def index2(): # return render_template("temp.html") # 向页面传递变量 @app.route("/") def index3(): time = datetime.date.today() num = ["1","2","3"] task = {"23":"45","67":"89"} return render_template("temp.html",var = time,list = num,task = task) ''' # 开启debug模式 if __name__ == '__main__': app.run() #运行截图 ``` ![输入图片说明](https://images.gitee.com/uploads/images/2021/0126/165551_b0488ce8_8483132.png "1.png") ![输入图片说明](https://images.gitee.com/uploads/images/2021/0126/165712_7a74f5ba_8483132.png "2.png") ![输入图片说明](https://images.gitee.com/uploads/images/2021/0126/165725_6a05c995_8483132.png "3.png") ![输入图片说明](https://images.gitee.com/uploads/images/2021/0126/165828_0d7a2af0_8483132.png "4.png") ![输入图片说明](https://images.gitee.com/uploads/images/2021/0126/165838_ea8136d5_8483132.png "5.png") ![输入图片说明](https://images.gitee.com/uploads/images/2021/0126/165847_29143d14_8483132.png "6.png")