@@ -25,7 +25,7 @@ def __init__(self, width = 500, height = 300):
2525 'X-Forwarded-For' : str (rip ),
2626 }
2727
28- def get_video_urls (self , user_id ):
28+ def get_video_urls (self , user_id , type_flag = 'f' ):
2929 """
3030 获得视频播放地址
3131 Parameters:
@@ -40,40 +40,65 @@ def get_video_urls(self, user_id):
4040 share_urls = []
4141 max_cursor = 0
4242 has_more = 1
43- share_user_url = 'https://www.amemv.com/share/user/%s' % user_id
43+ i = 0
44+ share_user_url = 'https://www.douyin.com/share/user/%s' % user_id
4445 share_user = requests .get (share_user_url , headers = self .headers )
45- _dytk_re = re .compile (r"dytk:\s*'(.+)'" )
46+ while share_user .status_code != 200 :
47+ share_user = requests .get (share_user_url , headers = self .headers )
48+ _dytk_re = re .compile (r"dytk\s*:\s*'(.+)'" )
4649 dytk = _dytk_re .search (share_user .text ).group (1 )
4750 _nickname_re = re .compile (r'<p class="nickname">(.+?)<\/p>' )
4851 nickname = _nickname_re .search (share_user .text ).group (1 )
49- print ('JS签名下载中' )
5052 urllib .request .urlretrieve ('https://raw.githubusercontent.com/Jack-Cherish/python-spider/master/douyin/fuck-byted-acrawler.js' , 'fuck-byted-acrawler.js' )
5153 try :
52- process = Popen (['node' , 'fuck-byted-acrawler.js' , str ( user_id ) ], stdout = PIPE , stderr = PIPE )
54+ Popen (['node' , '-v' ], stdout = PIPE , stderr = PIPE ). communicate ( )
5355 except (OSError , IOError ) as err :
5456 print ('请先安装 node.js: https://nodejs.org/' )
5557 sys .exit ()
56- sign = process . communicate ()[ 0 ]. decode (). strip ( ' \n ' ). strip ( ' \r ' )
58+ user_url_prefix = 'https://www.douyin.com/aweme/v1/aweme/favorite' if type_flag == 'f' else 'https://www.douyin.com/aweme/v1/aweme/post'
5759 print ('解析视频链接中' )
5860 while has_more != 0 :
59- user_url = 'https://www.amemv.com/aweme/v1/aweme/post/?user_id=%s&max_cursor=%s&count=21&aid=1128&_signature=%s&dytk=%s' % (user_id , max_cursor , sign , dytk )
61+ process = Popen (['node' , 'fuck-byted-acrawler.js' , str (user_id )], stdout = PIPE , stderr = PIPE )
62+ _sign = process .communicate ()[0 ].decode ().strip ('\n ' ).strip ('\r ' )
63+ user_url = user_url_prefix + '/?user_id=%s&max_cursor=%s&count=21&aid=1128&_signature=%s&dytk=%s' % (user_id , max_cursor , _sign , dytk )
6064 req = requests .get (user_url , headers = self .headers )
6165 while req .status_code != 200 :
6266 req = requests .get (user_url , headers = self .headers )
6367 html = json .loads (req .text )
68+ try :
69+ while html ['aweme_list' ] == []:
70+ i = i + 1
71+ sys .stdout .write ('已重新链接' + str (i ) + '次 (若超过100次,请ctrl+c强制停止再重来)' + '\r ' )
72+ sys .stdout .flush ()
73+ process = Popen (['node' , 'fuck-byted-acrawler.js' , str (user_id )], stdout = PIPE , stderr = PIPE )
74+ _sign = process .communicate ()[0 ].decode ().strip ('\n ' ).strip ('\r ' )
75+ user_url = user_url_prefix + '/?user_id=%s&max_cursor=%s&count=21&aid=1128&_signature=%s&dytk=%s' % (user_id , max_cursor , _sign , dytk )
76+ req = requests .get (user_url , headers = self .headers )
77+ while req .status_code != 200 :
78+ req = requests .get (user_url , headers = self .headers )
79+ html = json .loads (req .text )
80+ except :
81+ pass
82+ i = 0
6483 for each in html ['aweme_list' ]:
84+ try :
85+ url = 'https://aweme.snssdk.com/aweme/v1/play/?video_id=%s&line=0&ratio=720p&media_type=4&vr_type=0&test_cdn=None&improve_bitrate=0'
86+ uri = each ['video' ]['play_addr' ]['uri' ]
87+ video_url = url % uri
88+ except :
89+ continue
6590 share_desc = each ['share_info' ]['share_desc' ]
6691 if os .name == 'nt' :
6792 for c in r'\/:*?"<>|' :
6893 nickname = nickname .replace (c , '' ).strip ().strip ('\.' )
6994 share_desc = share_desc .replace (c , '' ).strip ()
7095 share_id = each ['aweme_id' ]
71- if share_desc in ['抖音-原创音乐短视频社区' , 'TikTok' ]:
96+ if share_desc in ['抖音-原创音乐短视频社区' , 'TikTok' , '' ]:
7297 video_names .append (share_id + '.mp4' )
7398 else :
7499 video_names .append (share_id + '-' + share_desc + '.mp4' )
75100 share_urls .append (each ['share_info' ]['share_url' ])
76- video_urls .append (each [ 'video' ][ 'play_addr' ][ 'url_list' ][ 0 ] )
101+ video_urls .append (video_url )
77102 max_cursor = html ['max_cursor' ]
78103 has_more = html ['has_more' ]
79104
@@ -89,10 +114,10 @@ def get_download_url(self, video_url, watermark_flag):
89114 """
90115 # 带水印视频
91116 if watermark_flag == True :
92- download_url = video_url
117+ download_url = video_url . replace ( '/play/' , '/playwm/' )
93118 # 无水印视频
94119 else :
95- download_url = video_url .replace ('playwm' , 'play' )
120+ download_url = video_url .replace ('/ playwm/ ' , '/ play/ ' )
96121
97122 return download_url
98123
@@ -132,11 +157,25 @@ def run(self):
132157 None
133158 """
134159 self .hello ()
135- user_id = input ('请输入UID(例如60388937600):' )
136- watermark_flag = int (input ('是否下载带水印的视频(0-否,1-是):' ))
137- video_names , video_urls , share_urls , nickname = self .get_video_urls (user_id )
138- if nickname not in os .listdir ():
139- os .mkdir (nickname )
160+ print ('搜索api需要登录,暂时使用UID下载\n 分享用户页面,用浏览器打开短链接,原始链接中/share/user/后的数字即是UID' )
161+ user_id = input ('请输入ID (例如95006183):' )
162+ user_id = user_id if user_id else '95006183'
163+ watermark_flag = input ('是否下载带水印的视频 (0-否(默认), 1-是):' )
164+ watermark_flag = watermark_flag if watermark_flag != '' else '0'
165+ watermark_flag = bool (int (watermark_flag ))
166+ type_flag = input ('f-收藏的(默认), p-上传的:' )
167+ type_flag = type_flag if type_flag != '' else 'f'
168+ save_dir = input ('保存路径 (例如"E:/Download/", 默认"./Download/"):' )
169+ save_dir = save_dir if save_dir else "./Download/"
170+ video_names , video_urls , share_urls , nickname = self .get_video_urls (user_id , type_flag )
171+ nickname_dir = os .path .join (save_dir , nickname )
172+ if not os .path .exists (save_dir ):
173+ os .makedirs (save_dir )
174+ if nickname not in os .listdir (save_dir ):
175+ os .mkdir (nickname_dir )
176+ if type_flag == 'f' :
177+ if 'favorite' not in os .listdir (nickname_dir ):
178+ os .mkdir (os .path .join (nickname_dir , 'favorite' ))
140179 print ('视频下载中:共有%d个作品!\n ' % len (video_urls ))
141180 for num in range (len (video_urls )):
142181 print (' 解析第%d个视频链接 [%s] 中,请稍后!\n ' % (num + 1 , share_urls [num ]))
@@ -146,10 +185,11 @@ def run(self):
146185 video_name = video_names [num ].replace ('/' , '' )
147186 else :
148187 video_name = video_names [num ]
149- if os .path .isfile (os .path .join (nickname , video_name )):
188+ video_path = os .path .join (nickname_dir , video_name ) if type_flag != 'f' else os .path .join (nickname_dir , 'favorite' , video_name )
189+ if os .path .isfile (video_path ):
150190 print ('视频已存在' )
151191 else :
152- self .video_downloader (video_urls [num ], os . path . join ( nickname , video_name ) , watermark_flag )
192+ self .video_downloader (video_urls [num ], video_path , watermark_flag )
153193 print ('\n ' )
154194 print ('下载完成!' )
155195
0 commit comments