11# -*- coding:utf-8 -*-
22from contextlib import closing
3- import requests , json , re , os , sys
4- from datetime import datetime , timezone
3+ import requests , json , re , os , sys , random
4+ from ipaddress import ip_address
5+ from subprocess import Popen , PIPE
56
67class DouYin (object ):
78def __init__ (self , width = 500 , height = 300 ):
89"""
910抖音App视频下载
1011"""
12+ rip = ip_address ('.' .join (map (str , (random .randint (0 , 255 ) for _ in range (4 )))))
13+ while rip .is_private :
14+ rip = ip_address ('.' .join (map (str , (random .randint (0 , 255 ) for _ in range (4 )))))
1115self .headers = {
1216'accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8' ,
1317'accept-encoding' : 'gzip, deflate, br' ,
1418'accept-language' : 'zh-CN,zh;q=0.9' ,
1519'cache-control' : 'max-age=0' ,
1620'upgrade-insecure-requests' : '1' ,
1721'user-agent' : 'Mozilla/5.0 (Linux; U; Android 5.1.1; zh-cn; MI 4S Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.146 Mobile Safari/537.36 XiaoMi/MiuiBrowser/9.1.3' ,
22+ 'X-Real-IP' : str (rip ),
23+ 'X-Forwarded-For' : str (rip ),
1824}
1925
2026def get_video_urls (self , user_id ):
@@ -31,30 +37,45 @@ def get_video_urls(self, user_id):
3137video_urls = []
3238share_urls = []
3339unique_id = ''
34- while unique_id != user_id :
35- search_url = 'https://api.amemv.com/aweme/v1/discover/search/?cursor=0&keyword=%s&count=10&type=1&retry_type=no_retry&iid=17900846586&device_id=34692364855&ac=wifi&channel=xiaomi&aid=1128&app_name=aweme&version_code=162&version_name=1.6.2&device_platform=android&ssmix=a&device_type=MI+5&device_brand=Xiaomi&os_api=24&os_version=7.0&uuid=861945034132187&openudid=dc451556fc0eeadb&manifest_version_code=162&resolution=1080*1920&dpi=480&update_version_code=1622' % user_id
36- req = requests .get (search_url , headers = self .headers )
37- html = json .loads (req .text )
38- aweme_count = 32767 # html['user_list'][0]['user_info']['aweme_count']
39- uid = html ['user_list' ][0 ]['user_info' ]['uid' ]
40- nickname = html ['user_list' ][0 ]['user_info' ]['nickname' ]
41- unique_id = html ['user_list' ][0 ]['user_info' ]['unique_id' ]
42- user_url = 'https://www.amemv.com/aweme/v1/aweme/post/?user_id=%s&max_cursor=0&count=%s' % (uid , aweme_count )
40+ device_id = str (random .randint (3 , 5 )) + '' .join (map (str , (random .randint (0 , 9 ) for _ in range (10 ))))
41+ search_url = 'https://api.amemv.com/aweme/v1/discover/search/?cursor=0&keyword={0}&count=10&type=1&retry_type=no_retry&device_id={1}&ac=wifi&channel=xiaomi&aid=1128&app_name=aweme&version_code=162&version_name=1.6.2&device_platform=android&ssmix=a&device_type=MI+5&device_brand=Xiaomi&os_api=24&os_version=7.0&manifest_version_code=162&resolution=1080*1920&dpi=480&update_version_code=1622' .format (user_id , device_id )
42+ req = requests .get (search_url , headers = self .headers )
43+ html = json .loads (req .text )
44+ aweme_count = 32767 # html['user_list'][0]['user_info']['aweme_count']
45+ uid = html ['user_list' ][0 ]['user_info' ]['uid' ]
46+ nickname = html ['user_list' ][0 ]['user_info' ]['nickname' ]
47+ unique_id = html ['user_list' ][0 ]['user_info' ]['unique_id' ]
48+ if unique_id != user_id :
49+ unique_id = html ['user_list' ][0 ]['user_info' ]['short_id' ]
50+ if unique_id != user_id :
51+ print ('用户ID可能输入错误或无法搜索到此用户ID' )
52+ sys .exit ()
53+ share_user_url = 'https://www.amemv.com/share/user/%s' % uid
54+ share_user = requests .get (share_user_url , headers = self .headers )
55+ _dytk_re = re .compile (r"dytk: '(.+)'" )
56+ dytk = _dytk_re .search (share_user .text ).group (1 )
57+ print ('签名JS下载中' )
58+ self .video_downloader ('https://raw.githubusercontent.com/loadchange/amemv-crawler/master/fuck-byted-acrawler.js' , 'fuck-byted-acrawler.js' )
59+ try :
60+ process = Popen (['node' , 'fuck-byted-acrawler.js' , str (uid )], stdout = PIPE , stderr = PIPE )
61+ except (OSError , IOError ) as err :
62+ print ('请先安装 node.js: https://nodejs.org/' )
63+ sys .exit ()
64+ sign = process .communicate ()[0 ].decode ()
65+ user_url = 'https://www.amemv.com/aweme/v1/aweme/post/?user_id=%s&max_cursor=0&count=%s&aid=1128&_signature=%s&dytk=%s' % (uid , aweme_count , sign , dytk )
4366req = requests .get (user_url , headers = self .headers )
4467html = json .loads (req .text )
4568for each in html ['aweme_list' ]:
4669share_desc = each ['share_info' ]['share_desc' ]
4770if os .name == 'nt' :
4871for c in r'\/:*?"<>|' :
49- share_desc = share_desc .replace (c , '' )
50- unix_timestamp = each ['create_time' ]
51- utc_time = datetime .fromtimestamp (unix_timestamp , timezone .utc )
52- local_time = utc_time .astimezone ()
53- tc = local_time .strftime ('%Y-%m-%d-%H-%M-%S' )
72+ nickname = nickname .replace (c , '' ).strip ()
73+ share_desc = share_desc .replace (c , '' ).strip ()
74+ share_id = each ['aweme_id' ]
5475if share_desc in ['抖音-原创音乐短视频社区' , 'TikTok' ]:
55- video_names .append (tc + '.mp4' )
76+ video_names .append (share_id + '.mp4' )
5677else :
57- video_names .append (tc + '-' + share_desc + '.mp4' )
78+ video_names .append (share_id + '-' + share_desc + '.mp4' )
5879share_urls .append (each ['share_info' ]['share_url' ])
5980video_urls .append (each ['video' ]['play_addr' ]['url_list' ][0 ])
6081
0 commit comments