爬取过程如下
1.获取网页URL
2.利用requests提取网页
3.解析网页数据,并利用正则表达式提取网页相关数据,并保存到datalist中
4.保存数据到excel中
用到的第三方包如下:用的是bs4+requests,用requests+xpath估计更快
import requests #用于获取网页数据 from bs4 import BeautifulSoup #用于解析网页数据 import xlwt #用于对excel表进行操作 from requests import exceptions #异常处理 import re #正则表达式
第一步,获取网页URL
在进入网页之后,通过分析网页的URL不难发现,此start对应的是每一页的第一个电影的位置start=24就是排行第24的电影
def main():
base_url = "https://movie.douban.com/top250?start="#start=?没写是为了后面拼接URL用的
#1.爬取网页,获取每部电影的数据保存到datalist中
datalist = getData(base_url)
#保存路径
# 2.保存数据到excel表
savepath = '豆瓣250.xls'
saveData(datalist,savepath)#保存
我们首先定义base_url = "https://movie.douban.com/top250?start="
start后面空着是为了拼接URL
第二步,利用requests提取网页
def askURL(url):
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:77.0) Gecko/20100101 Firefox/77.0"
}
try:
html = requests.get(url, headers=headers).text
except exceptions.Timeout as e:
print(e.reason)
except exceptions.HTTPError as e:
print(e.reason)
return html
第三步,解析网页数据,并利用正则表达式提取网页相关数据,并保存到datalist中
通过分析网页,我们发现有以下几个部分需要爬取(确定所需要爬取的内容):
("电影详情链接","图片链接","影片中文名","影片外国名","评分","评价数","概况","相关信息")
电影详情链接:
我们可以发现正是a标签里面的href
图片链接:
对应的是img标签
影片中文名:
对应的span标签
影片外国名:
也是span标签
评分:
也是span标签
评价数:
同理也是
概况:
概况也是span标签
相关信息:
是p标签
由以上分析可以写出提取信息的正则表达式如下:
#表达式 .* 的意思很好理解,就是单个字符匹配任意次,即贪婪匹配。
#表达式 .*? 是满足条件的情况只匹配一次,即懒惰匹配
#获取影片链接
findLink = re.compile(r'<a href="(.*?)">')
#获取图片的SRC
findimgSrc = re.compile(r'<img.*src="(.*?)"',re.S)#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)
getData函数如下:
def getData(baseurl):
datalist = []
#根据左闭右开,遍历10页
for i in range(0,10):
#拼接URL
url = baseurl+str(i*25)#由于每一页开头是0,25,50.....所以乘25
html = askURL(url)
# print(html)
#每个页面
soup = BeautifulSoup(html,"html.parser")
#因为电影相关信息是保存在class="item"这个中,所以只需要查找到div中的class="item"的即可
for item in soup.find_all('div',class_="item"):
data = [] #用于保存一部电影的完整信息
item = str(item)
#找到详情链接
link = re.findall(findLink,item)[0]#链接只有一个
data.append(link)#将Link保存到data列表中
#找到图片src
imgSrc = re.findall(findimgSrc,item)[0]
data.append(imgSrc)
#找到电影名
title = re.findall(findTitle,item)
#由于电影有中文名和英文名,所以需要分隔开来
if(len(title) == 2):
ctitle = title[0]#保存中文名到ctitle中
data.append(ctitle)
etitle = title[1].replace("/","")#字符串处理,并把英文名保存到etitle中
data.append(etitle)
else:
#如果没有英文名,直接加进去就行
data.append(title[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(" ")
#去掉br分隔符
bd = re.findall(findBd,item)[0]
bd = re.sub('<br(\s+)?>(\s+)?'," ",bd)
bd = re.sub('/'," ",bd)
data.append(bd.strip())#去掉前后空格
#把一部电影的所有存在data中的作为一个元组插入到datalist中
datalist.append(data)
return datalist
第四步,保存数据到excel中
def saveData(datalist,savepath):
#备用列表,用于存放datalist中的某一条数据
data = []
workbook = xlwt.Workbook(encoding="utf-8",style_compression=0)
worksheet = workbook.add_sheet('豆瓣电影top250',cell_overwrite_ok=True)
col = ("电影详情链接","图片链接","影片中文名","影片外国名","评分","评价数","概况","相关信息")
#在excel表第一行写入每一列应该保存的是什么
for i in range(0,8):
worksheet.write(0,i,col[i])
#一共爬取了250条数据,依次遍历放入excel中
for i in range(0,250):
print("第%d条数据写入完毕!"%(i+1))
data = datalist[i]
for j in range(0,8):
#写入数据
worksheet.write(i+1,j,data[j])
workbook.save(savepath)
全部过程代码如下:
#-*- codeing = utf-8 -*-
#@Time: 14:27
#@Author:long
#@File:spider.py
#@Software:PyCharm
import requests
from bs4 import BeautifulSoup
import xlwt
from requests import exceptions
import re
#表达式 .* 的意思很好理解,就是单个字符匹配任意次,即贪婪匹配。
#表达式 .*? 是满足条件的情况只匹配一次,即懒惰匹配
#re.compile指的是定义模式
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)
def main():
base_url = "https://movie.douban.com/top250?start="
#1.爬取网页,获取每部电影的数据保存到datalist中
datalist = getData(base_url)
#保存路径
# 2.保存数据到excel表
savepath = '豆瓣250.xls'
saveData(datalist,savepath)
def getData(baseurl):
datalist = []
for i in range(0,10):
url = baseurl+str(i*25)
html = askURL(url)
# print(html)
#解析每个页面
soup = BeautifulSoup(html,"html.parser")
for item in soup.find_all('div',class_="item"):
data = [] #用于保存一部电影的完整信息
item = str(item)
#找到详情链接
link = re.findall(findLink,item)[0]
data.append(link)
#找到图片src
imgSrc = re.findall(findimgSrc,item)[0]
data.append(imgSrc)
#找到电影名
title = re.findall(findTitle,item)
if(len(title) == 2):
ctitle = title[0]
data.append(ctitle)
etitle = title[1].replace("/","")#字符串处理
data.append(etitle)
else:
data.append(title[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(" ")
#去掉br
bd = re.findall(findBd,item)[0]
bd = re.sub('<br(\s+)?>(\s+)?'," ",bd)
bd = re.sub('/'," ",bd)
data.append(bd.strip())#去掉前后空格
datalist.append(data)
return datalist
def askURL(url):
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:77.0) Gecko/20100101 Firefox/77.0"
}
try:
html = requests.get(url, headers=headers).text
except exceptions.Timeout as e:
print(e.reason)
except exceptions.HTTPError as e:
print(e.reason)
return html
def saveData(datalist,savepath):
data = []
workbook = xlwt.Workbook(encoding="utf-8",style_compression=0)
worksheet = workbook.add_sheet('豆瓣电影top250',cell_overwrite_ok=True)
col = ("电影详情链接","图片链接","影片中文名","影片外国名","评分","评价数","概况","相关信息")
for i in range(0,8):
worksheet.write(0,i,col[i])
for i in range(0,250):
print("第%d条数据写入完毕!"%(i+1))
data = datalist[i]
for j in range(0,8):
worksheet.write(i+1,j,data[j])
workbook.save(savepath)
if __name__ == '__main__':
main()