美文网首页
春暖花开,我见六间房

春暖花开,我见六间房

作者: 自成背后之隐士 | 来源:发表于2022-03-15 12:52 被阅读0次

1. 花开正好,我们也要充满希望

又是一年春暖花开的时候,

image.png

山河温暖,

image.png

万物可爱,


image.png

一切都是那么的生机勃勃,而我们也到了我们该努力勃发的时候了。
今天还谈学习技术,
为避免单调,咱们这里以本地下载保存一个App漂亮小姐姐的视频为例。

接下来咱们进入正题,又到了愉快地学技术的时候啦。

2. 准备环境

工欲善其事必先利其器,我们需要的环境有:fiddler抓包工具、手机模拟器或手机、六间房秀场App,python环境。

这里提一下,六间房秀场App历史版本下载安装,可以本地去豌豆荚网站下载六间房秀场APP的历史版本,地址:https://www.wandoujia.com/apps/7450760/history

打开往下拉,尽量选择较低版本,我下的版本是v7.1.5.0713的,注意下的时候取消勾选优先下载豌豆荚安装,点普通下载就行了。

下载之后直接拖到手机模拟器里点击安装就🆗了。

3. 开始分析

打开fiddler监控请求,并打开六间房秀场App,点开小视频开始查看fiddler:


image.png

成功找到数据包,把url复制粘贴一下,看看

https://v.6.cn/coop/mobile/index.php?act=recommend&padapi=minivideo-getlist.php&page=1

看着url,估计翻页只需要变一下page就行了。

模拟器里视频再往下翻翻看,验证一下猜想,
先清理一下fiddler会话,再往下翻视频:


image.png

把url复制粘贴一下,再看看:

https://v.6.cn/coop/mobile/index.php?act=recommend&padapi=minivideo-getlist.php&page=2

两个放一块对比:

https://v.6.cn/coop/mobile/index.php?act=recommend&padapi=minivideo-getlist.php&page=1
https://v.6.cn/coop/mobile/index.php?act=recommend&padapi=minivideo-getlist.php&page=2

可以看到就page变了,每次翻页加1,证明我们的猜想正确,接下来我们就尝试写代码发请求了。

4. 初次测试

先用requests测试一下看看能不能用:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : 冰履踏青云
# @File    : 01.py
import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning


#关闭安全请求警告
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
urls = 'https://v.6.cn/coop/mobile/index.php?act=recommend&padapi=minivideo-getlist.php&page=1'
headers = {
    'User-Agent': 'Xc27CgIxEEbhJ3L5ZyaZXDorG8FCEKyWJDvRFdZOsMjDq62c4ivPe321e3netvJYy3w9z35Kk46oAnWClMK3NC6nw25)JAwGMw)5CSgTBa)Ou8hMi4XqakiCYh1dG2MxKm0RAyGKt27OOtXqR8zIHLLWXChr)P99AA@@'
}

response = requests.get(urls, headers=headers, verify=False).json()
print(response)

结果:


image.png

成功返回json数据包,接下来我们用jsonpath直接提取视频标题和播放地址:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : 冰履踏青云
# @File    : 01.py


import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
import jsonpath



#关闭安全请求警告
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
urls = 'https://v.6.cn/coop/mobile/index.php?act=recommend&padapi=minivideo-getlist.php&page=1'
headers = {
    'User-Agent': 'Xc27CgIxEEbhJ3L5ZyaZXDorG8FCEKyWJDvRFdZOsMjDq62c4ivPe321e3netvJYy3w9z35Kk46oAnWClMK3NC6nw25)JAwGMw)5CSgTBa)Ou8hMi4XqakiCYh1dG2MxKm0RAyGKt27OOtXqR8zIHLLWXChr)P99AA@@'
}

response = requests.get(urls, headers=headers, verify=False).json()
# print(response)
title_list = jsonpath.jsonpath(response,'$..title')
playurl_list = jsonpath.jsonpath(response,'$..playurl')

print(title_list,len(title_list))
print(playurl_list,len(playurl_list))

image.png

一页视频标题和播放地址都是20个,没啥问题。接下来我们就只需要给播放地址playurl发请求保存视频就🆗了。

5. 第一版 ——requests版本

我们还是先对上面的程序稍微改造一下使其更具有可读性再保存,先下3页看看效果:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : 冰履踏青云
# @File    : 02.py


import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
import jsonpath
import os
import time


#关闭安全请求警告
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

def get_url(url,headers):
    '''获取视频标题和播放地址'''
    response = requests.get(url, headers=headers, verify=False).json()
    # print(response)
    title_list = jsonpath.jsonpath(response,'$..title')
    playurl_list = jsonpath.jsonpath(response,'$..playurl')

    # print(title_list,len(title_list))
    # print(playurl_list,len(playurl_list))
    return (title_list,playurl_list)


def save_videos(url):
    '''保存视频'''
    res = get_url(url, headers)
    # print(res)
    print(res[0])
    for i in range(len(res[0])):
        content = requests.get(res[1][i],headers=headers).content
        path = './Video/'
        if not os.path.exists(path):
            os.makedirs(path)
        title = res[0][i].replace('/','_') # 有的标题带表情的是这样的:我们意念合一/大笑/  “/”会影响文件存储,用_替换掉
        with open(path + title + '.mp4', 'ab') as f:
            f.write(content)
        print(title + '.mp4' + '已经下载完成!')


if __name__ == '__main__':
    url = 'https://v.6.cn/coop/mobile/index.php?act=recommend&padapi=minivideo-getlist.php&page={}'

    headers = {
        'User-Agent': 'Xc27CgIxEEbhJ3L5ZyaZXDorG8FCEKyWJDvRFdZOsMjDq62c4ivPe321e3netvJYy3w9z35Kk46oAnWClMK3NC6nw25)JAwGMw)5CSgTBa)Ou8hMi4XqakiCYh1dG2MxKm0RAyGKt27OOtXqR8zIHLLWXChr)P99AA@@'
    }
    start_time = time.time()
    # save_videos()
    for i in range(1,4):
        save_videos(url.format(str(i)))

    end_time = time.time()
    print('全部下载完成,用时:%s'%(end_time-start_time))


运行结果:


image.png

看一下视频文件:

image.png

具体里面的内容我就不展示了,其实就是正常的小姐姐小视频而已,
三页,一页20个视频,总共60个视频也是没问题的。

唯一有点不美的是用了114秒,用的时间看着有点长,下面我们改进一下。

6. 第二版——requests版升级

我们这里为了少改动代码,直接用ThreadPoolExecutor ,代码示例:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : 冰履踏青云
# @File    : 02.py

import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
import jsonpath
import os
import time
from concurrent.futures import ThreadPoolExecutor



#关闭安全请求警告
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

def get_url(url,headers):
    '''获取视频标题和播放地址'''
    response = requests.get(url, headers=headers, verify=False).json()
    # print(response)
    title_list = jsonpath.jsonpath(response,'$..title')
    playurl_list = jsonpath.jsonpath(response,'$..playurl')

    # print(title_list,len(title_list))
    # print(playurl_list,len(playurl_list))
    return (title_list,playurl_list)

    # for i in range(len(title_list)):



def save_videos(url):
    '''保存视频'''
    res = get_url(url, headers)
    # print(res)
    # print(res[0])
    for i in range(len(res[0])):
        content = requests.get(res[1][i],headers=headers).content
        path = './Video/'
        if not os.path.exists(path):
            os.makedirs(path)
        title = res[0][i].replace('/','_') # 有的标题带表情的是这样的:我们意念合一/大笑/  用_替换掉
        with open(path + title + '.mp4', 'ab') as f:
            f.write(content)
        print(title + '.mp4' + '已经下载完成!')


if __name__ == '__main__':
    url0 = 'https://v.6.cn/coop/mobile/index.php?act=recommend&padapi=minivideo-getlist.php&page={}'

    headers = {
        'User-Agent': 'Xc27CgIxEEbhJ3L5ZyaZXDorG8FCEKyWJDvRFdZOsMjDq62c4ivPe321e3netvJYy3w9z35Kk46oAnWClMK3NC6nw25)JAwGMw)5CSgTBa)Ou8hMi4XqakiCYh1dG2MxKm0RAyGKt27OOtXqR8zIHLLWXChr)P99AA@@'
    }
    start_time = time.time()
    with ThreadPoolExecutor(3) as t:
        for i in range(1,4):
            url = url0.format(i)
            t.submit(save_videos,url)
    end_time = time.time()
    print('全部下载完成,共用时:%s'%(end_time-start_time))


image.png

稍微好了一些,在翻页数比较少的情况下requests开线程池效率提升并不是很明显(我嫌耗时太长,没有设置很大的页数对比),我们试着再优化一下,再换一种方案。

7. 第三版 ——异步版

接下来我们不用requests了,用支持异步的asyncio,aiohttp开整:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : 冰履踏青云
# @File    : 3.py
import os
import time

import requests
import aiohttp
import asyncio
import jsonpath
import aiofiles
from requests.packages.urllib3.exceptions import InsecureRequestWarning

#关闭安全请求警告
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

# 先用requests把前三页视频地址拿到,也可以用async 
# 我这边懒省事儿,直接复制粘贴,反正就三个请求对时间影响不大,主要耗时的是视频流的下载
def get_url():
    '''获取视频标题和播放地址'''
    url = 'https://v.6.cn/coop/mobile/index.php?act=recommend&padapi=minivideo-getlist.php&page={}'
    ls = []
    title_lists = []
    playurl_lists = []

    for i in range(1,4):
        response = requests.get(url.format(str(i)), headers=headers, verify=False).json()
        # print(response)
        title_list = jsonpath.jsonpath(response,'$..title')
        playurl_list = jsonpath.jsonpath(response,'$..playurl')
        title_lists.extend(title_list) # 在原基础上扩展列表
        playurl_lists.extend(playurl_list)
    # print(len(title_lists),len(playurl_lists))
    return (title_lists,playurl_lists)

async def save_video(title,url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url,headers=headers) as resp:
            async with aiofiles.open(f"Video/{title.replace('/','_')+'.mp4'}", mode="wb") as f:
                await f.write(await resp.content.read())  # 把下载到的内容写入到文件中
        print(f"{title.replace('/','_')+'.mp4'}下载完毕")


if __name__ == '__main__':
    headers = {
        'User-Agent': 'Xc27CgIxEEbhJ3L5ZyaZXDorG8FCEKyWJDvRFdZOsMjDq62c4ivPe321e3netvJYy3w9z35Kk46oAnWClMK3NC6nw25)JAwGMw)5CSgTBa)Ou8hMi4XqakiCYh1dG2MxKm0RAyGKt27OOtXqR8zIHLLWXChr)P99AA@@'
    }

    start = time.time()
    path = './Video/'
    if not os.path.exists(path):
        os.makedirs(path)
    res = get_url()
    tasks = []
    for i in range(len(res[0])):
        title = res[0][i]
        url = res[1][i]
        c = save_video(title,url)
        task = asyncio.ensure_future(c)
        tasks.append(task)
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait(tasks))
    end = time.time()
    print('全部下载完成,总用时:%s'%(end-start))



运行结果:


image.png

好了一些,二三百兆的资源下83秒应该是正常的,像这种可能就是受限于网速吧。

本来还想再写个scrapy版本的,仔细想想也没必要,感兴趣的朋友可以自己写一下看看,这里我主要提两个需要注意的点:

  1. 第一点就是scrapy保存文件的逻辑可以在管道端写,不想写管道的也可以直接在主爬虫程序里面(不过这样感觉这个框架也是没咋利用好,不提倡哈)。
  2. 第二点就是要注意scrapy响应接收视频字节流用response.body,相当于requests的response.content和异步的response.content.read()。

其他的应该没啥需要注意的了,如果你写了遇到了问题欢迎来砸我,我最喜欢炒bug吃,嘎嘣脆,还是鸡肉味,咳咳咳。

贫瘠的荒漠会开满鲜花,尽头的街角,也会有人等你回家

本文改动了好多,试了稍微改一丢丢文章就审核不通过了,真难呀。

文章到此结束,欢迎三连,点个赞,收个藏啥的,有问题的尽管砸来,我有故事你有酒,好好交流不分手!哈哈哈!下次见!

相关文章

  • 春暖花开,我见六间房

    1. 花开正好,我们也要充满希望 又是一年春暖花开的时候, 山河温暖, 万物可爱, 一切都是那么的生机勃勃,而我们...

  • 宝安西乡带花园社区,滨海时代花园海景房

    大海,春暖花开 宝安西乡带花园社区,《滨海时代花园》海景房 户型品鉴: 一房一厅 两房(1+1) 三房(2+1) ...

  • 2020-04-04

    疫情期间我整整胖了10斤。 趁着疫情好转,春暖花开,4月7号健身房终于开业了,我必须要去健身房让自己回到以前的样子...

  • 罩见(照见)春暖花开

    文.图/英歌h 有一种相思 不必相见 有一种相守 无须相伴 有一种叹惋 情深缘浅 有一种爱恋 浴火涅磐 罩得住容颜...

  • 悦见书香 春暖花开

    一本好书, 一杯清茗, 一缕春风, 一位知...

  • 春暖花开,见想见的人

    今天中午,一个9年前的家长,好久没来厚街,说想见见我们,被想念是幸福 难得周日的下午休息,早早回来带诚去玩 看着诚...

  • 燕飞醉为谁

    寒冬将至燕南飞,春暖花开始见回。 好友举杯共一醉,酒后方知我为谁。

  • 病 房 见 闻

    在经济飞速发展的今天,人们拥有着优渥物质的生活同时,正在不断地追求精神文明。而精神文明的重要一环,离不开遵守规则、...

  • 三行诗•海子三十年祭

    你一句:面朝大海,春暖花开, 搅动了多少情怀? 更节省了海景房的广告牌! 面朝大海,春暖花开 作者。海子 从明天起...

  • 家之记忆土坯房

    青石墙脚土坯墙,红瓦盖帽土坯房。八一年我出生,李庄老家的土坯房建成,与我同龄的土坯房承载了我二十余年的人生记忆,见...

网友评论

      本文标题:春暖花开,我见六间房

      本文链接:https://www.haomeiwen.com/subject/vbqydrtx.html