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条数据。。。。。。

(0)

相关推荐