追求一个人不能全靠【感动】。
准时早安晚安,风雨无阻地送三餐,并不会让对方喜欢上你,甚至有可能会厌恶你。
更加正确的做法是提升自己,让对方感受到你的【魅力】和【踏实】。
一个女人能爱上你,是爱你的人,而不是你的跪舔。
懂得嘘寒问暖,却毫无追求,认不清现实。
每天想着各种拌饭讨好她,虽然会让她开心,但并不会让她产生喜欢,更别谈爱上你。
这种男人并不会真正给对方带来【安全感】,即使对方说了【我爱你】,也不会太长久,舔到最后只会是一场空。
获取B站视频信息
今天为大家带来的实战项目是获取B站的视频信息数据。B站的视频信息数据主要有哪些呢?
- 视频点赞数。
- 视频投币数
- 视频收藏数
- 视频弹幕数
- 视频播放时长
- 视频发布时间
上面所说的几点内容就是视频的主要信息数据,我们的目的就是要将这些数据获取下来,并将数据保存到数据库中。
目标网页分析
我们爬取的数据是来自《观察者网》的所有视频的数据。
对于B站的每一个视频来说每一个视频都有一个AV号。
例如,我们点击第一个视频,在里面我们就可以看到视频的各个数据了,比如说:点赞数、投币数、收藏数、弹幕数、视频播放时长、视频发布时间。
看到了吗?视频的主要数据刚刚好是在网页中呈现出来的。
为了确保数据的准确与无误,我们需要点击Network,查看Response,看看里面是不是同样也包含此类数据,如果包含相同数据的话,说明数据确实包含在网页中,而不是通过js或者是Ajax异步加载出来的,当然我更希望是通过这两个手段去渲染数据,我也容易一点。
如上图所示,数据的确包含在网页中,也就是说可以通过Python正常的进行模拟访问并获取到我们想要的数据。
分析到这里,我就先把本次爬取的代码框架先写出来吧
# 获取网页信息
def get_html(url):
pass
# 解析数据
def parse_html(html):
pass
# 保存数据
def save_data(data):
pass
获取网页信息
接下来就是将网页中我们需要的数据提取出来,这里我选择使用xpath来提取数据。
相对来说xpath比较简单,具体代码如下所示:
def parse_html(html):
html = etree.HTML(html)
title = html.xpath('//span[contains(@class, "tit")]/text()')[0]
danmu = int(re.findall('\d+', html.xpath('//span[@class="dm"]/text()')[0])[0])
times = html.xpath('//div[@class="video-data"]/span[3]/text()')[0]
like = int(re.findall('\d+', html.xpath('//div[@class="ops"]/span[@class="like"]/@title')[0])[0])
coin =int(re.findall('\d+', html.xpath('//div[@class="ops"]/span[2]/@title')[0])[0])
collect = int(re.findall('\d+', html.xpath('//div[@class="ops"]/span[@class="collect"]/@title')[0])[0])
return title, danmu, times, like, coin, collect
我对上面的代码做简单的说明:
title代表的是视频的标题;
danmu代表的是视频的弹幕数;
times代表的是视频发布时间;
like代表的是是点赞数;
coin代表的是投币数;
collect代表的是收藏数。
相信xpath语法不需要我再做任何的解释了吧。
认真阅读本文的小伙伴一定可以发现这边获取的数据还差一个,那就是视频时长。经过我的仔细查找之后也没有在响应中找到视频的播放时长,说实话,我当时瞬间懵了。
于是我返回上一级链接,
并将页面刷新,我很幸运,终于被我给找着了。
在一个页面中一共有30个视频,视频的标题、ID号、播放时长都在这面了。从上图可以很明显的看出,数据是通过Ajax异步加载出来的json数据。
获取所有视频的链接与时间
通过对上面的分析,我已经有了大体的思路了。三十个视频的ID号都在这里了,这个是第一页视频的所有信息,首先我必须知道它所给的API在不同的页面会有什么变化。
# 第一页
https://api.bilibili.com/x/space/arc/search?mid=10330740&ps=30&tid=0&pn=1&keyword=&order=pubdate&jsonp=jsonp
# 第二页
https://api.bilibili.com/x/space/arc/search?mid=10330740&ps=30&tid=0&pn=2&keyword=&order=pubdate&jsonp=jsonp
# 第三页
https://api.bilibili.com/x/space/arc/search?mid=10330740&ps=30&tid=0&pn=3&keyword=&order=pubdate&jsonp=jsonp
变化的参数就是pn,随着页面的变化而变化。
因此,我在这里定义了两个方法,分别获取视频的链接与视频的播放时长。
具体代码如下:
# 获取1-10页的视频链接
def get_url():
urls = []
# times = []
for page in range(1, 10):
api_url = f'https://api.bilibili.com/x/space/arc/search?mid=10330740&ps=30&tid=0&pn={page}&keyword=&order=pubdate&jsonp=jsonp'
data = requests.get(api_url, headers=headers).json()
bvids = jsonpath.jsonpath(data, '$.data..vlist..bvid')
time.sleep(0.5)
url = ['https://www.bilibili.com/video/'+bvid for bvid in bvids]
urls.extend(url)
return urls
# 获取1-10页的视频播放时长
def get_length():
times = []
for page in range(1, 10):
api_url = f'https://api.bilibili.com/x/space/arc/search?mid=10330740&ps=30&tid=0&pn={page}&keyword=&order=pubdate&jsonp=jsonp'
data = requests.get(api_url, headers=headers).json()
length = jsonpath.jsonpath(data, '$.data..vlist..length')
times.extend(length)
time.sleep(0.5)
return times
修改获取网页信息代码
现在我是已经成功拿到视频的播放时长了,为了方便存储,因此,需要将在获取网页信息代码中来调用获取视频播放时长的方法即可。修改之后的代码如下:
def parse_html(html):
global pages
lengths = get_length()
html = etree.HTML(html)
title = html.xpath('//span[contains(@class, "tit")]/text()')[0]
danmu = int(re.findall('\d+', html.xpath('//span[@class="dm"]/text()')[0])[0])
times = html.xpath('//div[@class="video-data"]/span[3]/text()')[0]
like = int(re.findall('\d+', html.xpath('//div[@class="ops"]/span[@class="like"]/@title')[0])[0])
coin =int(re.findall('\d+', html.xpath('//div[@class="ops"]/span[2]/@title')[0])[0])
collect = int(re.findall('\d+', html.xpath('//div[@class="ops"]/span[@class="collect"]/@title')[0])[0])
return title, danmu, times, like, coin, collect, lengths[pages]
因为,获取的播放时长,是放在一个列表中,因此,我在定义了一个全局变量:pages,当我调用完save_data()方法之后使pages加1即可。
这个pages其实表示的是每个视频的播放时长。
保存数据
本次保存的数据是放在MySQL数据库中,具体代码如下所示:
def save_data(data):
host = 'localhost'
user = 'root'
password = '密码'
port = 3306
db = pymysql.connect(host=host, user=user, password=password, port=port, db='bilibli')
cursor = db.cursor()
sql = 'insert into data3(title, danmu, vediotime, likecount, coin, collect, vediolength) values (%s, %s, %s, %s, %s, %s, %s)'
print(data)
try:
cursor.execute(sql, data)
db.commit()
print('插入成功')
except Exception as e:
print(e)
db.rollback()
print('插入失败')
注意在此之前必须要先创建好数据库bilibli和数据表data3,然后再调用上面的方法,将数据保存至数据库中。
本篇文章只做简单的爬虫知识,不做数据分析。
以本文为例,各位小伙伴们可以去爬取你们喜欢的UP主的视频详细数据,可以多爬取一个数据,比如说播放量,做B站视频Top100的数据分析,来巩固自己的爬虫知识和技巧,顺便再学习了简单的数据可视化知识。
最后
别人的建议只是参考答案,人生没有标准答案。
你不需要去抄别人,逼自己和别人一模一样,写你觉得对的答案就好。
看完文章,觉得对你有帮助的,可以给啃书君点个【在看】,我会继续努力,和你们一起成长前进。
文章的每一个字都是我用心敲出来的,只希望对得起每一位关注我的人。
点个【在看】,让我知道你们也在为人生【拼尽全力】。
我是啃书君,一个专注于学习的人,你懂的越多,你不懂的越多。更多精彩内容,我们下期再见!
respect