修改实现方法

This commit is contained in:
yezian 2024-07-22 15:24:28 +08:00
parent 44290b1108
commit 91a7a5bf3b
3 changed files with 129 additions and 36 deletions

11
api.py
View File

@ -1,18 +1,19 @@
from flask import Flask, request, jsonify
from qushuiyin import qushuiyin
from qushuiyin import clean_mask
app = Flask(__name__)
@app.route("/get_dy_urls", methods=["POST"])
async def get_dy_urls():
@app.route("/get_urls", methods=["POST"])
def get_urls():
data = request.get_json() # 从请求中获取JSON数据
if not data:
return jsonify({"error": "No data provided"}), 400
# 处理数据
dy_urls = await qushuiyin(data["share_url"])
return jsonify(dy_urls), 200
url = clean_mask(data["share_url"])
print(url)
return jsonify(url), 200
if __name__ == "__main__":

View File

@ -1,39 +1,131 @@
import asyncio
from f2.apps.douyin.utils import AwemeIdFetcher
from f2.utils.utils import extract_valid_urls
from f2.apps.douyin.handler import DouyinHandler
kwargs = {
"headers": {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0",
"Referer": "https://www.douyin.com/",
},
"cookie": "FORCE_LOGIN=%7B%22videoConsumedRemainSeconds%22%3A180%2C%22isForcePopClose%22%3A1%7D; UIFID_TEMP=96cd3b166f3029d7c1cc3f64582454ab8a83ff1f9e6d6689076dd47ef1dca5f83186b571ff21ff4bb6319242fd3a000958f84401be4ff7112aab5e1d0d28d225826c5cab4c0c98ad8e053a867536155b; passport_csrf_token=8cd8f40fd238dfc66726a9313bab7b43; passport_csrf_token_default=8cd8f40fd238dfc66726a9313bab7b43; strategyABtestKey=%221720775917.246%22; volume_info=%7B%22isUserMute%22%3Afalse%2C%22isMute%22%3Atrue%2C%22volume%22%3A0.5%7D; IsDouyinActive=false; UIFID=96cd3b166f3029d7c1cc3f64582454ab8a83ff1f9e6d6689076dd47ef1dca5f83186b571ff21ff4bb6319242fd3a000935cd9a29c945708e8dff5eac4d7162af456df1a101a167e1a053dd6804a055da1e54bcbc4da003151237a7ea7ff17ab16ecd680ca9dbb269d30e2dcf8b83e2dd3a615757a5b6b1b2a9f4cab94b0f01e64e80472791023d28c6086dd081454b6722c267408bb9fb23d9f9dd1afef82d04; __security_server_data_status=1; _bd_ticket_crypt_cookie=a2d6bc10b99e0ebe24f3b101dcdf8959; _bd_ticket_crypt_doamin=2; bd_ticket_guard_client_data=eyJiZC10aWNrZXQtZ3VhcmQtdmVyc2lvbiI6MiwiYmQtdGlja2V0LWd1YXJkLWl0ZXJhdGlvbi12ZXJzaW9uIjoxLCJiZC10aWNrZXQtZ3VhcmQtcmVlLXB1YmxpYy1rZXkiOiJCTkdmSW1QelhyYzdZdjNoczBsNVEyc3J5K0hWbFVURit6c2hXWUI3M0F0ckpURGN6eTlEa3hFa2hYck83MW1uMnVObUpmV3FOQllwWWQ4ZVpxWEdSNFk9IiwiYmQtdGlja2V0LWd1YXJkLXdlYi12ZXJzaW9uIjoxfQ%3D%3D; bd_ticket_guard_client_web_domain=2; biz_trace_id=b81688a4; home_can_add_dy_2_desktop=%221%22; n_mh=Hv1EJfXw0zYqU4nePlN0-RVMnIEWX6hsRuiqz9swB1g; odin_tt=517b4f71a98f5723cfb8702ea16e58a603fd74c3b0def5b3a0e9b7ad7f9107665aaa596b71780779ef7b186a9007a199; passport_assist_user=CjwaLaY1yUBd1BWBMaw9dw3dRtIhzeqTb55PAhaEKIp71exKOkVqHaXMD3h3jvzY8QUHeyefpHjoS36Wz5oaSgo8v2Hef5bG0COZ34nU_EzlMVDkAWO9QR155auuQIYTm4GbH7UkdJ1Mjp0jLIuQJFbb82AjYyyvyVCLwiJKELy51g0Yia_WVCABIgED-THeTQ%3D%3D; passport_auth_status=ae5e2fdc63086401ca880f6f7b5755a7%2C; passport_auth_status_ss=ae5e2fdc63086401ca880f6f7b5755a7%2C; publish_badge_show_info=%220%2C0%2C0%2C1720775946680%22; sessionid=f000d470c442a50b3053c21d630613e4; sessionid_ss=f000d470c442a50b3053c21d630613e4; sid_guard=f000d470c442a50b3053c21d630613e4%7C1720775948%7C5183997%7CTue%2C+10-Sep-2024+09%3A19%3A05+GMT; sid_tt=f000d470c442a50b3053c21d630613e4; sid_ucp_sso_v1=1.0.0-KDVmMGM5ODI2ODVmODJjZjFjZjE2NWM5YWU4ZmJkM2QyOTY1NjFhZWUKHwjant_X3AIQhurDtAYY7zEgDDDo17vUBTgGQPQHSAYaAmxmIiA4ZDU5MzVjNjU4MmE1NDNkODFkNzE1ZWQ4OGEyYmU5Yw; sid_ucp_v1=1.0.0-KGQzMzdiNTI0YTIxNTllZmU5YmQ0MjQ0ZGIxZmRmYTMwNDA2MGI4MjYKGQjant_X3AIQjOrDtAYY7zEgDDgGQPQHSAQaAmhsIiBmMDAwZDQ3MGM0NDJhNTBiMzA1M2MyMWQ2MzA2MTNlNA; ssid_ucp_sso_v1=1.0.0-KDVmMGM5ODI2ODVmODJjZjFjZjE2NWM5YWU4ZmJkM2QyOTY1NjFhZWUKHwjant_X3AIQhurDtAYY7zEgDDDo17vUBTgGQPQHSAYaAmxmIiA4ZDU5MzVjNjU4MmE1NDNkODFkNzE1ZWQ4OGEyYmU5Yw; ssid_ucp_v1=1.0.0-KGQzMzdiNTI0YTIxNTllZmU5YmQ0MjQ0ZGIxZmRmYTMwNDA2MGI4MjYKGQjant_X3AIQjOrDtAYY7zEgDDgGQPQHSAQaAmhsIiBmMDAwZDQ3MGM0NDJhNTBiMzA1M2MyMWQ2MzA2MTNlNA; sso_uid_tt=bb63fd08ff1688397ce405b1c5fb0501; sso_uid_tt_ss=bb63fd08ff1688397ce405b1c5fb0501; store-region=cn-sc; store-region-src=uid; stream_player_status_params=%22%7B%5C%22is_auto_play%5C%22%3A0%2C%5C%22is_full_screen%5C%22%3A0%2C%5C%22is_full_webscreen%5C%22%3A0%2C%5C%22is_mute%5C%22%3A1%2C%5C%22is_speed%5C%22%3A1%2C%5C%22is_visible%5C%22%3A0%7D%22; stream_recommend_feed_params=%22%7B%5C%22cookie_enabled%5C%22%3Atrue%2C%5C%22screen_width%5C%22%3A1440%2C%5C%22screen_height%5C%22%3A900%2C%5C%22browser_online%5C%22%3Atrue%2C%5C%22cpu_core_num%5C%22%3A8%2C%5C%22device_memory%5C%22%3A8%2C%5C%22downlink%5C%22%3A1.45%2C%5C%22effective_type%5C%22%3A%5C%223g%5C%22%2C%5C%22round_trip_time%5C%22%3A300%7D%22; toutiao_sso_user=8d5935c6582a543d81d715ed88a2be9c; toutiao_sso_user_ss=8d5935c6582a543d81d715ed88a2be9c; ttwid=1%7CburBMWkF_7QUTgeJnTOmvWfuMru9HzMGR94GSk2PbOM%7C1720775913%7C88e448a4fb798a93ac31cbb4f11533a9d8edd1314f03fe7e7a83991a9ede1ebc; uid_tt=4c93500137dae9741192d37d2e9f7600; uid_tt_ss=4c93500137dae9741192d37d2e9f7600; __ac_nonce=06690f4e900408e95cafa; __ac_signature=_02B4Z6wo00f01w0O85QAAIDAX.HTjoG5QxsNLvcAAKXdfd; device_web_cpu_core=8; device_web_memory_size=8; fpk1=U2FsdGVkX19QlXys0TN0qt/rloGcQnCb+pMhwVraOEscCHNEiGn9DqCC4NEHxt0qo36hgXj1vV9vV1xZZR3/eA==; fpk2=10f9287deaf609ee36fb37783f2b89c0; s_v_web_id=verify_lyihjt5b_W9CsZ62G_SzZ4_4kS2_Apei_7Cez2wak0XW2; =douyin.com; csrf_session_id=75739f2b4ce4064529cf3ad2c566e80e; dy_sheight=900; dy_swidth=1440; xg_device_score=6.719622045696811; passport_fe_beating_status=false",
"proxies": {"http://": None, "https://": None},
}
import re
import json
import requests
async def get_video_id(share_url):
raw_urls = [
share_url,
]
class Video:
def pipixia(self, url):
loc = requests.head(url).headers.get("Location")
id_match = re.search(r"item/(.*)\?", loc)
if id_match:
item_id = id_match.group(1)
response = requests.get(
f"https://is.snssdk.com/bds/cell/detail/?cell_type=1&aid=1319&app_name=super&cell_id={item_id}"
)
arr = response.json()
video_url = arr["data"]["data"]["item"]["origin_video_download"][
"url_list"
][0]["url"]
if video_url:
return {
"code": 200,
"data": {
"author": arr["data"]["data"]["item"]["author"]["name"],
"avatar": arr["data"]["data"]["item"]["author"]["avatar"][
"download_list"
][0]["url"],
"time": arr["data"]["data"]["display_time"],
"title": arr["data"]["data"]["item"]["content"],
"cover": arr["data"]["data"]["item"]["cover"]["url_list"][0][
"url"
],
"url": video_url,
},
}
return None
# 提取有效URL
urls = extract_valid_urls(raw_urls)
def douyin(self, url):
# Extract ID from URL
id_match = self.extract_id(url)
if not id_match:
return {"code": 400, "msg": "Unable to parse video ID"}
# 对于URL列表
return await AwemeIdFetcher.get_all_aweme_id(urls)
video_id = id_match
# Construct request headers
headers = {
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1 Edg/122.0.0.0"
}
# Send request to get video info
response = requests.get(
f"https://www.iesdouyin.com/share/video/{video_id}", headers=headers
)
pattern = r"window\._ROUTER_DATA\s*=\s*(.*?)</script>"
matches = re.search(pattern, response.text, re.DOTALL)
if not matches:
return {"code": 201, "msg": "Parsing failed"}
video_info = json.loads(matches.group(1).strip())
if "loaderData" not in video_info:
return {"code": 201, "msg": "Parsing failed"}
video_res_url = video_info["loaderData"]["video_(id)/page"]["videoInfoRes"][
"item_list"
][0]["video"]["play_addr"]["url_list"][0]
video_res_url = video_res_url.replace("playwm", "play")
return {
"code": 200,
"msg": "Parsing successful",
"data": {
"author": video_info["loaderData"]["video_(id)/page"]["videoInfoRes"][
"item_list"
][0]["author"]["nickname"],
"uid": video_info["loaderData"]["video_(id)/page"]["videoInfoRes"][
"item_list"
][0]["author"]["unique_id"],
"avatar": video_info["loaderData"]["video_(id)/page"]["videoInfoRes"][
"item_list"
][0]["author"]["avatar_medium"]["url_list"][0],
"like": video_info["loaderData"]["video_(id)/page"]["videoInfoRes"][
"item_list"
][0]["statistics"]["digg_count"],
"time": video_info["loaderData"]["video_(id)/page"]["videoInfoRes"][
"item_list"
][0]["create_time"],
"title": video_info["loaderData"]["video_(id)/page"]["videoInfoRes"][
"item_list"
][0]["desc"],
"cover": video_info["loaderData"]["video_(id)/page"]["videoInfoRes"][
"item_list"
][0]["video"]["cover"]["url_list"][0],
"url": video_res_url,
"music": {
"author": video_info["loaderData"]["video_(id)/page"][
"videoInfoRes"
]["item_list"][0]["music"]["author"],
"avatar": video_info["loaderData"]["video_(id)/page"][
"videoInfoRes"
]["item_list"][0]["music"]["cover_large"]["url_list"][0],
},
},
}
def extract_id(self, url):
try:
response = requests.head(url, allow_redirects=True)
final_url = response.url
id_match = re.search(r"/(\d+)", final_url)
return id_match.group(1) if id_match else None
except Exception as e:
return None
async def qushuiyin(share_url):
aweme_id = await get_video_id(share_url)
video = await DouyinHandler(kwargs).fetch_one_video(aweme_id=aweme_id[0])
video_info = video._to_dict()
cover_url = video_info["cover"]
music_url = video_info["music_play_url"]
video_urls = video_info["video_play_addr"]
return {"cover_url": cover_url, "music_url": music_url, "video_urls": video_urls}
def get_raw_url(share_url):
regex = r"http[s]?://[\w.]+[\w\/]*[\w.]*\??[\w=&:\-\+\%]*[/]*"
match = re.search(regex, share_url)
if match:
url = match.group(0)
return url
else:
return None
if __name__ == "__main__":
print(asyncio.run(qushuiyin()))
def clean_mask(share_url):
raw_url = get_raw_url(share_url)
video = Video()
result = video.douyin(raw_url)
print(result)
return result

Binary file not shown.