目录
- 写在前文
- 获取网页数据
- 提取数据
- 整合并保存数据
- 运行结果
点击此处,获取海量Python学习资料!
写在前文
在这篇博客中,我们将会从头开始实现完整的python简单爬虫项目。爬虫是一门高深的学问,这里说的简单爬虫是指获取的数据为静态网页数据,选择B站也是因为作者本身也是老二刺猿了,同时B站没有严格的反爬虫措施,适合新手的爬虫练手。由于本人第一次写博客,在编写的过程中难免会出现错误,如有发现错误或者不合理之处,欢迎到评论区留言指正~
获取网页数据
我们要爬取的内容是B站上的热门视频排行榜(全站版)
首先我们获取网页内容,为此需要构造网页网址url和请求头heqders。由于我使用的是谷歌浏览器,不同浏览器之间的使用方法可能会有些不同,这里以谷歌浏览器为例。
首先按F12打开控制台,然后依次点击Network、Doc,之后刷新页面,就会出现如下面图展示的内容:
从内容中可以看到,网页的url为:
‘https://www.bilibili.com/ranking?spm_id_from=333.851.b_7072696d61727950616765546162.3’
接着下拉进度条,最后有一个user-agent,这便是headers需要的参数了。
user-agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36
在得到了url和headers后,便可以获取网页内容了,本文使用python的requests模块进行爬虫。代码如下:
import requests
url = r'https://www.bilibili.com/ranking?spm_id_from=333.851.b_7072696d61727950616765546162.3'
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36'}
data = []
response = requests.get(url,headers=headers)
if response.status_code == 200:
data = response.content.decode('utf-8')
else:
print('网页解析失败')
提取数据
在前面的步骤中,我们利用requests库的get函数成功获取网页数据,那么如何从网页书中提取我们想要的数据呢?这里介绍一下Beautiful Soup。Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库,它能够通过你喜欢的转换器实现惯用的文档导航、查找、修改文档的方式,Beautiful Soup会帮你节省数小时甚至数天的工作时间。更详细的内容可以查看Beautiful Soup的官方中文网址。
1、第一步我们先解析获取的网页数据,使用lxml格式
soup = BeautifulSoup(data,'lxml')
2、经过Beautiful Soup解析后的数据,和我们在网页上看到的网页源代码应该是一样的,在谷歌浏览器上右键有一个“查看网页原代码选项”,点击后会跳转后HTML格式的网页代码端。
3、获取“视频标题”、“视频综合得分”、“视频播放量”、“视频评论数”、“up主名字”等数据
这里以网页源代码中的一小段数据进行展示,数据如下:
'''
</div></div><!----></div></li><li data-id="414452358" data-rank="4" class="rank-item">
<div class="num">4</div><div class="content"><div class="img">
<a href="https://www.bilibili.com/video/BV1UV41127Pc" target="_blank">
<div class="lazy-img cover">
<img alt="靠谱盘点93:破防成功?LEC解说开团乌兹不行,不好意思,又是三比零的一年!" src="">
</div></a><div class="watch-later-trigger w-later"></div></div><div class="info">
<a href="https://www.bilibili.com/video/BV1UV41127Pc" target="_blank" class="title">
靠谱盘点93:破防成功?LEC解说开团乌兹不行,不好意思,又是三比零的一年!</a><!---->
<div class="detail"><span class="data-box"><i class="b-icon play"></i>194.9万</span>
<span class="data-box"><i class="b-icon view"></i>1.5万</span>
<a target="_blank" href="//space.bilibili.com/279991456"><span class="data-box">
<i class="b-icon author"></i>靠谱电竞</span></a></div><div class="pts"><div>1939047</div>综合得分
'''
(1) 获取视频标题
在上面的数据中,可以看到视频标题数据是存放在“title”这个class中,为此我们利用Beautiful Soup中的find()函数可以找到这个class,find_all()函数用于找到所有符合输入形式的数据。找到数据之后我们再用get_text()函数获取文本。需要注意的是find_all函数返回的是ResultSet格式的数据,我们需要对里面的每一个元素使用get_text()
video_names = []
namelist = soup.find_all(class_='title')
for name in namelist:
video_names.append(name.get_text('title'))
(2) 获取视频综合得分
和上面获取视频标题的方法类似,视频综合得分数据存放于“pts”这个class中,因此方法完全一致
video_scores = []
scorelist = soup.find_all(class_='pts')
for score in scorelist:
video_scores.append(score.get_text().replace('综合得分n','').strip())
(3) 获取视频播放量、评论数、up主名字
播放量、评论数、up主名字都是放在“data-box”这个class中,为了减少代码的冗余,这里放在一起一并处理。
video_play = []
video_comment = []
up_name = []
messages = soup.find_all(class_='data-box')
for i in range(0,len(messages),3):
video_play.append(messages[i].get_text())
video_comment.append(messages[i+1].get_text())
up_name.append(messages[i+2].get_text())
(4) 获取视频排名
视频排名无非是1到100的数字,这里无需使用上面的方法了。因为我们爬下来的数据已经是按照顺序排列规整的,所以我们直接构造排名列表即可。
rank = [i for i in range(1,101,1)]
(5) 获取视频BV
这部分的数据比较难获取,主要原因是B站上源码里出现了两次视频地址,如果按照前面的方法,会提取到两个同样的视频地址。这里便需要字符串去重的方法了,需要保留字符顺序的同时并且实现去重的功能,这里我使用了for循环的方法
mess=[]
video_id = []
for value in soup.find_all('a'):
mess.append(value.get('href'))
for i in range(len(mess)):
if type(mess[i]) != str:
pass
elif mess[i].startswith('https://www.bilibili.com/video/'):
video_id.append(mess[i].strip('https://www.bilibili.com/video/)'))
else:
pass
video_ids = []
for i in video_id:
if not i in video_ids:
video_ids.append(i)
整合并保存数据
经过上面的步骤,我们已经得到了所有需要的数据,接下来便是整合的过程,我们将得到的数据写成一个字典的形式。
import requests
from bs4 import BeautifulSoup
import pandas as pd
import datetime
def GetWeb(url=None, headers=None):
'''
此函数用于获取网页内容
input
url:网页的url
headers:网页请求头
retrun
soup:经过Beautiful Soup解析后的数据
'''
data = []
response = requests.get(url,headers=headers)
if response.status_code == 200:
data = response.content.decode('utf-8')
soup = BeautifulSoup(data,'lxml')
return soup
else:
print('网页解析失败')
return None
def GetMess(soup):
'''
此函数用来从网页中提取需要的数据
input
soup:Beautiful Soup解析的数据
return
videodata:字典形式的数据,里面包含:视频标题、视频综合得分、
视频播放量、视频评论数、up主名字、视频BV等数据
'''
video_names = [] # 视频标题
video_scores = [] # 视频综合得分
video_play = [] # 视频播放量
video_comment = [] # 视频评论数
up_name = [] # up主名字
mess=[] # 视频地址
video_id = [] # 视频BV
# 对视频标题的处理
namelist = soup.find_all('a',class_='title')
for name in namelist:
video_names.append(name.get_text('title'))
# 对视频综合得分数据的处理
scorelist = soup.find_all(class_='pts')
for score in scorelist:
video_scores.append(score.get_text().replace('综合得分n','').strip())
# 对视频播放量、评论数、up主名字的处理
messages = soup.find_all(class_='data-box')
for i in range(0,len(messages),3):
video_play.append(messages[i].get_text())
video_comment.append(messages[i+1].get_text())
up_name.append(messages[i+2].get_text())
# 对视频id的处理
for value in soup.find_all('a'):
mess.append(value.get('href'))
for i in range(len(mess)):
if type(mess[i]) != str:
pass
elif mess[i].startswith('https://www.bilibili.com/video/'):
video_id.append(mess[i].strip('https://www.bilibili.com/video/)'))
else:
pass
video_ids = []
for i in video_id:
if not i in video_ids:
video_ids.append(i)
# 视频排名
rank = [i for i in range(1,101,1)]
# 打包整理成一个字典
videodata = {'视频名字':video_names,
'播放量':video_play,
'评论数':video_comment,
'综合得分':video_scores,
'up主名字':up_name,
'视频BV':video_ids,
'排名':rank
}
return videodata
def SaveToExcel(videodata):
try:
VideoData = pd.DataFrame(videodata)
VideoData.to_excel('B站排名前100的视频汇总({0}).xls'.format(datetime.datetime.now().strftime('%Y-%m-%d')),index=False)
print('数据保存成功,请到文件“B站排名前100的视频汇总({0}).xls”中查看'.format(datetime.datetime.now().strftime('%Y-%m-%d')))
except:
print('数据写入失败')
def main():
url = r'https://www.bilibili.com/ranking?spm_id_from=333.851.b_7072696d61727950616765546162.3'
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36'
}
soup = GetWeb(url=url, headers=headers)
videodata = GetMess(soup)
SaveToExcel(videodata)
if __name__ == '__main__':
main()
运行结果