在学习python基础以及一些爬虫基础概念之后,为了加深自己对知识的理解,于是跟着视频以及结合自己的心得,记录自己这段时间学习爬虫的实战项目心得。
【准备工作】
1.豆瓣电影Top250网站地址:https://movie.douban.com/top250
2.会使用浏览器开发者模式查找 User-Agent(这个东西的作用主要是防止我们爬取网页别系统检测到,后文我们会讲解)
3.会使用python中的相关库:re、urllib、xlwt、BeautifulSoup、request
re(Python的标准库,主要用于字符串匹配):https://www.cnblogs.com/beiyin/p/9129604.html
urllib(python内置的http请求库):https://www.cnblogs.com/qikeyishu/p/10748497.html
xlwt(操作excel主要用到xlrd和xlwt这两个库):https://www.cnblogs.com/liuguojun/p/11329594.html
BeautifulSoup(最主要的功能是从网页抓取数据,并解析):https://www.cnblogs.com/scios/p/8652760.html
【开始工作】
1.爬取网页首先我们需要获取网页链接,我们定义一个函数名字叫做:askURL(url)
# 获取网页链接
def askURL(url):
head = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"
}
req = urllib.request.Request(url, headers=head)
html = ""
try:
response = urllib.request.urlopen(req)
html = response.read().decode('utf-8') # read()获取响应体的内容,内容是bytes字节流,需要转换成字符串
#print(html)
except urllib.error.URLError as e: # 处理异常,如果被检测到了返回418
if hasattr(e,"code"):
print(e.code)
if hasattr(e,"reason"):
print(e.reason)
return html
可以看到我们写的函数里面有一段这样的代码,这句话主要是用于防止被监测到
head = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"
}
req = urllib.request.Request(url, headers=head)
那么我们如何获取到head里面这些东西呢,操作如下:
打开豆瓣电影Top250 https://movie.douban.com/top250,快捷键(Fn+F12)我的是笔记本,台式的话就是F12,如下所示
我们刷新下网页,出现如下所示
这里我们可以测试下我们获取的网页内容
import urllib
import re
import xlwt
from bs4 import BeautifulSoup
from urllib import request
def main():
baseUrl = 'https://movie.douban.com/top250?start='
askURL(baseUrl)
# 获取网页链接
def askURL(url):
head = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"
}
req = urllib.request.Request(url, headers=head)
html = ""
try:
response = urllib.request.urlopen(req)
html = response.read().decode('utf-8') # read()获取响应体的内容,内容是bytes字节流,需要转换成字符串
print(html)
except urllib.error.URLError as e:
if hasattr(e,"code"):
print(e.code)
if hasattr(e,"reason"):
print(e.reason)
return html
if __name__ == '__main__':
main()
测试结果如下(截取一小部分):
2.爬取了网页接下来我们需要的就是获取网页内容,我们写一个叫做 getData(baseUrl)的函数
通过分析我们可以看到豆瓣电影Top250 一页有25部电影,而且每一页对应的url也不同,如下所示
这是首页和第二页的地址,到了第二页url的格式就不同了,start=25代表的是上一页最后一部电影的编号
https://movie.douban.com/top250
https://movie.douban.com/top250?start=25&filter=
所以我们可以想一个办法将上面的url改成如下所示
https://movie.douban.com/top250?start=0
https://movie.douban.com/top250?start=25
因为有250部电影,所以每一页有25部,共10页,可以通过下面这个方法获取到每一页的完整url
# baseUrl是我们传入的地址 ,str(i*25)相当于start后面的数字
for i in range(0, 10):
url = baseUrl + str(i*25)
这样我们来简单测试下通过传入完成的url来解析后获得的数据是什么
import urllib
import re
import xlwt
from bs4 import BeautifulSoup
from urllib import request
def main():
baseUrl = 'https://movie.douban.com/top250?start='
getData(baseUrl)
#askURL(baseUrl)
# 爬取网页
def getData(baseUrl):
datalist = []
for i in range(0, 10):
url = baseUrl + str(i*25)
html = askURL(url) # 保存获取到的网页
print(html)
# 获取网页链接
def askURL(url):
head = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"
}
req = urllib.request.Request(url, headers=head)
html = ""
try:
response = urllib.request.urlopen(req)
html = response.read().decode('utf-8') # read()获取响应体的内容,内容是bytes字节流,需要转换成字符串
#print(html)
except urllib.error.URLError as e:
if hasattr(e,"code"):
print(e.code)
if hasattr(e,"reason"):
print(e.reason)
return html
if __name__ == '__main__':
main()
print("爬取完毕。")
测试结果如下:
上面测试我们可以获取这250部电影的相关信息,但是这里面的一些标签却不是我们想要的内容,所以我们需要解析,然后过滤掉这些对我们没有用的数据。
import urllib
import re
import xlwt
from bs4 import BeautifulSoup
from urllib import request
def main():
baseUrl = 'https://movie.douban.com/top250?start='
getData(baseUrl)
# 爬取网页
def getData(baseUrl):
datalist = []
for i in range(0, 10):
url = baseUrl + str(i*25)
html = askURL(url) # 保存获取到的网页
# 逐一解析数据
soup = BeautifulSoup(html, 'html.parser') # 也可以使用lxml代替html.parser作为解析器
print(soup.find_all('div', class_="item"))
# 获取网页链接
def askURL(url):
head = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"
}
req = urllib.request.Request(url, headers=head)
html = ""
try:
response = urllib.request.urlopen(req)
html = response.read().decode('utf-8') # read()获取响应体的内容,内容是bytes字节流,需要转换成字符串
#print(html)
except urllib.error.URLError as e:
if hasattr(e,"code"):
print(e.code)
if hasattr(e,"reason"):
print(e.reason)
return html
if __name__ == '__main__':
main()
print("爬取完毕。")
通过解析器我们可以看到每一部电影在网页中的具体位置,测试结果如下(截取一部电影):
导演: 弗兰克·德拉邦特 Frank Darabont 主演: 蒂姆·罗宾斯 Tim Robbins /...
1994 / 美国 / 犯罪 剧情
2143966人评价
希望让人自由。
这段代码的意思就是通过查找标签为div里面且属性class=“item”里面的所有内容,就是上面我们看到的这部分
soup.find_all('div', class_="item")
好了,既然获取到了主体部分,接下来我们就要根据我们的需求获取影片链接、影片图片、影片名字、影片评分、影片评价人数、影片概况以及影片内容
import urllib
import re
import xlwt
from bs4 import BeautifulSoup
from urllib import request
def main():
baseUrl = 'https://movie.douban.com/top250?start='
# 爬取网页
#datalist = getData(baseUrl)
getData(baseUrl)
askURL(baseUrl)
# 创建影片超链接正则表达式
findLink = re.compile(r'')
# 创建图片正则表达式
findImgSrc = re.compile(r'(.*)')
# 创建评分正则表达式
findRating = re.compile(r'(\d*)人评价')
# 创建概况正则表达式
findInq = re.compile(r'(.*)')
# 创建影片相关内容正则表达式
findBd = re.compile(r'(.*?)
', re.S)
# 爬取网页
def getData(baseUrl):
datalist = []
for i in range(0, 10):
url = baseUrl + str(i*25)
html = askURL(url) # 保存获取到的网页
# 逐一解析数据
soup = BeautifulSoup(html, 'html.parser') # 也可以使用lxml代替html.parser作为解析器
#print(soup.find_all('div', class_="item"))
# 通过条件筛选我们需要的列表
for item in soup.find_all('div', class_="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("/", " ") # 去掉标题中的/字符
data.append(otitle.split()) # 添加英文名,并将空格去掉
else:
data.append(titles[0])
data.append(" ") # 留空
# 获取影片评分
rating = re.findall(findRating, item)[0]
data.append(rating) # 添加影片评分
# 获取评价人数
judge = re.findall(findJudge, item)[0]
data.append(judge) # 添加评论人数
# 获取概况
inq = re.findall(findInq, item)
data.append(inq) # 添加概况
# 获取影片内容
bd = re.findall(findBd, item)[0]
bd = re.sub('
(\\s+)', " ", bd) # 使用空格替换掉
'
bd = re.sub('/', " ", bd) # 使用空格替换掉/
data.append(bd.split()) # 去掉前后的空格(\xa0代表空白符  使用strip()无法去掉)
print(data)
datalist.append(data) # 将一页的电影信息添加进去
return datalist
# 获取网页链接
def askURL(url):
head = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"
}
req = urllib.request.Request(url, headers=head)
html = ""
try:
response = urllib.request.urlopen(req)
html = response.read().decode('utf-8') # read()获取响应体的内容,内容是bytes字节流,需要转换成字符串
#print(html)
except urllib.error.URLError as e:
if hasattr(e,"code"):
print(e.code)
if hasattr(e,"reason"):
print(e.reason)
return html
if __name__ == '__main__':
main()
print("爬取完毕。")
')
# 创建评价人数正则表达式
findJudge = re.compile(r'
运行结果如下:
3.爬取到了数据接下来我们需要保存数据(这里我们采取保存数据到excel中)
# 保存数据
def saveData(datalist,savepath):
# 创建工作簿
book = xlwt.Workbook(encoding="utf-8")
# 创建工作表
sheet = book.add_sheet('豆瓣电影Top250', cell_overwrite_ok=True) # 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)
完整代码
import urllib
import re
import xlwt
from bs4 import BeautifulSoup
from urllib import request
def main():
baseUrl = 'https://movie.douban.com/top250?start='
# 爬取网页
datalist = getData(baseUrl)
savepath = '豆瓣电影Top250.xls'
# 保存数据
saveData(datalist, savepath)
askURL(baseUrl)
# 创建影片超链接正则表达式
findLink = re.compile(r'')
# 创建图片正则表达式
findImgSrc = re.compile(r'(.*)')
# 创建评分正则表达式
findRating = re.compile(r'(\d*)人评价')
# 创建概况正则表达式
findInq = re.compile(r'(.*)')
# 创建影片相关内容正则表达式
findBd = re.compile(r'(.*?)
', re.S)
# 爬取网页
def getData(baseUrl):
datalist = []
for i in range(0, 10):
url = baseUrl + str(i*25)
html = askURL(url) # 保存获取到的网页
# 逐一解析数据
soup = BeautifulSoup(html, 'html.parser') # 也可以使用lxml代替html.parser作为解析器
#print(soup.find_all('div', class_="item"))
# 通过条件筛选我们需要的列表
for item in soup.find_all('div', class_="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("/", " ") # 去掉标题中的/字符
data.append(otitle.split()) # 添加英文名,并将空格去掉
else:
data.append(titles[0])
data.append(" ") # 留空
# 获取影片评分
rating = re.findall(findRating, item)[0]
data.append(rating) # 添加影片评分
# 获取评价人数
judge = re.findall(findJudge, item)[0]
data.append(judge) # 添加评论人数
# 获取概况
inq = re.findall(findInq, item)
data.append(inq) # 添加概况
# 获取影片内容
bd = re.findall(findBd, item)[0]
bd = re.sub('
(\\s+)', " ", bd) # 使用空格替换掉
'
bd = re.sub('/', " ", bd) # 使用空格替换掉/
data.append(bd.split()) # 去掉前后的空格(\xa0代表空白符  使用strip()无法去掉)
datalist.append(data) # 将一页的电影信息添加进去
return datalist
# 获取网页链接
def askURL(url):
head = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"
}
req = urllib.request.Request(url, headers=head)
html = ""
try:
response = urllib.request.urlopen(req)
html = response.read().decode('utf-8') # read()获取响应体的内容,内容是bytes字节流,需要转换成字符串
#print(html)
except urllib.error.URLError as e:
if hasattr(e,"code"):
print(e.code)
if hasattr(e,"reason"):
print(e.reason)
return html
# 保存数据
def saveData(datalist,savepath):
# 创建workBook对象
book = xlwt.Workbook(encoding="utf-8")
# 创建工作表
sheet = book.add_sheet('豆瓣电影Top250', cell_overwrite_ok=True) # 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)
if __name__ == '__main__':
main()
print("爬取完毕。")
')
# 创建评价人数正则表达式
findJudge = re.compile(r'
运行结果如下:
在编译器左侧生成了一个豆瓣电影Top250.xls的表格
点击表格,我们可以看到如下结果:
参考资料:五天学会爬虫(这里主要看15-25节视频就可以,这个视频讲解的非常好)