1
1
# -*- coding:utf-8 -*-
2
2
from 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
5
6
6
7
class DouYin (object ):
7
8
def __init__ (self , width = 500 , height = 300 ):
8
9
"""
9
10
抖音App视频下载
10
11
"""
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 )))))
11
15
self .headers = {
12
16
'accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8' ,
13
17
'accept-encoding' : 'gzip, deflate, br' ,
14
18
'accept-language' : 'zh-CN,zh;q=0.9' ,
15
19
'cache-control' : 'max-age=0' ,
16
20
'upgrade-insecure-requests' : '1' ,
17
21
'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 ),
18
24
}
19
25
20
26
def get_video_urls (self , user_id ):
@@ -31,30 +37,45 @@ def get_video_urls(self, user_id):
31
37
video_urls = []
32
38
share_urls = []
33
39
unique_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 )
43
66
req = requests .get (user_url , headers = self .headers )
44
67
html = json .loads (req .text )
45
68
for each in html ['aweme_list' ]:
46
69
share_desc = each ['share_info' ]['share_desc' ]
47
70
if os .name == 'nt' :
48
71
for 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' ]
54
75
if share_desc in ['抖音-原创音乐短视频社区' , 'TikTok' ]:
55
- video_names .append (tc + '.mp4' )
76
+ video_names .append (share_id + '.mp4' )
56
77
else :
57
- video_names .append (tc + '-' + share_desc + '.mp4' )
78
+ video_names .append (share_id + '-' + share_desc + '.mp4' )
58
79
share_urls .append (each ['share_info' ]['share_url' ])
59
80
video_urls .append (each ['video' ]['play_addr' ]['url_list' ][0 ])
60
81
0 commit comments