爬虫学习
对于豆瓣电影的Tp250条movies数据的爬取+可视化我们分为两个步骤:
1、数据的爬取;
2、数据的可视化。
对于一个爬虫数据,我们简单就几行就可以爬取到一个完整网页:
import requests
head={
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36"
}
response = requests.get('https://www.baidu.com',headers=head)
html = response.text
print(html)
爬取结果(当然,有些网站能防爬,可能是乱码,也可能是因为ajax的原因爬取不完整):
一、数据爬取
那么我们怎么爬取完整的豆瓣电影并可视化呢?首先我们定义一个spider.py文件对电影数据进行爬取。spider.py文件内容我将按步骤划分(完整就是按步骤合起来,都归属于spider.py):
1、这是要用到的库文件
from bs4 import BeautifulSoup //用于解析拿到的网页
import re //用于匹配正则项
import urllib.request,urllib.error //用于配置访问网页路由,即想爬取网页地址
import pymysql //连接Mysql
2、接着我们根据豆瓣网页的HTML代码设置正则表达式
设置正则表达式的原因是提取你想要的部分,例如你想要电影名称、网址、图片、访问人数,都可以用正则表达式去提取。我这里简单拿出了想要的代码,如果不懂这个哪里来的,可以查看豆瓣Top250条电影的网页,按F12即可。
<img width="100" alt="肖申克的救赎" src="https://img2.doubanio.com/view/photo/s_ratio_poster/public/p480747492.webp" class="">
#下面的正则表达式根据这个html代码进行提取
................................正则表达开始式......................................................................
#影片详情链接
findLink = re.compile(r'<a href="(.*?)">') #创建正则表达式对象,表示匹配规则
#影片图片
#<img width="100" alt="肖申克的救赎" src="https://img2.doubanio.com/view/photo/s_ratio_poster/public/p480747492.webp" class="">
#下面的正则表达式根据这个html代码进行提取
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)
3、接着开始爬取数据设置
1、设置请求头,因为不设置的话,就会检测出是爬虫代码,无法爬取。请求头哪里来呢,访问豆瓣电影,F12就可以拿到。
这里用到了urllib的知识,有些用request、selenuim等
................................请求头设置......................................................................
def askURL(url):
head={
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36"
}
request=urllib.request.Request(url=url,headers=head) //这里是设置请求头信息
html = "" //用于存放待会爬取到的网页
try:
response = urllib.request.urlopen(request) //请求去访问URL地址
html = response.read().decode("utf-8") //保存爬到网页的html代码
# print(html)
except urllib.error.URLError as e:
if hasattr(e,"code"):
print(e.code)
if hasattr(e,"reason"):
print(e.reason)
return html
4、下一步就是加上正则提取想要数据,如果不知道每句话干嘛,可以print打印结果就明白了
................................数据开始爬取......................................................................
def getData(baseurl):
datalist = []
# 解析数据
for i in range(0,10):
url = baseurl + str(i*25)
html = askURL(url) //这里调用我们前面定义的askURL函数
soup = BeautifulSoup(html,"html.parser") //这里需要用html.parser解析一下爬到的网页Html代码
######### 上面三句,已经爬到整个网页数据了,下面for循环用来提取想要信息 ##############
for item in soup.find_all('div',class_="item"):
# print(item) 测试:查看电影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("/","") #去掉无关符号 /The Shawshank Redemption
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].replace("。","") #去掉句号
data.append(inq)
else:
data.append(" ") #留空
# 影片相关内容
bd = re.findall(findBd,item)[0]
bd = re.sub('<br(\s+)?/>(\s+)?'," ",bd) #去掉<br>
bd = re.sub('/'," ",bd) #替换
data.append(bd.strip()) #去掉前后空格
datalist.append(data) #把处理好的一部电影信息放入datalist中
return datalist
5、有了数据,接下来就用Mysql保存数据
...............................建立数据表并保存数据......................................................................
def init_db(): #建表操作
sql='''
create table movie250(
id int primary key auto_increment,
info_link text,
pic_link text,
cname varchar(100),
ename varchar(100),
score double,
rated double,
introduce text,
info text
)
'''
# 建立连接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456',db='spider',charset='utf8')
# 建立游标,python, 必须有一个游标对象, 用来给数据库发送sql语句, 并执行的.
cursor = conn.cursor()
cursor.execute(sql)
# 4. 关闭游标
cursor.close()
# 5. 关闭连接
conn.close()
def saveToMysql(dataList):
init_db()
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456',db='spider',charset='utf8')
cursor = conn.cursor()
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,introduce,info)
values(%s)'''%",".join(data)
# print(sql)
cursor.execute(sql)
conn.commit()
cursor.close()
conn.close()
6、这里我简单提一下PyCharm与Mysql连接步骤,看红框位置
在url的3306后面再加就能成功连接了
?serverTimezone=GMT
函数都定义好了,那就开始执行:
def main():
baseurl="https://movie.douban.com/top250?start="
# 爬取网页
datalist = getData(baseurl)
saveToMysql(datalist)
if __name__=="__main__":
main()
print("爬取完毕")
7、爬取结果
还 与 数 据 库 没 连 接 成 功 的 可 以 认 真 看 看 我 的 表 名 和 数 据 库 名 。 \color{red}{还与数据库没连接成功的可以认真看看我的表名和数据库名。 } 还与数据库没连接成功的可以认真看看我的表名和数据库名。
二、数据可视化
这里我运用到了比较简单的Flask框架,用到上面spider.py爬到的数据。由于html文件比较多,我就简单放一个app.py,完整项目代码,文件夹附上。
app.py
from flask import Flask,render_template
import pymysql
app = Flask(__name__)
@app.route('/')
def index():
return render_template("index.html")
@app.route('/index')
def index2():
return render_template("index.html")
# return index() 也可
@app.route('/movie')
def movie():
dataList = []
# 建立连接
conn = pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd='123456',db='spider',charset='utf8')
# 建立游标,python, 必须有一个游标对象, 用来给数据库发送sql语句, 并执行的.
cursor = conn.cursor()
# 4. 关闭游标
sql = 'select * from movie250'
result = cursor.execute(sql)
data = cursor.fetchall() #查询得到的结果是元组((1,...),(2,...))
for item in data:
dataList.append(item)
cursor.close()
# 5. 关闭连接
conn.close()
return render_template("movie.html",movies=dataList)
@app.route('/score')
def score():
score =[] #评分
num = [] #每个评分对应的电影数量
# 建立连接
conn = pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd='123456',db='spider',charset='utf8')
# 建立游标,python, 必须有一个游标对象, 用来给数据库发送sql语句, 并执行的.
cursor = conn.cursor()
# 4. 关闭游标
sql = 'select score,count(score) from movie250 group by score'
cursor.execute(sql)
data = cursor.fetchall() #查询得到的结果是元组((1,...),(2,...))
for item in data:
score.append(str(item[0]))
num.append(item[1])
cursor.close()
# 5. 关闭连接
conn.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")
if __name__ == '__main__':
app.run()
1、可视化结果
文中与数据库的连接别忘记修改成自己的喔
conn = pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd='123456',db='spider',charset='utf8')