嘘~ 正在从服务器偷取页面 . . .

工欲善其事,必先利其器——线程池的使用(2)


好吧,我们前面爬取图片发现使用了线程池后,其实我们的效率提高不是这么明显。那我们就来试一试爬取视频吧。因为不同的网站对视频的反爬的策略都不尽相同,所以我们这里讲的示例并没有普世的意义。唯一普世的做法是好好分析视频网址的存放地址。

需求

首先来讲一讲我们这次爬取的视频。

我们这次爬取的视频是梨视频娱乐模块最热的视频

即图片里的前三个(但我们打开抓包工具时,又发现其实是 4 个视频,不管是几个,关系都不大)

分析

首先我们先随便定位一个视频,得到如下的网页源码


我们发现这里的 a 标签下面有一个超链接,然后我们点击这个超链接,跳转网页,来到了视频播放页。注意这个超链接的内容,后面要用到。

接着我们再一次试图定位时,却发现我们找不到 .mp4 的网页。怎么办呢?


没事,我们可以试着播放视频再进行定位。下面就是见证奇迹的时候了。

当然,以我们目前所学是拿不到在这个动态加载的数据的,但这个步骤不是毫无用处的,我们要记住这串网址。

https://video.pearvideo.com/mp4/third/20210508/cont-1728888-11721137-174842-hd.mp4

因为是动态加载的数据,我们可以到 XHR 里面去找网址会不会在这里面。


我们一看,果然在!

不过先别太激动,我们把阿贾克斯加载的网址复制下来,就又发现问题了。

https://video.pearvideo.com/mp4/third/20210508/1620721592006-11721137-174842-hd.mp4

我们两相对比后,发现相差的部分是:“ cont-1728888 ”。那么 count 后面的数字是从什么地方来的呢?

还记得我们一开始爬取的超链接吗?

video_1728888。这里的数字不就是我们要的吗?

欧克,分析了之后,我们还要阿贾克斯加载的参数。


我们发现其中的 contld 是已知的,那么剩下的 mrd 是什么呢?

很简单,什么都不是,只是一串随机数

到这里,我们就完成了对爬取梨视频的分析,剩下的就是代码的问题了。

同步爬虫爬取梨视频

import requests
from lxml import etree
import os
import time
import random
import re

def save_video(videoNum_title):
    video_num = videoNum_title[0]
    title = videoNum_title[1]

    # UA伪装
    header = {
        "user-agnet": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36",
        "Referer": "https://www.pearvideo.com/" + "video_" + video_num
    }

    # 指定url
    url = "https://www.pearvideo.com/videoStatus.jsp"

    # 传入参数
    param = {
        "contId": video_num,
        "mrd": str(random.random())
    }

    # 获取假网址
    json = requests.get(url = url, headers = header, params = param).json()
    href = json["videoInfo"]["videos"]["srcUrl"]

    # 获取真正的网址
    url = re.sub(r"/.{13}-", "/cont-" + video_num + "-", href)

    # 保存视频
    header = {
        "user-agnet": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36"
    }
    video = requests.get(url = url, headers =header).content

    if not os.path.exists("C:\\Users\\ASUS\\Desktop\\CSDN\\高性能异步爬虫\\线程池\\同步爬取梨视频\\" + title + ".mp4"):
        with open("C:\\Users\\ASUS\\Desktop\\CSDN\\高性能异步爬虫\\线程池\\同步爬取梨视频\\" + title + ".mp4", "wb") as fp:
            print(title, "正在下载……")
            fp.write(video)
            print(title, "下载完成!!!")

if __name__ == '__main__':
    start = time.time()

    # 创建文件夹
    if not os.path.exists("C:\\Users\\ASUS\\Desktop\\CSDN\\高性能异步爬虫\\线程池\\同步爬取梨视频"):
        os.mkdir("C:\\Users\\ASUS\\Desktop\\CSDN\\高性能异步爬虫\\线程池\\同步爬取梨视频")

    # UA伪装
    header = {
        "user-agnet": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36"
    }

    # 指定 url
    url = "https://www.pearvideo.com/category_4"

    # 发送请求
    page = requests.get(url = url, headers = header).text

    # xpath 解析
    tree = etree.HTML(page)
    li_list = tree.xpath('//*[@id="listvideoListUl"]/li') # li 标签列表
    List = []
    for li in li_list:
        title = li.xpath('div//div[@class="vervideo-title"]/text()')[0].split(" ")[-1]
        video_num = li.xpath('div/a/@href')[0][6:]
        List.append((video_num, title))

    for videoNum_title in List:
        save_video(videoNum_title)

    end = time.time()
    print(end - start)

    print("over!!!")


同步用时 45 秒,现在让我们试试异步

异步爬虫爬取梨视频

import requests
from lxml import etree
import os
import time
import random
import re
from multiprocessing import Pool

def save_video(videoNum_title):
    video_num = videoNum_title[0]
    title = videoNum_title[1]

    # UA伪装
    header = {
        "user-agnet": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36",
        "Referer": "https://www.pearvideo.com/" + "video_" + video_num
    }

    # 指定url
    url = "https://www.pearvideo.com/videoStatus.jsp"

    # 传入参数
    param = {
        "contId": video_num,
        "mrd": str(random.random())
    }

    # 获取假网址
    json = requests.get(url = url, headers = header, params = param).json()
    href = json["videoInfo"]["videos"]["srcUrl"]

    # 获取真正的网址
    url = re.sub(r"/.{13}-", "/cont-" + video_num + "-", href)

    # 保存视频
    header = {
        "user-agnet": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36"
    }
    video = requests.get(url = url, headers =header).content

    if not os.path.exists("C:\\Users\\ASUS\\Desktop\\CSDN\\高性能异步爬虫\\线程池\\异步爬取梨视频\\" + title + ".mp4"):
        with open("C:\\Users\\ASUS\\Desktop\\CSDN\\高性能异步爬虫\\线程池\\异步爬取梨视频\\" + title + ".mp4", "wb") as fp:
            print(title, "正在下载……")
            fp.write(video)
            print(title, "下载完成!!!")

if __name__ == '__main__':
    start = time.time()

    # 创建文件夹
    if not os.path.exists("C:\\Users\\ASUS\\Desktop\\CSDN\\高性能异步爬虫\\线程池\\异步爬取梨视频"):
        os.mkdir("C:\\Users\\ASUS\\Desktop\\CSDN\\高性能异步爬虫\\线程池\\异步爬取梨视频")

    # UA伪装
    header = {
        "user-agnet": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36"
    }

    # 指定 url
    url = "https://www.pearvideo.com/category_4"

    # 发送请求
    page = requests.get(url = url, headers = header).text

    # xpath 解析
    tree = etree.HTML(page)
    li_list = tree.xpath('//*[@id="listvideoListUl"]/li') # li 标签列表
    List = []
    for li in li_list:
        title = li.xpath('div//div[@class="vervideo-title"]/text()')[0].split(" ")[-1]
        video_num = li.xpath('div/a/@href')[0][6:]
        List.append((video_num, title))

    # 使用线程池
    pool = Pool()
    pool.map(save_video, List)
    pool.close()
    pool.join()

    end = time.time()
    print(end - start)

    print("over!!!")

文章作者: New Ass
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 New Ass !
  目录