241 lines
8.6 KiB
Python
241 lines
8.6 KiB
Python
import time
|
|
import json
|
|
import redis
|
|
import requests
|
|
import urllib3
|
|
from requests.adapters import HTTPAdapter
|
|
from urllib3.util.retry import Retry
|
|
from typing import Optional, Dict, Any, Union
|
|
|
|
class HttpClient:
|
|
def __init__(self, max_retries: int = 3, backoff_factor: float = 0.5):
|
|
self.session = requests.Session()
|
|
# 配置重试策略
|
|
retry_strategy = Retry(
|
|
total=max_retries,
|
|
backoff_factor=backoff_factor,
|
|
status_forcelist=[500, 502, 503, 504, 429]
|
|
)
|
|
|
|
adapter = HTTPAdapter(max_retries=retry_strategy)
|
|
self.session.mount("http://", adapter)
|
|
self.session.mount("https://", adapter)
|
|
|
|
def request(self,
|
|
method: str,
|
|
url: str,
|
|
headers: Optional[Dict] = None,
|
|
params: Optional[Dict] = None,
|
|
data: Optional[Union[Dict, str]] = None,
|
|
cookies: Optional[Dict] = None,
|
|
allow_redirects: bool = True,
|
|
timeout: int = 30,
|
|
**kwargs) -> requests.Response:
|
|
try:
|
|
response = self.session.request(
|
|
method=method,
|
|
url=url,
|
|
headers=headers,
|
|
params=params,
|
|
data=data,
|
|
cookies=cookies,
|
|
allow_redirects=allow_redirects,
|
|
timeout=timeout,
|
|
**kwargs
|
|
)
|
|
response.raise_for_status()
|
|
return response
|
|
except requests.exceptions.RequestException as e:
|
|
print(f"请求失败: {url}, 错误: {str(e)}")
|
|
raise
|
|
|
|
def get(self, url: str, **kwargs) -> requests.Response:
|
|
return self.request("GET", url, **kwargs)
|
|
|
|
def post(self, url: str, **kwargs) -> requests.Response:
|
|
return self.request("POST", url, **kwargs)
|
|
|
|
# 创建全局的 HTTP 客户端实例
|
|
http_client = HttpClient()
|
|
|
|
_REDIS_CONF = {
|
|
"host": "192.144.230.75",
|
|
"port": 6379,
|
|
"password": "qwert@$123!&",
|
|
"decode_responses": True,
|
|
"db": 1,
|
|
}
|
|
|
|
def save_report_token(key_name: str, json_data: dict):
|
|
r = redis.Redis(**_REDIS_CONF)
|
|
key = key_name
|
|
json_str = json.dumps(json_data, ensure_ascii=False)
|
|
r.set(key, json_str)
|
|
print(f"已在 Redis(DB {_REDIS_CONF['db']}) 中写入 key -> {key}")
|
|
|
|
|
|
def get_report_token(key_name: str):
|
|
r = redis.Redis(**_REDIS_CONF)
|
|
key = key_name
|
|
json_str = r.get(key)
|
|
if not json_str:
|
|
return None
|
|
return json.loads(json_str)
|
|
|
|
|
|
def login():
|
|
try:
|
|
headers = {
|
|
"Accept": "*/*",
|
|
"Accept-Language": "zh-CN,zh;q=0.9",
|
|
"Cache-Control": "no-cache",
|
|
"Connection": "keep-alive",
|
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
"Origin": "https://www.dailymotion.com",
|
|
"Pragma": "no-cache",
|
|
"Referer": "https://www.dailymotion.com/",
|
|
"Sec-Fetch-Dest": "empty",
|
|
"Sec-Fetch-Mode": "cors",
|
|
"Sec-Fetch-Site": "same-site",
|
|
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0",
|
|
"sec-ch-ua": "\"Chromium\";v=\"136\", \"Microsoft Edge\";v=\"136\", \"Not.A/Brand\";v=\"99\"",
|
|
"sec-ch-ua-mobile": "?0",
|
|
"sec-ch-ua-platform": "\"Windows\""
|
|
}
|
|
url = "https://graphql.api.dailymotion.com/oauth/token"
|
|
data = {
|
|
"client_id": "f1a362d288c1b98099c7",
|
|
"client_secret": "eea605b96e01c796ff369935357eca920c5da4c5",
|
|
"grant_type": "password",
|
|
"username": "copyright@qiyi.com",
|
|
"password": "ppsIQIYI2018@",
|
|
"scope": "userinfo,email,manage_subscriptions,manage_history,manage_likes,manage_playlists,manage_videos",
|
|
"version": "2",
|
|
"traffic_segment": "962042",
|
|
"visitor_id": "359703fb-66c2-43d2-bd0d-b1cac9c7ae8a"
|
|
}
|
|
response = http_client.post(url, headers=headers, data=data)
|
|
data = {
|
|
"update_time": int(time.time()),
|
|
"username": "copyright@qiyi.com",
|
|
"password": "ppsIQIYI2018@",
|
|
"token": response.json()
|
|
}
|
|
save_report_token('token', data)
|
|
return data
|
|
except Exception as e:
|
|
print(f"登录失败: {str(e)}")
|
|
raise
|
|
|
|
def get_cookies(access_token: str, refresh_token: str):
|
|
try:
|
|
cookies = {
|
|
"access_token": access_token,
|
|
"refresh_token": refresh_token,
|
|
}
|
|
url = "https://www.dailymotion.com/cookie/refresh_token"
|
|
http_client.post(url, cookies=cookies, allow_redirects=True)
|
|
except Exception as e:
|
|
print(f"刷新 cookie 失败: {str(e)}")
|
|
raise
|
|
|
|
def get_cookies1(access_token: str, refresh_token: str):
|
|
"""302 跳转"""
|
|
try:
|
|
cookies = {
|
|
"access_token": access_token,
|
|
"refresh_token": refresh_token,
|
|
}
|
|
url = "https://www.dailymotion.com/zendesk"
|
|
params = {
|
|
"return_to": "https://faq.dailymotion.com/hc/en-us/requests/new",
|
|
"timestamp": str(int(time.time())),
|
|
}
|
|
response = http_client.get(url, cookies=cookies, params=params, allow_redirects=True)
|
|
cookies_dict = {"update_time": int(time.time()), "cookies": dict(http_client.session.cookies)}
|
|
save_report_token('cookies', cookies_dict)
|
|
return cookies_dict
|
|
except Exception as e:
|
|
print(f"获取 cookies 失败: {str(e)}")
|
|
raise
|
|
|
|
def get_csrftoken():
|
|
try:
|
|
url = "https://faq.dailymotion.com/hc/api/internal/csrf_token.json"
|
|
response = http_client.get(url)
|
|
data = {"update_time": int(time.time()), "csrf_token": response.json()}
|
|
save_report_token('csrf_token', data)
|
|
return data
|
|
except Exception as e:
|
|
print(f"获取 CSRF token 失败: {str(e)}")
|
|
raise
|
|
|
|
def report(csrf_token:str, cookies:dict):
|
|
try:
|
|
headers = {
|
|
"Accept": "*/*",
|
|
"Accept-Language": "zh-CN,zh;q=0.9",
|
|
"Cache-Control": "no-cache",
|
|
"Connection": "keep-alive",
|
|
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
|
"Origin": "https://faq.dailymotion.com",
|
|
"Pragma": "no-cache",
|
|
"Referer": "https://faq.dailymotion.com/hc/en-us/requests/new",
|
|
"Sec-Fetch-Dest": "empty",
|
|
"Sec-Fetch-Mode": "cors",
|
|
"Sec-Fetch-Site": "same-origin",
|
|
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0",
|
|
"sec-ch-ua": "\"Chromium\";v=\"136\", \"Microsoft Edge\";v=\"136\", \"Not.A/Brand\";v=\"99\"",
|
|
"sec-ch-ua-mobile": "?0",
|
|
"sec-ch-ua-platform": "\"Windows\"",
|
|
"X-CSRF-Token": csrf_token
|
|
}
|
|
data = {
|
|
"request[subject]": "版权投诉",
|
|
"request[description]": "请删除侵权视频",
|
|
"request[email]": "copyright@qiyi.com",
|
|
"request[ticket_form_id]": "360000717219"
|
|
}
|
|
response = http_client.post('https://faq.dailymotion.com/hc/en-us/requests',
|
|
cookies=cookies,
|
|
headers=headers,
|
|
data=data)
|
|
return response.status_code == 200
|
|
except Exception as e:
|
|
print(f"提交报告失败: {str(e)}")
|
|
raise
|
|
|
|
def prepare_data():
|
|
try:
|
|
token = get_report_token('token')
|
|
cookies = get_report_token('cookies')
|
|
csrf_token = get_report_token('csrf_token')
|
|
|
|
min_update_time = min(d.get('update_time', 0) for d in (token, cookies, csrf_token) if d)
|
|
if not min_update_time or min_update_time + (24 * 60 * 60) < time.time():
|
|
token = login()
|
|
if not token:
|
|
raise Exception("登录失败")
|
|
|
|
access_token = token['token']['access_token']
|
|
refresh_token = token['token']['refresh_token']
|
|
|
|
get_cookies(access_token, refresh_token)
|
|
cookies = get_cookies1(access_token, refresh_token)
|
|
csrf_token = get_csrftoken()
|
|
|
|
if not all([cookies, csrf_token]):
|
|
raise Exception("获取 cookies 或 csrf_token 失败")
|
|
|
|
if not all([token, cookies, csrf_token]):
|
|
raise Exception("获取令牌失败")
|
|
|
|
success = report(csrf_token['csrf_token']['current_session']['csrf_token'], cookies['cookies'])
|
|
if not success:
|
|
raise Exception("提交投诉失败")
|
|
|
|
except Exception as e:
|
|
print(f"处理数据失败: {str(e)}")
|
|
raise
|
|
|