Loading... # 爬取抖音 主页|喜欢|合集 视频 ## 说明 1.以下代码仅供学习交流,主要功能爬取抖音用户 主页 喜欢 and 合集 (喜欢仅支持公开的用户) 2.程序运行后会在当前目录下生成video的文件夹存储爬取到的视频 3.需要第三方库 ``` requests ``` ``` bs4 ``` 4.如遇到什么问题和报错请在评论区详细列出 (例如报错)请留下报错日志和出问题的链接 ## 教程 ### 主页和喜欢分享链接获取  ### 合集分享链接获取  ## 演示    ## 代码 ```python import os import requests import time from bs4 import BeautifulSoup class viode_ini: # 初始化游标 max_cursor = 0 # 初始化视频数量 video_count = 0 # 成功下载的视频数量 success = 0 # 失败下载的视频数量 error = 0 # 初始化类型 video = 0 image = 0 # 全局请求头 header = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36' } path = '' # 初始化文件夹 def __init__(self): # 判断文件夹是否存在 if not os.path.exists('video'): os.mkdir('video') if not os.path.exists('video/主页'): os.mkdir('video/主页') if not os.path.exists('video/喜欢'): os.mkdir('video/喜欢') if not os.path.exists('video/合集'): os.mkdir('video/合集') # 链接重定向 def redirect(self, url): response = requests.get(url, headers=self.header) return response.url # 获取sec_uid @staticmethod def get_sec_uid(url): return url.split('user/')[1].split('?')[0] # 获取mix_id @staticmethod def get_mix_id(url): return url.split('detail/')[1].split('/')[0] # 获取用户信息 def get_user_info(self, sec_uid): url = f'https://www.iesdouyin.com/web/api/v2/user/info/?sec_uid={sec_uid}' response = requests.get(url, headers=self.header) return response.json()['user_info']['nickname'] # 特殊字符处理 @staticmethod def replace(title): title = title.replace('\\', '') title = title.replace('/', '') title = title.replace(':', '') title = title.replace('*', '') title = title.replace('?', '') title = title.replace('"', '') title = title.replace('<', '') title = title.replace('>', '') title = title.replace('|', '') title = title.replace('\n', '') return title # 验证是否为视频 @staticmethod def is_video(data): try: video = data['video']['download_addr'] return True except KeyError: return False # 结束输出 def end(self): print('=====================================================') print(f'* 视频总数:{self.video_count}') print(f'* 成功下载:{self.success}') print(f'* 失败下载:{self.error}') print('=====================================================') s = input('回车退出') exit(0) # 视频下载 def download(ini, video, title): try: # 请求视频 response = requests.get(video, headers=ini.header) # 写入视频 with open(f'{ini.path}/{title}.mp4', 'wb') as f: f.write(response.content) # 成功下载数量 ini.success += 1 except Exception as e: log_name = ErrorLog(e) # 失败下载数量 ini.error += 1 print(title + f'下载失败,详细请查看/video/Log/{log_name}.log文件') # 写入日志 def ErrorLog(error): if not os.path.exists('video/Log'): os.mkdir('video/Log') # 获取当前时间 log_name = time.strftime('%Y-%m-%d', time.localtime(time.time())) date = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) Errror = f'====================={date}=====================\n' \ f'{error}\n' \ f'=============================================================\n' # 写入错误日志 with open(f'video/Log/{log_name}.log', 'a', encoding='utf-8') as f: f.write(Errror) return log_name # 程序主入口 def Start(): ini = viode_ini() print('=====================================================') print('***************** 抖音视频爬虫工具 *********************') print('***************** \t作者:安逸 \t*********************') print('=====================================================') print('1.下载用户主页视频\t\t2.下载用户喜欢视频\n3.下载视频合集\t\t4.退出程序') print('=====================================================') choice = input('请输入序号选择类型:') try: if choice == '1': HomeAndLike(ini, choice) elif choice == '2': HomeAndLike(ini, choice) elif choice == '3': Collection(ini) elif choice == '4': exit() else: print('输入错误,请重新输入!') Start() except Exception as e: log_name = ErrorLog(e) input(f'程序出现错误,错误日志已保存至 video/Log 文件夹,联系作者请提交log_name.log文件!') # 主页And喜欢 def HomeAndLike(ini, Type): # 获取真实链接 url = ini.redirect(input('请输入用户主页链接:')) # 获取sec_uid sec_uid = ini.get_sec_uid(url) # 获取用户昵称 nickname = ini.get_user_info(sec_uid) nickname = ini.replace(nickname) # 下载路径 if Type == '1': ini.path = f'video/主页/{nickname}' elif Type == '2': ini.path = f'video/喜欢/{nickname}' # 创建文件夹 if not os.path.exists(ini.path): os.makedirs(ini.path) print('***************** 开始下载视频 *********************') # 开始执行任务 while True: # 接口设置 if Type == '1': url = f'https://m.douyin.com/web/api/v2/aweme/post/?reflow_source=reflow_page&sec_uid={sec_uid}&count=21&max_cursor={ini.max_cursor}' elif Type == '2': url = f'https://m.douyin.com/web/api/v2/aweme/like/?reflow_source=reflow_page&sec_uid={sec_uid}&count=21&max_cursor={ini.max_cursor}' data = requests.get(url, headers=ini.header).json() # 获取视频列表 aweme_list = data['aweme_list'] # 读取视频 for aweme in aweme_list: # 更新视频数量 ini.video_count += 1 # 视频标题 title = f'【{ini.video_count}】 {ini.replace(aweme["desc"])}' # 视频链接 try: video_url = aweme['video']['play_addr']['url_list'][0] except KeyError: ini.error += 1 print('下载失败: ' + title) print('原因: 视频链接获取失败,可能是因为视频已被删除!') continue # 验证视频是否存在 if ini.is_video(aweme): print('正在下载:' + title) # 下载视频 download(ini, video_url, title) else: # 下载失败 ini.error += 1 print('下载失败:' + title) print('失败原因:图文视频,跳过下载') # 判断是否还有下一页 if data['has_more']: # 更新max_cursor ini.max_cursor = data['max_cursor'] else: print('***************** 视频下载结束 *********************') ini.end() # 下载视频合集 def Collection(ini): # 获取真实链接 url = ini.redirect(input('请输入视频合集链接:')) mix_id = url.split('detail/')[1].split('/')[0] # 获取合集信息 url = f'https://www.iesdouyin.com/share/mix/detail/{mix_id}' response = requests.get(url, headers=ini.header) # 获取合集信息 soup = BeautifulSoup(response.text, 'html.parser') # 获取用户昵称 nickname = ini.replace(soup.select('span[class="font-small color-yellow mr-10"]')[0].text).replace('@', '') # 获取合集名称 collection_name = ini.replace(soup.select('span[class="mix-info-name-text"]')[0].text) # 下载路径 ini.path = f'video/合集/{nickname}/{collection_name}' # 创建文件夹 if not os.path.exists('video/合集/{nickname}'): os.makedirs('video/合集/{nickname}') if not os.path.exists(ini.path): os.makedirs(ini.path) print('***************** 开始下载视频 *********************') # 开始执行任务 while True: url = f'https://www.iesdouyin.com/web/api/mix/item/list/?reflow_source=reflow_page&mix_id={mix_id}&count=10&cursor={ini.max_cursor}' data = requests.get(url, headers=ini.header).json() # 获取视频列表数据 aweme_list = data['aweme_list'] for aweme in aweme_list: # 更新视频总数 ini.video_count += 1 # 视频标题 title = f'【第{ini.video_count}集】 {ini.replace(aweme["desc"])}' # 视频链接 try: video_url = aweme['video']['play_addr']['url_list'][0] except KeyError: ini.error += 1 print('下载失败: ' + title) print('原因: 视频链接获取失败,可能是因为视频已被删除!') continue # 验证视频是否存在 if ini.is_video(aweme): print('正在下载:' + title) # 下载视频 download(ini, video_url, title) else: # 下载失败 ini.error += 1 print('下载失败:' + title) print('失败原因:图文视频,跳过下载') # 判断是否还有下一页 if data['has_more']: # 更新游标 ini.max_cursor = data['cursor'] else: print('***************** 视频下载结束 *********************') ini.end() if __name__ == '__main__': Start() ``` ## 下载 已打包程序和代码:<button class=" btn m-b-xs btn-success " onclick="window.open('https://dav.uoll.cn/d/%E9%98%BF%E9%87%8C%E4%BA%91/Blog/%E4%BB%A3%E7%A0%81%E7%AC%94%E8%AE%B0/python/%E7%A8%8B%E5%BA%8F/TiktokVideo.zip?sign=1SKEhde4rEd4arvBdSRuSbJAir6zEXBX1R5ZrdPAdjU=:0','_blank')">点击下载</button> ## 更新 2022-12-12 20:31 1.修复视频重名覆盖导致视频缺失 2.添加视频下载超时处理 2022-12-15 00:10 1.修复遇到图文下载黑屏,解决方案:跳过图文下载 2.对一些潜在的报错进行处理:名称、标题、合集名 进行特殊字符替换 3.重复代码进行优化 最后修改:2022 年 12 月 15 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 24 如果觉得我的文章对你有用,请随意赞赏
14 条评论
这篇文章如同一幅色彩斑斓的画卷,每一笔都充满了独特的创意。
既有宏观视野,又兼顾微观细节。
博主太厉害了!
大佬,下载不了了,能不能抽空更新一下呀!
最近更新的这次一直获取失败
软件用不了,闪退,望解决,可提供资金支持
用不了了,获取失败
为什么用的合集的链接 选择的也是合集 获取会闪退
大神可以加你微信吗?
有问题咱就直说
6666666666666666
我草 支持
支持