起因
测试视频播放器的时候需要用到一些视频(其实是很多)来看看长时间的播放会不会导致播放器崩溃,可是单一的文件多次播放还是会有一点点的偶然性,所以就需要一系列的视频来播放。这个时候我想到了新闻联播,一年365天不休息,而且播了这么多年,数据肯定多,所以就去下载一些新闻联播的视频好了。
开始下载
下载视频,我首先想到了you-get这个软件,只要输入视频的网页路径就可以下载网页上面的视频。所以我手动下载了最近几天的新闻, 可以下载没有问题,而且可以跑满带宽。
You-Get
进阶
如果就需要几天的视频,一个网址一个网址地复制粘贴还可以,关键需要的数量太多,不可能手动完成,所以就需要写一个爬虫程序来获取视频了。
首先分析一下需求:
下载视频的时候 you-get 基本可以跑满带宽,所以不需要多线程加速
需要一个ip代理池,防止下着下着我的ip就被封了
要自动获取每天视频的网页地址
接下来就一步一步实现。
获取新闻联播的网页地址
打开浏览器,输入新闻联播的网址 http://tv.cctv.com/lm/xwlb/ 。然后按下F12,切换到网络选项卡,点击不同日期的新闻就可以看到页面的网络请求,第一个请求的是一个shtml的网页文件,这个就是节目列表了,如下图
点开节目列表的内容看一下是不是和网页上面的新闻标题一致,看起来都是一致的。点开标题对应的链接就转向了视频的页面,那么每个标题对应的链接就是视频的网页地址了。
使用you-get测试一下上面的地址,没有问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 (base) ➜ ~ you-get -i https://tv.cctv.com/2021/12/10/VIDERjGehdKgKOaBZPRTJvko211210.shtml site: CNTV.com title: [视频]国际联播快讯 streams: [ DEFAULT ] _________________________________ - format: 1 container: mp4 video-profile: 1280x720_2000kb/s - format: 2 container: mp4 video-profile: 1280x720_1200kb/s - format: 3 container: mp4 video-profile: 640x360_850kb/s - format: 4 container: mp4 video-profile: 480x270_450kb/s
再进一步研究发现每天的节目信息网页地址是按照一定格式生成的,如下:
1 http://tv.cctv.com/lm/xwlb/day/年月日.shtm
所以到时只需要解析这个格式的网页的内容就可以了。
ip代理池
ip代理池我直接使用别人写好的,按照其中的说明配置就可以了。
GitHub - jhao104/proxy_pool: Python爬虫代理IP池(proxy pool)
使用这个库有一个小问题,就是需要自己安装redis数据库的服务,可以在redis官网下载,然后编译安装。
Redis
在python程序中使用you-get
在you-get的官网中只给出了cli的调用方式,没有给出python API的调用方式,所以只能使用os或者sys库吗。使用os或者sys库,感觉有一些多此一举,所以我阅读了一下you-get的源码,主要的下载程序在you_get.common 里面,参数的设置也在里面,所以可以通过引入you_get.common的方式来调用you-get。
编写爬虫程序
因为实现的功能比较简单,所以程序也比较简单,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 import requests as rimport bs4import you_get.common as uget_cheader = {"User-Agent" :"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.20 Safari/537.36 Edg/97.0.1072.21" } def get_proxy_dict (): proxy_pool_url = "http://0.0.0.0:5010/get/" http_proxy = None https_proxy = None while (http_proxy is None ) or (https_proxy is None ): res = r.get(proxy_pool_url, headers = header) if res.status_code != 200 : continue res_json = res.json() if res_json["https" ]: https_proxy = res_json["proxy" ] else : http_proxy = res_json["proxy" ] https_proxy_url = "https://%s" %(https_proxy) http_proxy_url = "http://%s" %(http_proxy) return {"https" :https_proxy_url, "http" :http_proxy_url} def get_cctv_video (html_txt,out_dir ): res = bs4.BeautifulSoup(html_txt, "html.parser" ) all_video = res.find_all("a" ) for v in all_video: v_url = v["href" ] print (v_url) uget_c.any_download(v_url, output_dir=out_dir, merge=True ) break def get_cctv (date ): cctv_url_prefix = "http://tv.cctv.com/lm/xwlb/day/%s.shtml" url_to_get = cctv_url_prefix%(date) print ("Get %s" %url_to_get) try_count = 0 try_limit = 5 while try_count < try_limit: try : proxy_dict = get_proxy_dict() res = r.get(url_to_get, headers=header, proxies=proxy_dict) except : try_count += 1 continue if res.status_code != 200 : try_limit += 1 continue else : get_cctv_video(res.text, "./cctv/" ) break print ("Get video fail!" ) if __name__ == "__main__" : for i in range (1 ,32 ): get_cctv("202110%02d" %(i))
完成
查看一下已经下载完成的视频:
1 2 3 4 5 6 7 8 (base) ➜ cctv ls 《新闻联播》 20211001 2100. mp4 《新闻联播》 20211008 2100. mp4 《新闻联播》 20211015 2100. mp4 《新闻联播》 20211022 2100. mp4 《新闻联播》 20211029 2100. mp4 《新闻联播》 20211002 1900. mp4 《新闻联播》 20211009 2100. mp4 《新闻联播》 20211016 2100. mp4 《新闻联播》 20211023 2100. mp4 《新闻联播》 20211030 1900. mp4 《新闻联播》 20211003 1900. mp4 《新闻联播》 20211010 1900. mp4 《新闻联播》 20211017 1900. mp4 《新闻联播》 20211024 1900. mp4 《新闻联播》 20211031 1900. mp4 《新闻联播》 20211004 1900. mp4 《新闻联播》 20211011 2100. mp4 《新闻联播》 20211018 2100. mp4 《新闻联播》 20211025 2100. mp4 《新闻联播》 20211005 1900. mp4 《新闻联播》 20211012 1900. mp4 《新闻联播》 20211019 1900. mp4 《新闻联播》 20211026 2100. mp4 《新闻联播》 20211006 2100. mp4 《新闻联播》 20211013 1900. mp4 《新闻联播》 20211020 1900. mp4 《新闻联播》 20211027 1900. mp4 《新闻联播》 20211007 1900. mp4 《新闻联播》 20211014 1900. mp4 《新闻联播》 20211021 2100. mp4 《新闻联播》 20211028 1900. mp4
其实我发现我下载的视频数目也不多,不会被封IP,所以ip代理池可以不用。