app1/views.py
1 from django.shortcuts import render, redirect, HttpResponse 2 from django.http import StreamingHttpResponse, FileResponse 3 import json 4 import re 5 import requests 6 7 8 header = { 9 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 10 'accept-language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7', 11 'pragma': 'no-cache', 12 'upgrade-insecure-requests': '1', 13 'user-agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Mobile Safari/537.36' 14 } 15 16 17 def douyinurlpars(url, version=1): 18 url = re.findall('(https?://[^\s]+)', url)[0] 19 20 print(url) 21 res = requests.get(url, headers=header, allow_redirects=True).url 22 # print(requests.headers) 23 # 视频id 24 item_id = res.split('/')[5] 25 26 html_url = 'https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids=' + item_id 27 28 29 res2 = requests.get(html_url, headers=header).text 30 response_title = json.loads(res2)['item_list'][0]['desc'] 31 # print(response) 32 if version == 1: 33 34 # 无水印视频url 35 video_url = json.loads(res2)['item_list'][0]['video']['play_addr']['url_list'][0].replace('/playwm/', '/play/') 36 else: 37 # 有水印视频url 38 video_url = json.loads(res2)['item_list'][0]['video']['play_addr']['url_list'][0] 39 return video_url, response_title 40 41 42 def douyin(request): 43 if request.method == 'POST': 44 url = request.POST.get('url') 45 if not url: 46 return render(request, 'index.html', {'msg': '输入的链接地址不能为空!!!'}) 47 res_url, title = douyinurlpars(url) 48 # res_url = 'https://aweme.snssdk.com/aweme/v1/play/?video_id=v0200fg10000c3ourrbc77uf4e6l8s8g&ratio=720p&line=0' 49 # title = '很多事是科学无法解释的%诡异 %经典港剧' 50 51 # 将url 进行编码,这里是为了res.html中给后端get传参,因为url中有特殊字符& (最开始想用来着,后来download函数没用,所以这一步其实也用不到了) 52 date = res_url.replace('&', 'renew') 53 54 return render(request, 'res.html', {'url': res_url, 'title': title, 'quote_url': date}) 55 return render(request, 'index.html') 56 57 # 备注下,download func 暂时没用,如果有想用的自己研究下也行。小事儿。。。 58 def download(request): 59 60 head = { 61 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 62 'Accept-Encoding': 'gzip, deflate', 63 'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7', 64 'Cache-Control': 'max-age=0', 65 'Connection': 'keep-alive', 66 'Upgrade-Insecure-Requests': '1', 67 'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Mobile Safari/537.36', 68 } 69 70 quote_url = request.GET.get('quote_url') 71 # print(type(quote_url), str(quote_url)) 72 73 url = quote_url.replace('renew', '&') 74 file_name = request.GET.get('title') + '1.mp4' 75 # file_name = 'a.mp4' 76 print(quote_url) 77 print(url) 78 print(file_name) 79 # url = 'https://aweme.snssdk.com/aweme/v1/play/?video_id=v0200fg10000c3ourrbc77uf4e6l8s8g&ratio=720p&line=0' 80 81 # 文件迭代,减少内存压力 82 def generate(url): 83 r = requests.get(url, headers=head, stream=True) 84 for chunk in r.iter_content(chunk_size=512): 85 if chunk: 86 yield chunk 87 88 response = StreamingHttpResponse(generate(url)) 89 response['content_type'] = "application/octet-stream" 90 response['Content-Disposition'] = 'attachment; filename="{}"'.format(file_name) 91 return response
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>抖音解析</title> <meta name="viewport" content="width=device-width, initial-scale=1"/> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous"> </head> <body> <h1 class="text-center">抖音无水印视频解析</h1> <form class="form-horizontal" action="{% url 'app1:douyin' %}" method="post"> {% csrf_token %} <br> <div class="form-group form-group-lg"> <div> <input name="url" class="form-control input-lg text-center" type="text" id="formGroupInputLarge" placeholder="放入复制的链接,不用去除链接中的文字和符号"> <br> <button class="form-control btn btn-primary btn-lg">提交</button> </div> </div> {% if msg %} <div class="text-center alert alert-danger alert-dismissible " role="alert"> <strong>{{ msg }}</strong> </div> {% endif %} </form> <!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) --> <script src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js" integrity="sha384-nvAa0+6Qg9clwYCGGPpDQLVpLNn0fRaROjHqs13t4Ggj3Ez50XnGQqc/r8MhnRDZ" crossorigin="anonymous"></script> <!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 --> <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"></script> </body> </html>
res.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="referrer" content="no-referrer" /> <title>视频页</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous"> <style> html, body { background: #393D49; height: 100%; } </style> </head> <body> <div class="text-center"> <h3><a name="title">{{ title }}</a></h3> <!--<p class="lead"><a href="{{ url }}">查看视频</a></p>--> </div> <div class=" text-center"> <video width="240" height="420" controls="controls"> <source src="{{ url }}" type="video/mp4"/> </video> </div> <!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) --> <script src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js" integrity="sha384-nvAa0+6Qg9clwYCGGPpDQLVpLNn0fRaROjHqs13t4Ggj3Ez50XnGQqc/r8MhnRDZ" crossorigin="anonymous"></script> <!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 --> <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"></script> </body> </html>
备注
注意,用django写好后,自己部署完毕。这台机器尽量不要用固定的外网ip地址,抖音对固定的IP地址有做反扒。至于怎么每次运行时更换外网IP地址,有需要的可以留言,我们交流交流。