Python爬虫作业爬虫专题Python 爬虫专栏

python爬虫CCTV2《环球财经连线》

2018-03-01  本文已影响149人  6c0fe9142f09

笔者前言:平时比较喜欢看CCTV2的《国际财经报道》(原环球财经连线),但是央视的app没有提供缓存功能,笔者又想上下班和跑步的时候看或者听。于是花了大概一天时间写了python脚本爬取了央视的视频并转为音频。
相关文件下载地址:

一、爬取视频

1. 分析视频链接

通过对央视的cctv2直播和国际财经报道专题页面视频流的传递分析,最终选择了专题页面的视频接口,作为视频下载的爬虫接口。


1.CCTV2直播页面
1.2国际财经报道专题页面
1.2.1国际财经报道专题-详细播放页面

直播视频接口的分析不作介绍,感兴趣的读者可以自行分析。详细讲解专题页面的视频接口分析

        var itemid1="VIDEKrNvEp5ead7SdmFq0fxe180228";/*正文页id,赋值给留言评论模块的参数之一*/

        var column_id = "TOPC1451531385787654";/*专题id*/

分析的工作终于渐入尾声,我们来整理一下捋出的线

步骤 描述
1. 视频下载 为了实现视频下载,我们需要知道下载链接http://cntv.hls.cdn.myqcloud.com/asp/hls/850/0303000a/3/default/9f1152607b444e62969618bd2b18b871/4.ts中的节目码
2. 获取节目码 当前页面请求http://tv.cctv.com/2018/02/28/VIDEKrNvEp5ead7SdmFq0fxe180228.shtml返回了我们需要的节目码,获取节目最新节目链接
3.获取最新节目链接 节目接口http://api.cntv.cn/video/getVideoListByTopicIdInfo?videoid=VIDEKrNvEp5ead7SdmFq0fxe180228&topicid=TOPC1451531385787654&serviceId=cbox&type=0&t=jsonp&cb=setItem0=返回了我们需要的最新节目链接,但是要知道videoidtopicid
4. 获取videoidtopicid 在最近任意一期的节目页面请求中http://tv.cctv.com/2018/02/28/VIDEKrNvEp5ead7SdmFq0fxe180228.shtml我们可以获取videoidtopicid
5. 获取最近一期节目链接 我们在专题页面http://tv.cctv.com/lm/hqcjlx/随便拿一期节目链接即可

至此,我们通过这条线就能够下载节目视频了

2. 视频下载

视频的下载可以查读代码,下载成功之后我们就会有一个有一个连续的.ts视频文件了

import requests
import re
import os
import time
import datetime
import hebingshipin


# 设置文件保存根目录
# path = r'E:\xn\开发\python\pythondown_yangshi'
path = r'/home/gzyDesktop/yangshiPython/huanqiucaijinglianxian/output/ts'

# 获取当前日期
now = datetime.datetime.now()
year = (now.strftime('%y'))
month = (now.strftime('%m'))
day = (now.strftime('%d'))
# print(year,month,day)

def getVideo():
    videoCenterId = getVideoCenterId()
    if (videoCenterId == "300"):
        print("今日节目未更新,等待下次监测")
        return "300"
    else:
        print("今日节目已更新,监测是否下载")
        downloadVideo(videoCenterId)


# 根据videoCenterId将对应日期的节目下载到指定文件夹
def downloadVideo(videoCenterId):
    filepath = path+r'/20'+year+month+day
    isExists = os.path.exists(filepath)
    if not isExists:
        # 如果不存在则创建目录
        # 创建目录操作函数
        print("节目未下载,正在创建文件夹")
        os.makedirs(filepath)
        print('文件夹'+filepath + ' 创建成功')

        print("正在下载视频")
        # 下载文件
        for i in range(1, 156):
            downloadUrl = r'http://cntv.hls.cdn.myqcloud.com/asp/hls/850/0303000a/3/default/'+videoCenterId+r'/' + str(i) + r'.ts'
            url = downloadUrl
            r = requests.get(url)
            with open(filepath + r'/'+year+month+day+r'_' + str(i).zfill(3) + r".ts", "wb") as code:
                code.write(r.content)
        print("视频下载成功")
        print("正在将视频转为acc音频文件...")
        hebingshipin.getMusic();
    else:
        # 如果目录存在则不创建,并提示目录已存在
        print("视频已下载")

# 获取《环球财经连线最新节目的url》
def getVideoCenterId():
    #
    # 《环球财经连线》介绍页面
    jieshaoyeurl = "http://tv.cctv.com/lm/hqcjlx/"
    response = requests.get(jieshaoyeurl)

    # 介绍页当前第一个节目的链接正则
    firsturlCompile = '\"><a href=\"(.*?)\" target=\"_blank\">'

    pattern = re.compile(firsturlCompile, re.DOTALL)
    items = re.findall(pattern, response.text)
    # print(items[0])
    firsturl = items[0]

    #
    # 访问获取到的播放页面
    response = requests.get(firsturl)

    # column_id正则
    column_idCompile = 'var column_id = \"(.*?)\";'
    # itemid1正则
    itemid1Compile = 'var itemid1=\"(.*?)\";'

    column_idpattern = re.compile(column_idCompile, re.DOTALL)
    column_iditems = re.findall(column_idpattern, response.text)

    column_id = column_iditems[0]
    # print(column_id)

    itemid1pattern = re.compile(itemid1Compile, re.DOTALL)
    itemid1items = re.findall(itemid1pattern, response.text)

    itemid1 = itemid1items[0]
    # print(itemid1)

    #
    # 由于介绍页面的节目不是最新节目,我们要调用另一个接口去获取最新的节目单

    # http://api.cntv.cn/video/getVideoListByTopicIdInfo?videoid={itemid1}&topicid={column_id}&serviceId=cbox&type=0&t=jsonp&cb=setItem0=
    jiemudanUrl = r'http://api.cntv.cn/video/getVideoListByTopicIdInfo?videoid=' + itemid1 + r'&topicid=' + column_id + r'&serviceId=cbox&type=0&t=jsonp&cb=setItem0='
    response = requests.get(jiemudanUrl)

    # 最新节目url正则
    newJiemuCompile = 'video_url\":\"(.*?)\",'

    newJiemupattern = re.compile(newJiemuCompile, re.DOTALL)
    newJiemuitems = re.findall(newJiemupattern, response.text)
    # print(response.text)
    newJiemu = newJiemuitems[0]
    # print(newJiemu)

    #
    #至此最新节目的url已经获取到了
    #
    #判断当前节目是否是最新节目,如果不是则return
    if(newJiemu.find(day+".shtml") == -1):
        return "300"
    #
    # 获取最新节目的videoCenterId,用于后续的下载
    response = requests.get(newJiemu)

    # 最新节目url正则
    videoCenterIdCompile = r'addVariable\("videoCenterId","(.*?)"\);'

    videoCenterIdpattern = re.compile(videoCenterIdCompile, re.DOTALL)
    videoCenterIditems = re.findall(videoCenterIdpattern, response.text)

    videoCenterId = videoCenterIditems[0]
    # print(videoCenterId)
    return videoCenterId


二、视频的合并与转码

视频的合并使用了ffmpeg,下载和安装可以参考 Centos 7.3 Install ffmpeg 3.1

def hebingshipin(inVideopath,outVideopath,outFilename):
    mkdir(inVideopath)
    mkdir(outVideopath)
    dirs = inVideopath
    mp4 = outVideopath
    filename = outFilename
    a = 1
    content = ""
    lists = os.listdir(dirs)
    lists.sort()
    print(lists)
    b = [lists[i:i + 250] for i in range(0, len(lists), 250)]
    for lis in b:
        cmd = "cd %s && ffmpeg -i \"concat:" % mp4
        for file in lis:
            if file != '.DS_Store':
                file_path = os.path.join(dirs, file)
                cmd += file_path + '|';
                # print("文件:%s"%file_path)
        cmd = cmd[:-1]
        cmd += '" -bsf:a aac_adtstoasc -c copy -vcodec copy %s.mp4' % a
        try:
            os.system(cmd)
            content += "file '%s.mp4'\n" % a
            a = a + 1
        except:
            print("Unexpected error")

    fp = open("%smp4list.txt" % mp4, 'a+')
    fp.write(content)
    fp.close()
    mp4cmd = "cd %s && ffmpeg -y -f concat -i mp4list.txt -c copy %s" % (mp4, filename)
    os.system(mp4cmd)
    filenamecmd = "cd %s && mv 1.mp4 %s" % (mp4, filename)
    os.system(filenamecmd)

def mkdir(filepath):
    isExists = os.path.exists(filepath)
    if not isExists:
        # 如果不存在则创建目录
        # 创建目录操作函数  
        os.makedirs(filepath)
    else:
        print(filepath+'文件夹已建立')

三、将视频转换为音频

def videoToaacmusic(videoFilepath,videoFilename,musicFilename):
    mkdir(videoFilepath)
    haveMusiccmd = "cd %s && ffmpeg -i %s -vn -y -acodec -ab 192k copy %s" % (videoFilepath,videoFilename,musicFilename)
    os.system(haveMusiccmd)

总结:大概花了一天时间实现了这个想法,都是一些非常成熟的技术,重点在一整条链路的分析上,由于笔者是性能测试工程师,时常接触这方便的内容,且使用了其他工具,所以较为熟练。存在的疑点为:python爬虫的分析,目前是否存在相关的插件,可以帮助分析出一整条链路?

上一篇 下一篇

猜你喜欢

热点阅读