Python爬虫进阶:爬取梨视频网站Top排行榜视频数据
本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理
以下文章来源于青灯编程 ,作者:清风
Python爬虫进阶:反反爬实战案例—爬取梨视频,观看地址:
https://www.bilibili.com/video/BV1mK4y1E75Y/
前言
关于梨视频的爬取,网站上面还是有很多教程文章的,但是之前的那些教程文章统统都不能实现了,因为梨视频网站早就更新了。之前也有很多小伙伴也在问关于该网站的爬取方法。
基本开发环境
- Python 3.6
- Pycharm
相关模块的使用
import requests import re import threading
目标网页分析
单个视频地址获取
点击进入第一个视频的详情页,使用开发者工具可以找到相关的视频地址。
https://video.pearvideo.com/mp4/adshort/20201221/1608712845841-15540331_adpkg-ad_hd.mp4
链接中的 contId 对应的就是视频的ID
def get_video_url(video_id):
data_url = 'https://www.pearvideo.com/videoStatus.jsp?contId={}&mrd=0.5606814943122209'.format(video_id)
headers_1 = {
'Referer': 'https://www.pearvideo.com/video_{}'.format(video_id),
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36'
}
response = requests.get(url=data_url, headers=headers_1)
html_data = response.json()
video_url = html_data['videoInfo']['videos']['srcUrl']
suffix = video_url.split('-')[1]
date = video_url.split('/')[-2]
new_url = 'https://video.pearvideo.com/mp4/adshort/{}/cont-{}-{}-ad_hd.mp4'.format(date, video_id, suffix)
return new_url
注意点:
1、headers 请求头一定要添加 Referer 防盗链 , 不然获取不到数据 。
2、这里获取的视频url地址,并非真实的url地址,复制链接会发现是404
# 数据接口获取的视频地址
'''
https://video.pearvideo.com/mp4/adshort/20201222/1608723660585-15542059_adpkg-ad_hd.mp4
'''
# 真实的视频播放地址
'''
https://video.pearvideo.com/mp4/adshort/20201222/cont-1712976-15542059_adpkg-ad_hd.mp4
'''
所以需要拼接一下url
获取视频ID
根据数据接口url 可知,只要获取每个视频的ID值,就可以爬取所有的视频了。
这就需要在排行榜列表中查找了。
如上图所示,视频排行榜页面有我们需要的视频ID值,但是这只有一个10个视频地址呀,需要网页往下滑动才可以查看更多的内容。所以老办法,先清空开发者工具里面的数据,然后下滑网页。
于是乎就出现了很多的相关数据。经过分析对比。
可以发现其中是有两个参数发现改变的:
start:等差数列,每次增加10
sort:9、14、21、29、38、46、54、62、69、74 每次变化没有规律
那这样我只能让不规律的哪个参数保持不变,给一个恒定值9,然后根据start的参数给改变,看是否能够获取数据,咱们就以不变应万变。
当URL中 start=0 时
可以看出,最后一个视频是<2020回声:50段现场声音回顾这一年> ,在排行榜当中应该是属于 第9个的位置,但是这里的序号是18.
当URL中 sort=10 时
第一个视频是<被害者家属谈劳荣枝案首日庭审> ,在排行榜当中应该是属于 第10个的位置,刚好是接着上面的视频往下排的。。
当URL中 sort=20 时
同样的是接着排下来的。
所以只需要改变 sort 这个参数即可获取排行榜所有的视频ID以及视频标题。
def get_video_id(page_url):
html_data = get_response(page_url).text
video_ids = re.findall('<a href="video_(\d+)" class="actplay">', html_data)
title = re.findall('<h2 class="popularem-title">(.*?)</h2>', html_data)
video_info = zip(video_ids, title)
for i in video_info:
video_title = i[1]
video_id = i[0]
保存数据
def save(video_url, video_title):
video_content = get_response(video_url).content
filename = 'video\\' + video_title + '.mp4'
with open(filename, mode='wb') as f:
f.write(video_content)
print('正在保存:', video_title)
当保存的时候出现了报错。
因为标题中出现特殊字符,没有办法保存。
之前有说过,当你新建文件的时候,文件命名中出现特殊字符是没有办法命名创建的,所以需要使用正则表达式,替换掉标题中的特殊字符。
def change_title(title):
pattern = re.compile(r"[\/\\\:\*\?\"\<\>\|]") # '/ \ : * ? " < > |'
new_title = re.sub(pattern, "_", title) # 替换为下划线
return new_title
完整实现代码
import requests
import re
import threading
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36'
}
def get_response(html_url):
response = requests.get(url=html_url, headers=headers)
return response
def change_title(title):
pattern = re.compile(r"[\/\\\:\*\?\"\<\>\|]") # '/ \ : * ? " < > |'
new_title = re.sub(pattern, "_", title) # 替换为下划线
return new_title
def save(video_url, video_title):
video_content = get_response(video_url).content
filename = 'video\\' + video_title + '.mp4'
with open(filename, mode='wb') as f:
f.write(video_content)
print('正在保存:', video_title)
print(video_url)
def get_video_url(video_id):
data_url = 'https://www.pearvideo.com/videoStatus.jsp?contId={}&mrd=0.5606814943122209'.format(video_id)
headers_1 = {
'Referer': 'https://www.pearvideo.com/video_{}'.format(video_id),
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36'
}
response = requests.get(url=data_url, headers=headers_1)
html_data = response.json()
video_url = html_data['videoInfo']['videos']['srcUrl']
suffix = video_url.split('-')[1]
date = video_url.split('/')[-2]
new_url = 'https://video.pearvideo.com/mp4/adshort/{}/cont-{}-{}-ad_hd.mp4'.format(date, video_id, suffix)
return new_url
def main(page_url):
html_data = get_response(page_url).text
video_ids = re.findall('<a href="video_(\d+)" class="actplay">', html_data)
title = re.findall('<h2 class="popularem-title">(.*?)</h2>', html_data)
video_info = zip(video_ids, title)
for i in video_info:
video_title = i[1]
video_id = i[0]
video_url = get_video_url(video_id)
new_title = change_title(video_title)
save(video_url, new_title)
if __name__ == '__main__':
for page in range(0, 101, 10):
url = 'https://www.pearvideo.com/popular_loading.jsp?reqType=1&categoryId=&start={}&sort=9&mrd=0.9278261602425337'.format(page)
main_thread = threading.Thread(target=main, args=(url,))
main_thread.start()
排行榜一共是74条数据。。。。。。