吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 26325|回复: 204
收起左侧

[Python 转载] [源码+打包]抖音视频下载之指定作者批量下载-已更新,请看本贴置顶

     关闭 [复制链接]
neteast 发表于 2022-7-30 10:38
本帖最后由 neteast 于 2022-10-12 12:35 编辑

本程序参考了本站本版的其他两位作者代码,感谢他们的原创作品,吾爱破解论坛因他们更精彩!
程序部份代码及解析API部份来自以下作者。如有关于api的疑问可以去请教原作者
https://www.52pojie.cn/thread-1634311-1-1.html

程序UI设计及部份代码来自以下作者。如有关于UI的疑问可以去请教原作者
https://www.52pojie.cn/thread-1668148-1-1.html



程序食用方法


一。打开APP获得你要下载作者的主页ID
1weixin.png
只要其中的ID即可
3.png

二。将上述ID复制或输入到程序文本框内,点 【获取信息】 ,再点 【开始下载】 即可。
2.png

三。下载文件在 【保存文件】 提示的对话框指定文件夹内

四。打包好的exe方便没有python环境的食用,下载如下
下载:https://wwz.lanzoub.com/iwZMQ08nxt4d 密码:52pj


五。如下是代码部份。


[Python] 纯文本查看 复制代码
# -*- coding:utf-8 -*-
# @FileName  :52pojieUI_douyin.py
# @AuThor    :neteast@52pojie

import os
import re
import subprocess
import threading
import time
import tkinter as tk
import tkinter.font as tkFont
import warnings
from datetime import datetime

import requests

LOG_LINE_NUM = 0


class App:
    def __init__(self, root):
        self.test = False
        self.initUi(root)
        self.initData()
        self.testData()

    def testData(self):
        if (self.test):
            self.GLineEdit_332.insert(0, '2p5EEc9')  # 2sWmMkb
            self.GButton_333['state'] = 'active'

    def initData(self):

        self.nickname = '未找到该ID用户或者暂未发布作品'
        self.status_download = True
        self.tag = 'odd'
        self.session = requests.Session()
        self.session.headers.update({
            'User-Agent': "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1C28 Safari/419.3"})
        self.starurl = None
        self.baseurl = 'https://v.douyin.com/'
        self.baseinfo = 'https://www.iesdouyin.com/web/api/v2/user/info/?'
        self.userinfourl = None

    def initUi(self, root):
        # setting title
        root.title("DYDownloader neteast@52pojie")
        # setting window size
        width = 897
        height = 533
        screenwidth = root.winfo_screenwidth()
        screenheight = root.winfo_screenheight()
        alignstr = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)
        root.geometry(alignstr)
        root.resizable(width=False, height=False)

        ft = tkFont.Font(family='宋体', size=10)
        GLabel_515 = tk.Label(root)
        GLabel_515["font"] = ft
        GLabel_515["justify"] = "center"
        GLabel_515["text"] = "作者ID"
        GLabel_515.place(x=20, y=10, width=47, height=30)

        self.GLineEdit_508 = tk.Entry(root)
        self.GLineEdit_508["borderwidth"] = "1px"
        self.GLineEdit_508["justify"] = "center"
        self.GLineEdit_508["text"] = "path"
        self.GLineEdit_508['state'] = 'readonly'
        self.GLineEdit_508.place(x=90, y=50, width=610, height=30)

        self.GLineEdit_332 = tk.Entry(root)
        self.GLineEdit_332["borderwidth"] = "1px"
        self.GLineEdit_332["justify"] = "center"
        self.GLineEdit_332["text"] = "url"
        self.GLineEdit_332.place(x=90, y=10, width=231, height=30)

        self.GButton_333 = tk.Button(root)
        self.GButton_333["justify"] = "center"
        self.GButton_333["text"] = "开始下载"
        self.GButton_333.place(x=710, y=50, width=90, height=30)
        self.GButton_333['state'] = 'disable'
        self.GButton_333["command"] = self.GButton_333_command

        ft2 = tkFont.Font(family='宋体', size=12)
        self.GLineEdit_428 = tk.Text(root)
        self.GLineEdit_428["borderwidth"] = "1px"
        self.GLineEdit_428["font"] = ft2
        self.GLineEdit_428.place(x=10, y=90, width=881, height=427)

        self.GButton_676 = tk.Button(root)
        self.GButton_676["font"] = ft
        self.GButton_676["justify"] = "center"
        self.GButton_676["text"] = "停止下载"
        self.GButton_676['state'] = 'disable'
        self.GButton_676.place(x=810, y=50, width=74, height=30)
        self.GButton_676["command"] = self.GButton_676_command

        GButton_701 = tk.Button(root)
        GButton_701["font"] = ft
        GButton_701["justify"] = "center"
        GButton_701["text"] = "获取信息"
        GButton_701.place(x=330, y=10, width=70, height=30)
        GButton_701["command"] = self.GButton_701_command

        GLabel_100 = tk.Label(root)
        GLabel_100["font"] = ft
        GLabel_100["justify"] = "center"
        GLabel_100["text"] = "昵称"
        GLabel_100.place(x=410, y=10, width=43, height=30)

        GLabel_1 = tk.Label(root)
        GLabel_1["font"] = ft
        GLabel_1["justify"] = "center"
        GLabel_1["text"] = "条作品"
        GLabel_1.place(x=790, y=10, width=76, height=30)

        self.GLineEdit_690 = tk.Entry(root)
        self.GLineEdit_690["borderwidth"] = "1px"
        self.GLineEdit_690["font"] = ft
        self.GLineEdit_690["justify"] = "center"
        self.GLineEdit_690["text"] = "条作品"
        self.GLineEdit_690['state'] = 'readonly'
        self.GLineEdit_690.place(x=710, y=10, width=90, height=30)

        self.GLineEdit_281 = tk.Entry(root)
        self.GLineEdit_281["borderwidth"] = "1px"
        self.GLineEdit_281["font"] = ft
        self.GLineEdit_281["fg"] = "#333333"
        self.GLineEdit_281["justify"] = "center"
        self.GLineEdit_281["text"] = "昵称"
        self.GLineEdit_281['state'] = 'readonly'
        self.GLineEdit_281.place(x=460, y=10, width=240, height=31)

        GButton_55 = tk.Button(root)
        GButton_55["bg"] = "#efefef"
        GButton_55["font"] = ft
        GButton_55["fg"] = "#000000"
        GButton_55["justify"] = "center"
        GButton_55["text"] = "保存路径"
        GButton_55["relief"] = "groove"
        GButton_55.place(x=10, y=50, width=70, height=30)
        GButton_55["command"] = self.GButton_55_command

    def GButton_55_command(self):  # 打开文件夹
        path = self.GLineEdit_508.get()
        if path:
            self.open_fp(path)

    def GButton_701_command(self):  # 获取信息
        authorId = self.GLineEdit_332.get()
        self.status_download = True
        if authorId:
            self.starurl = self.baseurl + authorId

            self._log(f'{"-" * 20}开始查询,请稍等{"-" * 20}')
            obj1 = threading.Thread(target=self.analysis, args=({False}))
            obj1.setDaemon(True)
            obj1.start()
        else:
            self._log("请输入作者ID")

    def GButton_676_command(self):  # 停止下载
        self.status_download = False
        self.GButton_676['state'] = 'disable'

    def GButton_333_command(self):  # 开始下载
        self.status_download = True
        authorId = self.GLineEdit_332.get()
        if authorId:
            self.starurl = self.baseurl + authorId
            self._log(f'{"-" * 20}准备下载,请稍等{"-" * 20}')
            self.GButton_333['state'] = 'disable'
            self.GButton_676['state'] = 'active'
            self.pcursor = ''
            obj1 = threading.Thread(target=self.analysis, args=({True}))
            obj1.setDaemon(True)
            obj1.start()
        else:
            self._log("请输入作者ID")

    def analysis(self, flag):
        req = self._requests('get', self.starurl, decode_level=3)
        sp = req.url.split('?')
        if len(sp) == 2:
            param = sp[1]
        else:
            self._log(f'{"-" * 20}获取数据失败,请检查主播ID是否正确{"-" * 20}')
            return
        self.userinfourl = self.baseinfo + param
        userinfo = self._requests('get', self.userinfourl, decode_level=2)
        self.nickname = userinfo['user_info']['nickname']
        aweme_count = userinfo['user_info']['aweme_count']
        if not flag:
            self._log(f'{"-" * 20}查询完成!{"-" * 20}')
            filepath = os.getcwd() + '\\' + 'dydownloads' + '\\' + self.nickname
            self.GLineEdit_690['state'] = 'normal'
            self.GLineEdit_281['state'] = 'normal'
            self.GLineEdit_508['state'] = 'normal'
            self.GLineEdit_508.delete(0, 'end')
            self.GLineEdit_281.delete(0, 'end')
            self.GLineEdit_690.delete(0, 'end')
            self.GLineEdit_690.insert(0, f'{aweme_count}')
            self.GLineEdit_281.insert(0, f'{self.nickname}')
            self.GLineEdit_508.insert(0, f'{filepath}')
            self.GLineEdit_690['state'] = 'readonly'
            self.GLineEdit_281['state'] = 'readonly'
            self.GLineEdit_508['state'] = 'readonly'
            self.GButton_333['state'] = 'active'
        else:
            self._log(f'{"-" * 20}开始下载{"-" * 20}')
            max_cursor = 0
            video_has_more = True
            icount = 0;
            while video_has_more and self.status_download:
                json_url = f'https://www.iesdouyin.com/web/api/v2/aweme/post/?{param}&' \
                           f'count=21&max_cursor={max_cursor}'
                req = self._requests('get', json_url, decode_level=2)
                video_has_more = req['has_more']
                max_cursor = req['max_cursor']
                video_list = req['aweme_list']
                for video in video_list:
                    if not self.status_download:
                        self._log(f'{"-" * 20}已停止下载video!{"-" * 20}')
                        break
                    icount += 1
                    self.download_video(video, icount)
            self._log(f'{"-" * 20}全部{aweme_count}个视频已下载完成{icount}个!{"-" * 20}')

    def download_video(self, video, num=0):
        try:
            filepath = os.getcwd() + '/' + 'dydownloads' + '/' + self.nickname
            caption = video['desc']  # title
            vid = video['video']['vid']  # video link
            caption = re.sub('[ \\/:*?"<>|\n\t]', '', caption)
            likeCount = video['statistics']['digg_count']
            comment_count = video['statistics']['comment_count']
            caption = caption[:40] if len(caption) > 40 else caption
            self._log(f'{num:0>3d}{caption} {comment_count}评论 {likeCount}人点赞')
            caption = caption[:28] if len(caption) > 28 else caption
            if caption:
                download_url = f'https://aweme.snssdk.com/aweme/v1/play/?video_id={video["video"]["vid"]}&ratio=1080p'
                video_data = self._requests('get', download_url, decode_level=3).content
                self.save_video(os.path.normpath(filepath),
                                f'{num:0>3d}_' + caption + '_' + video["video"]["vid"] + '.mp4', video_data,
                                download_url)
        except Exception as e:
            print(e)
            self._log(f'获取数据失败,请检查主播ID是否正确,也可能cookies已过期!')

    def save_video(self, path, filename, video_data, url):
        if not os.path.exists(path):
            os.makedirs(path)
        with open(os.path.normpath(os.path.join(path, filename)), 'wb') as f:
            f.write(video_data)
            now_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            self._log(f'  状态:[下载完成]')

    def open_fp(self, fp):
        """
        打开文件或文件夹
        :param fp: 需要打开的文件或文件夹路径
        """
        import platform
        systemType: str = platform.platform()  # 获取系统类型
        if 'mac' in systemType:  # 判断以下当前系统类型
            fp: str = fp.replace("\\", "/")  # mac系统下,遇到`\\`让路径打不开,不清楚为什么哈,觉得没必要的话自己可以删掉啦,18行那条也是
            subprocess.call(["open", fp])
        else:
            fp: str = fp.replace("/", "\\")  # win系统下,有时`/`让路径打不开
            try:
                os.startfile(fp)
            except:
                self._log(f'{"-" * 20}文件还未下载{"-" * 20}')

    def _requests(self, method, url, decode_level=1, retry=0, timeout=15, **kwargs):
        if method in ["get", "post"]:
            for _ in range(retry + 1):
                try:
                    warnings.filterwarnings('ignore')
                    response = getattr(self.session, method)(url, timeout=timeout, verify=False, **kwargs)
                    return response.text if decode_level == 1 else response.json() if decode_level == 2 else response
                except Exception as e:
                    self._log(e)

        return None

    def _log(self, logmsg):
        global LOG_LINE_NUM
        current_time = self.get_current_time()
        logmsg_in = str(current_time) + " " + str(logmsg) + "\n"  # 换行
        self.GLineEdit_428.tag_config("even", background='#e0e0e0')
        self.GLineEdit_428.tag_config("odd", background='#ffffff')
        self.tag = 'odd' if self.tag == 'even' else 'even'
        if LOG_LINE_NUM <= 22:

            self.GLineEdit_428.insert('end', logmsg_in, self.tag)
            LOG_LINE_NUM = LOG_LINE_NUM + 1
        else:
            self.GLineEdit_428.delete(1.0, 2.0)
            self.GLineEdit_428.insert('end', logmsg_in, self.tag)

    def get_current_time(self):
        current_time = time.strftime('%H:%M:%S', time.localtime(time.time()))
        return current_time


if __name__ == "__main__":
    root = tk.Tk()
    app = App(root)
    root.mainloop()


免费评分

参与人数 52吾爱币 +54 热心值 +49 收起 理由
安安安二 + 1 + 1 已经处理,感谢您对吾爱破解论坛的支持!
hongzhonglaoda + 1 + 1 鼓励转贴优秀软件安全工具和文档!
感觉还在不在 + 1 + 1 谢谢@Thanks!
ydb7007 + 1 + 1 热心回复!
LKLJH + 1 + 1 我很赞同!
phiflee + 1 + 1 WC,牛P!~~~~
l146 + 1 + 1 用心讨论,共获提升!
wk882008 + 1 + 1 谢谢@Thanks!
sspm18 + 1 + 1 我很赞同!
wyx071405 + 2 + 1 谢谢@Thanks!
rico_xiang + 1 + 1 我很赞同!
catwl820 + 1 + 1 简直太好用了,谢谢
小蚂蚁哈哈乐 + 1 + 1 我很赞同!正好需要,感谢
why3316 + 1 + 1 谢谢@Thanks!
a1231564123 + 1 + 1 我很赞同!
XJ666 + 1 + 1 我很赞同!
ljb_pojie + 1 + 1 谢谢@Thanks!
zz12590 + 1 + 1 谢谢@Thanks!
Poplar + 1 + 1 谢谢@Thanks!
agatalos + 1 + 1 谢谢@Thanks!
5ipj2007 + 1 谢谢@Thanks!
Ainong + 1 + 1 谢谢@Thanks!
guoguoas + 1 + 1 鼓励转贴优秀软件安全工具和文档!
o冰冰o + 1 + 1 谢谢@Thanks!
yj122325 + 1 + 1 我很赞同!
tianya166 + 1 + 1 谢谢@Thanks!
UXGO + 1 谢谢 @Thanks!
流觞曲水 + 1 + 1 谢谢@Thanks!
志舟ing + 1 谢谢@Thanks!
tyd521 + 1 + 1 我很赞同!
bm98 + 1 + 1 谢谢@Thanks!
ecm05062 + 1 谢谢@Thanks!
baizss + 1 + 1 我很赞同!
a055990 + 1 + 1 谢谢@Thanks!
crosslcy + 1 + 1 谢谢@Thanks!
fqxc + 1 谢谢,能改一个批量抓取头条文章的应用程序吗?爬虫小白求助
何其自性 + 1 + 1 谢谢@Thanks!
sdqwj + 1 + 1 鼓励转贴优秀软件安全工具和文档!
wjr0060 + 1 谢谢@Thanks!
guoruihotel + 1 + 1 谢谢@Thanks!
2255 + 1 + 1 谢谢@Thanks!
dltest + 1 + 1 谢谢@Thanks!
hetiwz + 1 + 1 我很赞同!
lhuanyun + 1 + 1 实在不错!!
叫我主任 + 1 + 1 用心讨论,共获提升!
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
我也叫风清扬 + 1 我很赞同!
jie520yun + 1 + 1 我很赞同!
xueche8 + 1 + 1 我很赞同!
kingzswang + 1 用心讨论,共获提升!
夜步城 + 1 + 1 谢谢@Thanks!
kololi + 1 + 1 用心讨论,共获提升!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| neteast 发表于 2022-10-12 12:28
2022/10/12 收集了热心网友的个别需求,作以下更新

1.可以单独下载指定作品(左侧列表页,单选或多选。按键盘ctrl 或shift 控制多选)
2.修复下载没有文案的作品
3.获取信息时,会生成xls文件,将每条作品文案、点赞数、评论数,对应保存做参考。附有临时下载地址,也可以单独下载。
4.保存文件名统一去除特号,请参考xls文案
5.其它

下载地址:
外链:https://wwz.lanzoub.com/b03dhetxa 密码:52pj

2022-10-12_121543.png

代码如下
[Python] 纯文本查看 复制代码
# -*- coding:utf-8 -*-
# @ FileName  :52pojieUI_douyin.py
# @ Author    :neteast@52pojie

import os
import re
import subprocess
import threading
import tkinter as tk
import tkinter.font as tkFont
import warnings
import requests
from openpyxl import Workbook
from tkinter import *
import tkinter.ttk as ttk
LOG_LINE_NUM = 0


class App:
    def __init__(self, root):
        self.test = True
        self.initUi(root)
        self.initData()
        self.wb = Workbook()
        self.ws = self.wb.create_sheet(index=0, title='sheet1')
        self.ws.append(['序号','标题','点赞数','评论数','临时下载链接'])



    def initData(self):
        self.tvList_var =  Variable()
        self.path = None
        self.allaweme = []
        self.nickname = '未找到该ID用户或者暂未发布作品'
        self.status_download = True
        self.tag = 'odd'
        self.session = requests.Session()
        self.session.headers.update({
            'User-Agent': "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1C28 Safari/419.3"})
        self.starurl = None
        self.baseurl = 'https://v.douyin.com/'
        self.baseinfo = 'https://www.iesdouyin.com/web/api/v2/user/info/?'
        self.userinfourl = None

    def initUi(self, root):
        root.title("DYDownloader neteast@52pojie 2022/10/12")
        width = 897
        height = 533
        screenwidth = root.winfo_screenwidth()
        screenheight = root.winfo_screenheight()
        alignstr = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)
        root.geometry(alignstr)
        root.resizable(width=False, height=False)

        ft = tkFont.Font(family='宋体', size=10)
        GLabel_515 = tk.Label(root)
        GLabel_515["font"] = ft
        GLabel_515["justify"] = "center"
        GLabel_515["text"] = "作者ID"
        GLabel_515.place(x=20, y=10, width=47, height=30)

        self.GLineEdit_508 = tk.Entry(root)
        self.GLineEdit_508["borderwidth"] = "1px"
        self.GLineEdit_508["justify"] = "center"
        self.GLineEdit_508["text"] = "path"
        self.GLineEdit_508['state'] = 'readonly'
        self.GLineEdit_508.place(x=90, y=50, width=610, height=30)

        self.GLineEdit_332 = tk.Entry(root)
        self.GLineEdit_332["borderwidth"] = "1px"
        self.GLineEdit_332["justify"] = "center"
        self.GLineEdit_332["text"] = "url"
        self.GLineEdit_332.place(x=90,y=10,width=128,height=30)

        self.GButton_333 = tk.Button(root)
        self.GButton_333["justify"] = "center"
        self.GButton_333["text"] = "下载全部"
        self.GButton_333.place(x=810, y=50, width=74, height=30)
        self.GButton_333['state'] = 'disable'
        self.GButton_333["command"] = self.GButton_333_command

        ft2 = tkFont.Font(family='宋体', size=11)
        self.GLineEdit_428 = tk.Text(root)
        self.GLineEdit_428["borderwidth"] = "1px"
        self.GLineEdit_428["font"] = ft2
        self.GLineEdit_428.place(x=530,y=90,width=362,height=438)

        self.GLineEdit_515=tk.Entry(root)
        self.GLineEdit_515["borderwidth"] = "1px"
        ft = tkFont.Font(family='Times',size=10)
        self.GLineEdit_515["font"] = ft
        self.GLineEdit_515["fg"] = "#333333"
        self.GLineEdit_515["justify"] = "center"
        self.GLineEdit_515["text"] = "tvlist"
        self.GLineEdit_515.place(x=10,y=90,width=511,height=442)
        yscroll = Scrollbar(self.GLineEdit_515, orient=VERTICAL)
        yscroll.pack(side=RIGHT, fill=Y)
        titles = ('序号', '作品名-(按住ctrl多选,按住shift连选)', '点赞数','评论数','下载链接')
        self.tvList =ttk.Treeview(self.GLineEdit_515, columns=titles, style='Treeview', show='headings', height=21,
                                        yscrollcommand=yscroll.set)
        self.tvList.pack()
        for i in range(len(titles)):
            self.tvList.heading(column=titles[i], text=titles[i], anchor=CENTER) # 定义表头
            self.tvList.column(titles[i], minwidth=20, anchor=CENTER ,stretch=True) # 定义列
        self.tvList.column(titles[0], width=40, anchor=CENTER)
        self.tvList.column(titles[1], width=300, anchor='w')
        self.tvList.column(titles[2], width=75, anchor=CENTER)
        self.tvList.column(titles[3], width=75, anchor=CENTER)
        yscroll.config(command=self.tvList.yview)
        self.tvList.bind("<ButtonRelease-1>", self.get_cursor)

        self.GButton_676 = tk.Button(root)
        self.GButton_676["font"] = ft
        self.GButton_676["justify"] = "center"
        self.GButton_676["text"] = "停止获取"
        self.GButton_676['state'] = 'disable'
        self.GButton_676.place(x=760,y=10,width=131,height=30)
        self.GButton_676["command"] = self.GButton_676_command

        self.GButton_701 = tk.Button(root)
        self.GButton_701["font"] = ft
        self.GButton_701["justify"] = "center"
        self.GButton_701["text"] = "获取信息"
        self.GButton_701.place(x=230,y=10,width=70,height=30)
        self.GButton_701["command"] = self.GButton_701_command

        GLabel_100 = tk.Label(root)
        GLabel_100["font"] = ft
        GLabel_100["justify"] = "center"
        GLabel_100["text"] = "昵称"
        GLabel_100.place(x=300,y=10,width=43,height=30)

        GLabel_1 = tk.Label(root)
        GLabel_1["font"] = ft
        GLabel_1["justify"] = "center"
        GLabel_1["text"] = "条作品"
        GLabel_1.place(x=690,y=10,width=76,height=30)

        self.GLineEdit_690 = tk.Entry(root)
        self.GLineEdit_690["borderwidth"] = "1px"
        self.GLineEdit_690["font"] = ft
        self.GLineEdit_690["justify"] = "center"
        self.GLineEdit_690["text"] = "条作品"
        self.GLineEdit_690['state'] = 'readonly'
        self.GLineEdit_690.place(x=590,y=10,width=90,height=30)

        self.GLineEdit_281 = tk.Entry(root)
        self.GLineEdit_281["borderwidth"] = "1px"
        self.GLineEdit_281["font"] = ft
        self.GLineEdit_281["fg"] = "#333333"
        self.GLineEdit_281["justify"] = "center"
        self.GLineEdit_281["text"] = "昵称"
        self.GLineEdit_281['state'] = 'readonly'
        self.GLineEdit_281.place(x=340,y=10,width=240,height=31)

        GButton_55 = tk.Button(root)
        GButton_55["bg"] = "#efefef"
        GButton_55["font"] = ft
        GButton_55["fg"] = "#000000"
        GButton_55["justify"] = "center"
        GButton_55["text"] = "保存路径"
        GButton_55["relief"] = "groove"
        GButton_55.place(x=10, y=50, width=70, height=30)
        GButton_55["command"] = self.GButton_55_command

        self.GButton_40=tk.Button(root)
        self.GButton_40["bg"] = "#f0f0f0"
        ft = tkFont.Font(family='Times',size=10)
        self.GButton_40["font"] = ft
        self.GButton_40["fg"] = "#000000"
        self.GButton_40["justify"] = "center"
        self.GButton_40["text"] = "下载选定"
        self.GButton_40.place(x=720,y=50,width=73,height=30)
        self.GButton_40["command"] = self.GButton_40_command

    def get_cursor(self, ev):
        self.tvList_var.set([ev.widget.item(idx)['values'] for idx in ev.widget.selection()])

    def GButton_40_command(self):
        obj1 = threading.Thread(target=self.download_video, args=({True}))
        obj1.setDaemon(True)
        obj1.start()


    def GButton_55_command(self):  # 打开文件夹
        path = self.GLineEdit_508.get()
        if path:
            self.open_fp(path)

    def GButton_701_command(self):  # 获取信息
        self.GButton_676['state'] = 'active'
        authorId = self.GLineEdit_332.get()
        for item in self.tvList.get_children():
            self.tvList.delete(item)
        self.GLineEdit_428.delete(0.0,'end')
        global LOG_LINE_NUM
        LOG_LINE_NUM = 0
        self.status_download = True
        if authorId:
            self.starurl = self.baseurl + authorId
            self._log(f'{"-" * 5}开始解析,请稍等{"-" * 5}')
            obj1 = threading.Thread(target=self.analysis, args=({False}))
            obj1.setDaemon(True)
            obj1.start()
        else:
            self._log("请输入作者ID")

    def GButton_676_command(self):  # 停止获取
        self.status_download = not self.status_download
        self.GButton_676['state'] = 'disable'

    def GButton_333_command(self):  # 开始下载
        obj1 = threading.Thread(target=self.download_video, args=({False}))
        obj1.setDaemon(True)
        obj1.start()


    def analysis(self, flag):
        req = self._requests('get', self.starurl, decode_level=3)
        sp = req.url.split('?')
        param =''
        if 'share/user' in req.url and len(sp) == 2:
            param = sp[1]
        else:
            self._log(f'{"-" * 5}获取数据失败,请检查主播ID是否正确{"-" * 5}')
            return
        self.userinfourl = self.baseinfo + param
        userinfo = self._requests('get', self.userinfourl, decode_level=2)
        self.nickname = userinfo['user_info']['nickname']
        sen_text = re.compile(u'[\u4E00-\u9FA5|\s\w]').findall(self.nickname)
        self.nickname = "".join(sen_text)
        if len(self.nickname) < 1:
            self.nickname = '名字全为符号'
        aweme_count = userinfo['user_info']['aweme_count']
        if not flag:
            self._log(f'{"-" * 5}找到作者,开始解析作品!{"-" * 5}')
            filepath = os.getcwd() + '\\' + 'dydownloads' + '\\' + self.nickname
            self.GLineEdit_690['state'] = 'normal'
            self.GLineEdit_281['state'] = 'normal'
            self.GLineEdit_508['state'] = 'normal'
            self.GLineEdit_508.delete(0, 'end')
            self.GLineEdit_281.delete(0, 'end')
            self.GLineEdit_690.delete(0, 'end')
            self.GLineEdit_690.insert(0, f'{aweme_count}')
            self.GLineEdit_281.insert(0, f'{self.nickname}')
            self.GLineEdit_508.insert(0, f'{filepath}')
            self.GLineEdit_690['state'] = 'readonly'
            self.GLineEdit_281['state'] = 'readonly'
            self.GLineEdit_508['state'] = 'readonly'
            self.GButton_333['state'] = 'active'
            file_name = self.GLineEdit_281.get() + '.xlsx'
            max_cursor = 0
            video_has_more = True
            icount = 0;
            while video_has_more and self.status_download:
                json_url = f'https://www.iesdouyin.com/web/api/v2/aweme/post/?{param}&' \
                           f'count=21&max_cursor={max_cursor}'
                req = self._requests('get', json_url, decode_level=2)
                video_has_more = req['has_more']
                max_cursor = req['max_cursor']
                video_list = req['aweme_list']
                for video in video_list:
                    if not self.status_download:
                        self._log(f'{"-" * 5}已停止解析video!{"-" * 5}')
                        break
                    icount += 1
                    self.analysis_video(video, icount)
            self._log(f'{"-" * 5}全部{aweme_count}个视频已解析完成{icount}个!{"-" * 2}')
            if aweme_count > icount and self.status_download:
                self._log(f'作者有隐藏作品{aweme_count - icount}个无法列表')
            self.path = os.getcwd() + '/' + 'dydownloads' + '/' + self.nickname
            if not os.path.exists(self.path):
                os.makedirs(self.path)
            self.wb.save(self.path+'/'+file_name)

    def analysis_video(self, video, num=0):
        try:
            filepath = os.getcwd() + '/' + 'dydownloads' + '/' + self.nickname
            video_desc = video['desc'].replace('\n',' ')
            likeCount = video['statistics']['digg_count']
            comment_count = video['statistics']['comment_count']
            download_url = f'https://aweme.snssdk.com/aweme/v1/play/?video_id={video["video"]["vid"]}&ratio=1080p'
            self.ws.append([num,video_desc,likeCount,comment_count,download_url])
            self.tvList.insert('','end',values=(num,video_desc,likeCount,comment_count,download_url))
            self._log(f'[{num:0>3d}]{video_desc} {comment_count}评论 {likeCount}人点赞')
            self.allaweme.append((num,video_desc,likeCount,comment_count,download_url))
        except Exception as e:
            self._log(f'获取数据失败,请检查主播ID是否正确,也可能cookies已过期!')
            self._log(f'{e}')

    def download_video(self,flag):
        vediolist =[]
        if flag :
            vediolist = self.tvList_var.get()
        else:
            vediolist = self.allaweme
        if len(vediolist) <1 :
            return
        self._log("-----------开始下载----------")
        for vedio in vediolist:
            filename = vedio[1]
            if len(filename) < 1:
                filename = '无标题'
            # filename = filename.replace('\\','').replace('/','').replace(':','').replace('*','').replace('<','')\
            #             .replace('>','').replace('|','').replace('\"','').replace('?','')
            sen_text = re.compile(u'[\u4E00-\u9FA5|\s\w]').findall(filename)
            filename = "".join(sen_text)
            if len(filename) > 40:
                filename = filename[0:40]
            self._log(f'[开始下载]{vedio[0]}{filename}')
            video_data = self._requests('get', vedio[4], decode_level=3).content
            self.save_video(self.path,
                                f'{vedio[0]:0>3d}_' + filename + '_' + '.mp4', video_data                                )
        self._log("-----------下载结束----------")

    def save_video(self, path, filename, video_data):
        if not os.path.exists(path):
            os.makedirs(path)
        with open(os.path.normpath(os.path.join(path, filename)), 'wb') as f:
            f.write(video_data)
            self._log(f'          --------[下载完成]--------')

    def open_fp(self, fp):
        import platform
        systemType: str = platform.platform()  # 获取系统类型
        if 'mac' in systemType:  # 判断以下当前系统类型
            fp: str = fp.replace("\\", "/")  # mac系统下,遇到`\\`让路径打不开,不清楚为什么哈,觉得没必要的话自己可以删掉啦,18行那条也是
            subprocess.call(["open", fp])
        else:
            fp: str = fp.replace("/", "\\")  # win系统下,有时`/`让路径打不开
            try:
                os.startfile(fp)
            except:
                self._log(f'{"-" * 20}文件还未下载{"-" * 20}')

    def _requests(self, method, url, decode_level=1, retry=0, timeout=15, **kwargs):
        if method in ["get", "post"]:
            for _ in range(retry + 1):
                try:
                    warnings.filterwarnings('ignore')
                    response = getattr(self.session, method)(url, timeout=timeout, verify=False, **kwargs)
                    return response.text if decode_level == 1 else response.json() if decode_level == 2 else response
                except Exception as e:
                    self._log(e)
        return None

    def _log(self, logmsg):
        logmsg = logmsg[:25] if len(logmsg) > 25 else logmsg
        global LOG_LINE_NUM
        logmsg_in = str(logmsg) + "\n"  # 换行
        self.GLineEdit_428.tag_config("even", background='#e0e0e0')
        self.GLineEdit_428.tag_config("odd", background='#ffffff')
        self.tag = 'odd' if self.tag == 'even' else 'even'
        if LOG_LINE_NUM <= 27:
            self.GLineEdit_428.insert('end', logmsg_in, self.tag)
            LOG_LINE_NUM = LOG_LINE_NUM + 1
        else:
            self.GLineEdit_428.delete(1.0, 2.0)
            self.GLineEdit_428.insert('end', logmsg_in, self.tag)



if __name__ == "__main__":
    root = tk.Tk()
    app = App(root)
    root.mainloop()


免费评分

参与人数 8吾爱币 +9 热心值 +7 收起 理由
ALRIGHT + 1 + 1 谢谢@Thanks!
Bila + 1 + 1 谢谢@Thanks!
qwerty200696 + 2 用心讨论,共获提升!
haoren6205 + 1 + 1 谢谢@Thanks!
昨日书 + 1 + 1 谢谢@Thanks!
kololi + 1 + 1 我很赞同!
小井不坑 + 1 + 1 能不能增加个点赞或者评论的排序 ,还有采集下视频发布时间 可以的话也排序 .
lwd871209 + 1 + 1 我很赞同!

查看全部评分

pxxwy 发表于 2022-7-30 11:42
duup 发表于 2022-7-30 11:46
songsong20 发表于 2022-7-30 11:52
厉害了  是去水印的吗
kololi 发表于 2022-7-30 11:55
可以的可以的,没有水印很方便。
wkdxz 发表于 2022-7-30 12:00
软件不错,学习了。谢谢楼主分享!
demiao 发表于 2022-7-30 12:29
可以用 作者真牛
guoke2022 发表于 2022-7-30 12:54
这个真方便,谢谢。
bycyrus 发表于 2022-7-30 13:30
漂亮,省了我还要广告
yishanguanlan 发表于 2022-7-30 14:10
正好实用,感谢分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-3-29 04:25

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表