python视频

仅用于学习python之用

1. 下载历史视频

#!/usr/bin/env python
# encoding: utf-8
'''

'''
import os, sys, requests
import json, re, time
from retrying import retry
from contextlib import closing


class DouYin:
    '''
     This is a main Class, the file contains all documents.
     One document contains paragraphs that have several sentences
     It loads the original file and converts the original file to new content
     Then the new content will be saved by this class
    '''

    def __init__(self):
        '''
        Initial the custom file by some url
        '''
        self.headers = {
            'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
            'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
            'pragma': 'no-cache',
            'cache-control': 'no-cache',
            'upgrade-insecure-requests': '1',
            'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1',
        }

    def hello(self):
        '''
        This is welcome speech
        :return: self
        '''
        print("*" * 50)
        print(' ' * 15 + '抖音下载小助手')
        print(' ' * 5 + '改进者: Hou bin Date: 2021-02-20 20:45')
        print(' ' * 15 + '无水印 | 有水印')
        print(' ' * 12 + '输入用户的sec_uid即可')
        print(' ' * 2 + '用浏览器打开用户分享链接,复制参数中sec_uid')
        print("*" * 50)
        return self

    def get_video_urls(self, sec_uid, type_flag='p'):
        '''
        Get the video link of user
        :param type_flag: the type of video
        :return: nickname, video_list
        '''
        user_url_prefix = 'https://www.iesdouyin.com/web/api/v2/aweme/post' if type_flag == 'p' else 'https://www.iesdouyin.com/web/api/v2/aweme/like'
        print('---解析视频链接中...\r')

        i = 0
        result = []
        while result == []:
            i = i + 1
            print('---正在第 {} 次尝试...\r'.format(str(i)))
            user_url = user_url_prefix + '/?sec_uid=%s&count=2000' % (sec_uid)
            response = self.get_request(user_url)
            html = json.loads(response.content.decode())
            if html['aweme_list'] != []:
                result = html['aweme_list']

        nickname = None
        count=0
        video_list = []
        for item in result:
            count+=1
            if nickname is None:
                nickname = item['author']['nickname'] if re.sub(r'[\/:*?"<>|]', '',
                                                                item['author']['nickname']) else None

            video_list.append({
                'desc': "{}.".format(str(count))+re.sub(r'[\/:*?"<>|\n]', '', item['desc']) if item['desc'] else "{}.".format(str(count))+'无标题' + str(int(time.time())),
                'url': item['video']['play_addr']['url_list'][0]
            })
        return nickname, video_list

    def get_download_url(self, video_url, watermark_flag):
        '''
        Whether to download watermarked videos
        :param video_url: the url of video
        :param watermark_flag: the type of video
        :return: the url of o
        '''
        if watermark_flag == True:
            download_url = video_url.replace('api.amemv.com', 'aweme.snssdk.com')
        else:
            download_url = video_url.replace('aweme.snssdk.com', 'api.amemv.com')

        return download_url

    def video_downloader(self, video_url, video_name, watermark_flag=False):
        '''
        Download the video
        :param video_url: the url of video
        :param video_name: the name of video
        :param watermark_flag: the flag of video
        :return: None
        '''
        size = 0
        video_url = self.get_download_url(video_url, watermark_flag=watermark_flag)
        with closing(requests.get(video_url, headers=self.headers, stream=True)) as response:
            chunk_size = 1024
            content_size = int(response.headers['content-length'])
            if response.status_code == 200:
                sys.stdout.write('----[文件大小]:%0.2f MB\n' % (content_size / chunk_size / 1024))

                with open(video_name + '.mp4', 'wb') as file:
                    for data in response.iter_content(chunk_size=chunk_size):
                        file.write(data)
                        size += len(data)
                        file.flush()

                        sys.stdout.write('----[下载进度]:%.2f%%' % float(size / content_size * 100) + '\r')
                        sys.stdout.flush()

    @retry(stop_max_attempt_number=3)
    def get_request(self, url, params=None):
        '''
        Send a get request
        :param url: the url of request
        :param params: the params of request
        :return: the result of request
        '''
        if params is None:
            params = {}
        response = requests.get(url, params=params, headers=self.headers, timeout=10)
        assert response.status_code == 200
        return response

    @retry(stop_max_attempt_number=3)
    def post_request(self, url, data=None):
        '''
        Send a post request
        :param url: the url of request
        :param data: the params of request
        :return: the result of request
        '''
        if data is None:
            data = {}
        response = requests.post(url, data=data, headers=self.headers, timeout=10)
        assert response.status_code == 200
        return response

    def run(self):
        '''
        Program entry
        '''
        sec_uid = input('请输入用户sec_uid:')
        sec_uid = sec_uid if sec_uid else 'MS4wLjABAAAAle_oORaZCgYlB84cLTKSqRFvDgGmgrJsS6n3TfwxonM'

        watermark_flag = input('是否下载带水印的视频 (0-否(默认), 1-是):')
        watermark_flag = bool(int(watermark_flag)) if watermark_flag else 0

        type_flag = input('p-上传的(默认), l-收藏的:')
        type_flag = type_flag if type_flag else 'p'

        save_dir = input('保存路径 (默认"./Download/"):')
        save_dir = save_dir if save_dir else "./Download/"

        nickname, video_list = self.get_video_urls(sec_uid, type_flag)
        nickname_dir = os.path.join(save_dir, nickname)

        if not os.path.exists(nickname_dir):
            os.makedirs(nickname_dir)

        if type_flag == 'f':
            if 'favorite' not in os.listdir(nickname_dir):
                os.mkdir(os.path.join(nickname_dir, 'favorite'))

        print('---视频下载中: 共有%d个作品...\r' % len(video_list))

        for num in range(len(video_list)):
            print('---正在解析第%d个视频链接 [%s] 中,请稍后...\n' % (num + 1, video_list[num]['desc']))

            video_path = os.path.join(nickname_dir, video_list[num]['desc']) if type_flag != 'f' else os.path.join(
                nickname_dir, 'favorite', video_list[num]['desc'])
            if os.path.isfile(video_path):
                print('---视频已存在...\r')
            else:
                self.video_downloader(video_list[num]['url'], video_path, watermark_flag)
            print('\n')
        print('---下载完成...\r')


if __name__ == "__main__":
    DouYin().hello().run()

代码文件download_his.py,
使用说明参考 https://blog.csdn.net/hb_learing/article/details/113892621?spm=1001.2014.3001.5502

2. 监控多个账号直播状态并录制视频

# -*- coding: utf-8 -*-

import requests
import json, os
import time
import sys
from pathlib import Path
import traceback
import urllib.request
import random
import multiprocessing

# 获取登录后的cookie
def get_cookies(username,password):
    print("get_cookies")
    headers = {
        'Host': 'api-service.chanmama.com',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:97.0) Gecko/20100101 Firefox/97.0',
        'Accept': 'application/json, text/plain, */*',
        'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
        'Accept-Encoding': 'gzip, deflate, br',
        'Referer': 'https://www.chanmama.com/login',
        'Content-Type': 'application/json;charset=utf-8',
        'X-Client-Id': '3057153329',
        #'Content-Length': '130',
        'Origin': 'https://www.chanmama.com',
        'Connection': 'keep-alive',
        'Cookie': 'Qs_lvt_411649=1645779886%2C1646012504%2C1646043451%2C1646100509%2C1646187120; Qs_pv_411649=4463430239281573000%2C900198088675931400%2C941538611317045000%2C3144867226959896600%2C16376944367739524; CMM_A_C_ID=09868efa-9605-11ec-adbb-0abe4946c76b; Hm_lvt_1f19c27e7e3e3255a5c79248a7f4bdf1=1645779886; Hm_lpvt_1f19c27e7e3e3255a5c79248a7f4bdf1=1646117927',
        'Sec-Fetch-Dest': 'empty',
        'Sec-Fetch-Mode': 'cors',
        'Sec-Fetch-Site': 'same-site',
        'TE': 'trailers'
    }
    filepath = Path.cwd().joinpath('token.json')
    if not filepath.exists():
        # 登录页面
        downlod_url = 'https://api-service.chanmama.com/v1/access/token'
        # 时间戳,先弄成整数型的,再弄成字符串
        timeStamp = str(int(time.time()))
        # 发起请求时携带的参数
        data = {
            'appId': '10000',
            'password': password,
            'timeStamp': timeStamp,
            'username': username,
        }
        print (data)
        # 对参数json化一下
        data = json.dumps(data)
        # 发起一个post请求,返回的数据也是json类型的,用res接一下
        res = requests.post(downlod_url,headers=headers,data=data).json()
        # 返回了一个json串,里面有一个键值是'errCode',大家可以自己试一下故意输错密码,或者带错参数,返回的都不是0
        # 也就是说只有返回的'errCode'是0的情况下才说明我们登录成功了!
        print ("new login")
        print(res)
        if res['errCode'] == 0:
            save_json('token.json', res)
        else:
            print ("error")
            return
    else:
        print ("old login")
        res = load_json('token.json')
        print(res)

    # 进行登录是否成功的一个验证,返回的键值里面是数字嘛,所以0就不用带引号了
    if res['errCode'] == 0:
        print('成功取得cookies!')
        # 处理我们的cookies
        #headers['Authorization'] = res['data']['token']
        headers['Cookie'] = 'Qs_lvt_411649=1645770885%2C1645779886%2C1646012504%2C1646043451%2C1646100509; Qs_pv_411649=1864459626041325600%2C1717597733433621500%2C486146630748321900%2C2485253651107755500%2C1084117790172438800; CMM_A_C_ID=09868efa-9605-11ec-adbb-0abe4946c76b; Hm_lvt_1f19c27e7e3e3255a5c79248a7f4bdf1=1645779886; Hm_lpvt_1f19c27e7e3e3255a5c79248a7f4bdf1=1646100947; LOGIN-TOKEN-FORSNS=' + res['data']['token']
        return headers

    else:
        print('没了,看看是密码错了还是参数带错了吧。')

def check_livestate(headers,key,nums):
    # 搜索界面的url
    url = 'https://api-service.chanmama.com/v2/douyin/live/search'
    # 发起请求时携带的参数
    data = {"search_type":0,"keyword_type":0,"province":"","page":1,"star_category":"","star_sub_category":"","multi_product_category":[],"keyword":key,"follower_count":"","volume":"","sort":"begin_time","order_by":"desc","size":nums,"is_take_product":0,"has_warm_aweme":0,"live_state":2,"live_begin_time":"2022-02-24","live_end_time":"2022-03-02"}
    # 这里为什么用json=而不用data=呢,是json可以帮我们跟网页说这个数据你需要自己弄成json串
    # 使用data传参的话,是支持嵌套字典的,两者都可以用,当然这里你也可以选择手动处理一下data
    res = requests.post(url, json=data, headers=headers).json()

    #print (res)
    if res['errCode'] == 0:
        if len(res['data']['list']) > 0:
            #save_json('data3.json', res['data']['list'])
            for i in range(len(res['data']['list'])):
                nickname = res['data']['list'][i]['author']['nickname']
                #print (nickname)
                if nickname == key:
                    room_id = res['data']['list'][i]['room_id']
                    return room_id, nickname
        return "", ""
    else:
        print ("error")
        print (res)
        return "false", ""

def load_json(filename: str):
    filepath = Path.cwd().joinpath(filename)
    if filepath.exists():
        with open(filepath, mode="r", encoding="UTF-8") as f:
            data = json.load(f)
        return data
    else:
        #save_json(filename, {})
        return {}

def save_json(filename: str, data: dict):
    filepath = Path.cwd().joinpath(filename)
    with open(filepath, mode="w+", encoding="UTF-8") as f:
        json.dump(
            data,
            f,
            indent=4,
            ensure_ascii=False
        )

def get_flv_url(headers, roomid):
    url = 'https://api-service.chanmama.com/v1/douyin/live/room/info'
    params = {'room_id': roomid}
    headers['Referer'] = 'https://www.chanmama.com/liveDetail/'+str(roomid)
    #url = "https://api-service.chanmama.com/v1/user/info"
    #params = {'timeStamp': str(int(time.time()))}
    print (url)
    #print (headers)
    try:
        res = requests.get(url, headers=headers, params=params, timeout=3).json()
        #
        if res['errCode'] == 0:
            #save_json('data4.json', res)
            return res['data']['author']['nickname'], res['data']['room']['play_flv_url']
        else:
            print ("error")
            print(res)
            return
    except requests.exceptions.RequestException as e:
        print(e)

def save_flv(nickname, real_url):
    videopath = ""
    if real_url != None:
        now = time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime(time.time()))
        try:
            if len(videopath) > 0:
                if videopath[-1] != "\\":
                    videopath = videopath + "\\"
                if not os.path.exists(videopath + nickname):
                    os.makedirs(videopath + nickname)
            else:
                if not os.path.exists(nickname):
                    os.makedirs('./' + nickname)

        except Exception as e:
            print("路径错误信息708: " + str(e) + " 发生错误的行数: " + str(e.__traceback__.tb_lineno))

        if not os.path.exists(videopath + nickname):
            print("保存路径不存在,不能生成录制.请避免把本程序放在c盘,桌面,下载文件夹,qq默认传输目录.请重新检查设置")
            videopath = ""
            print("因为配置文件的路径错误,本次录制在程序目录")

        filename = nickname + '_' + now + '.flv'
        if len(videopath) == 0:
            print("\r" + nickname + " 录制视频中: " + os.getcwd() + "\\" + nickname + '\\' + filename)
        else:
            print("\r" + nickname + " 录制视频中: " + videopath + nickname + '\\' + filename)

        if not os.path.exists(videopath + nickname):
            print("目录均不能生成文件,不能生成录制.请避免把本程序放在c盘,桌面,下载文件夹,qq默认传输目录.请重新检查设置,程序将会退出")
            input("请按回车退出")
            os._exit(0)
        # flv录制格式

        try:
            _filepath, _ = urllib.request.urlretrieve(real_url, videopath + nickname + '\\' + filename)
        except Exception:
            print (traceback.format_exc())
            print('\r' + time.strftime('%Y-%m-%d %H:%M:%S  ') + nickname + ' 未开播')

def record_data(record_list, headers):
    print ("record_data")
    r_list = []
    while True:
        #print("记录列表")
        #print(record_list)
        if not record_list.empty():
            room_id = record_list.get()["room_id"]
            nickname, play_flv_url = get_flv_url(headers, room_id)
            #print(play_flv_url)
            #time.sleep(random.randint(1, 10))
            print ("保存视频%s"%nickname)
            r_list.append(nickname)
            p3 = multiprocessing.Process(target=save_flv, args=(nickname, play_flv_url, ))
            p3.start()
        time.sleep(3)
        for i in range(len(r_list)):
            print ("%s正在录制视频中..."%r_list[i])

def check_state(record_list, norecord_list, headers):
    print ("check_state")
    while True:
        if not norecord_list.empty():
            key = norecord_list.get()
            print (10*'-')
            print ("监控直播状态:%s"%key)
            room_id, nickname = check_livestate(headers, key, 50)
            # print (room_id, nickname)
            if room_id == "false":
                sys.exit()
            elif room_id != "":
                print("%s正在直播" % nickname)
                record_list.put({"room_id": room_id, "nickname": nickname})
                print (record_list)
            else:
                print("----%s没有直播" % key)
                norecord_list.put(key)
            time.sleep(random.randint(20, 60))

if __name__ == '__main__':
    try:
        #填入婵妈妈账号和密码
        user_cmm = ''
        passwd_cmm = ''
        headers = get_cookies( user_cmm, passwd_cmm)
        users = load_json('users.json')
        print (users)

        record_list = multiprocessing.Queue()
        norecord_list = multiprocessing.Queue()
        for i in range(len(users)):
            norecord_list.put(users[i])

        p1 = multiprocessing.Process(target=check_state, args=(record_list, norecord_list, headers,))
        p1.start()
        p2 = multiprocessing.Process(target=record_data, args=(record_list, headers,))
        p2.start()
        while(1):
            a =1
    except Exception:
        print("error")
        print (traceback.format_exc())
        urllib.request.urlcleanup()
        sys.exit()
    except KeyboardInterrupt:
        print ("暂停")
        urllib.request.urlcleanup()
        sys.exit()

代码文件download_live.py
将需要监控的抖音账号名添加到users.json文件中,在download_live.py文件中填入婵mama账号和密码,运行即可

如果报账号在其它地点已登录的错误,则删除文件夹下token.json,重新运行程序即可

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值