import configparser
import execjs
import requests
import time
import json
import os
import sys
import random
import uuid
import base64
from datetime import datetime
from http.cookiejar import LWPCookieJar
# 设备信息生成器(内置)
class DeviceSimulator:
@staticmethod
def generate_device_info():
"""生成模拟设备信息"""
brands = ["Xiaomi", "Huawei", "OPPO", "vivo", "Apple", "Samsung"]
models = {
"Xiaomi": ["Mi 11", "Redmi Note 10", "Mi 10 Pro", "Redmi K40"],
"Huawei": ["P40 Pro", "Mate 40", "Nova 8", "P30"],
"OPPO": ["Reno 5", "Find X3", "A74", "A94"],
"vivo": ["X60", "V21", "Y72", "Y20s"],
"Apple": ["iPhone 13", "iPhone 12", "iPhone 11", "iPhone SE"],
"Samsung": ["Galaxy S21", "Galaxy Note20", "Galaxy A52", "Galaxy Z Fold2"]
}
brand = random.choice(brands)
model = random.choice(models[brand])
return {
"device_id": str(uuid.uuid4()).replace('-', ''),
"device_brand": brand,
"device_model": model,
"device_os": "Android" if brand != "Apple" else "iOS",
"os_version": f"{random.randint(10, 13)}.{random.randint(0, 6)}.{random.randint(0, 9)}",
"app_version": f"{random.randint(9, 12)}.{random.randint(0, 5)}.{random.randint(0, 50)}",
"network_type": random.choice(["WIFI", "4G", "5G"]),
"screen_width": str(random.randint(1080, 1440)),
"screen_height": str(random.randint(1920, 3120)),
"carrier": random.choice(["China Mobile", "China Telecom", "China Unicom"]),
"language": "zh_CN",
"timezone": "Asia/Shanghai"
}
# 快手登录工具(完整实现)
class KuaishouLogin:
def __init__(self, config_path='config.ini'):
self.config = configparser.ConfigParser()
self.config_path = config_path
# 如果配置文件不存在,创建默认配置
if not os.path.exists(config_path):
self.create_default_config()
self.config.read(config_path)
self.session = requests.Session()
# 设置Cookie存储
self.session.cookies = LWPCookieJar('kuaishou_cookies.txt')
if os.path.exists('kuaishou_cookies.txt'):
try:
self.session.cookies.load(ignore_discard=True)
print("检测到已保存的Cookie")
except:
pass
# 一次性生成设备信息并保持一致性
self.device_info = DeviceSimulator.generate_device_info()
# 正确格式化设备信息头
self.headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36",
"X-Device-Info": json.dumps(self.device_info, separators=(',', ':'),
"Content-Type": "application/json"
}
# 加载JS加密环境
self.js_ctx = self.create_js_context()
def create_default_config(self):
"""创建默认配置文件"""
config = configparser.ConfigParser()
config['API'] = {
'token_url': 'https://www.kuaishou.com/rest/rpc/login/getToken',
'login_url': 'https://www.kuaishou.com/rest/rpc/login/loginWithPassword',
'profile_url': 'https://www.kuaishou.com/graphql'
}
config['ACCOUNT'] = {
'username': 'your_phone_number',
'password': 'your_password'
}
with open(self.config_path, 'w', encoding='utf-8') as configfile:
config.write(configfile)
print(f"已创建默认配置文件 {self.config_path},请填写您的账号信息")
def create_js_context(self):
"""创建JS执行环境(内置加密函数)"""
js_code = """
// 基础加密函数(实际项目中应替换为真实算法)
function encryptPassword(password) {
// 简单示例:Base64编码 + 反转
return btoa(password.split('').reverse().join(''));
}
// 签名生成函数(实际项目中应替换为真实算法)
function generateSignature(url, dataString, timestamp) {
// 简单示例:组合数据并计算简单哈希
const rawString = url + dataString + timestamp;
let hash = 0;
for (let i = 0; i < rawString.length; i++) {
const char = rawString.charCodeAt(i);
hash = (hash << 5) - hash + char;
hash |= 0; // 转换为32位整数
}
return {
"X-Signature": "sign_" + (hash >>> 0).toString(16),
"X-Timestamp": timestamp.toString(),
"X-Request-ID": "req_" + Math.random().toString(36).substr(2, 10)
};
}
"""
return execjs.compile(js_code)
def get_token(self):
"""获取动态令牌"""
try:
print("正在获取登录令牌...")
resp = self.session.get(
self.config['API']['token_url'],
headers=self.headers,
timeout=10
)
resp.raise_for_status() # 检查HTTP错误
token_data = resp.json()
if token_data.get('result') == 1:
token = token_data['token']
print(f"获取Token成功: {token[:10]}...")
return token
else:
error_msg = token_data.get('error_msg', '未知错误')
raise ValueError(f"Token API错误: {error_msg}")
except Exception as e:
print(f"获取Token失败: {str(e)}")
return None
def encrypt_password(self, pwd):
"""JS加密密码"""
try:
return self.js_ctx.call("encryptPassword", pwd)
except Exception as e:
print(f"密码加密失败: {str(e)}")
return pwd # 失败时使用原始密码(实际不可行)
def generate_headers(self, url, data):
"""生成签名请求头"""
# 获取当前时间戳
timestamp = int(time.time() * 1000) # 毫秒级时间戳
try:
# 调用JS生成签名
signature_headers = self.js_ctx.call(
"generateSignature",
url,
json.dumps(data, separators=(',', ':')), # 保持JSON紧凑格式
timestamp
)
# 合并基础头
return {**self.headers, **signature_headers}
except Exception as e:
print(f"生成签名失败: {str(e)}")
return self.headers
def login(self):
"""执行登录流程"""
# 获取token(失败时退出)
token = self.get_token()
if not token:
print("无法获取Token,登录终止")
return False
# 准备登录数据
username = self.config['ACCOUNT']['username']
password = self.config['ACCOUNT']['password']
login_data = {
"mobile": username,
"password": self.encrypt_password(password),
"token": token,
"device_id": self.device_info['device_id'] # 使用初始化时的设备ID
}
print(f"使用账号 {username} 尝试登录...")
# 生成带签名的请求头
signed_headers = self.generate_headers(
self.config['API']['login_url'],
login_data
)
try:
# 发送登录请求
print("正在发送登录请求...")
response = self.session.post(
self.config['API']['login_url'],
json=login_data,
headers=signed_headers,
timeout=15
)
response.raise_for_status()
# 解析响应
login_result = response.json()
if login_result.get('result') == 1:
user_id = login_result.get('user_id', '未知')
print(f"登录成功! 用户ID: {user_id}")
# 保存Cookie
self.session.cookies.save(ignore_discard=True)
return True
else:
error_msg = login_result.get('error_msg', '未知错误')
error_code = login_result.get('error_code', '未知')
print(f"登录失败: {error_msg} (代码: {error_code})")
return False
except Exception as e:
print(f"登录请求异常: {str(e)}")
return False
def get_user_profile(self):
"""获取用户资料"""
if not self.is_logged_in():
print("需要先登录...")
if not self.login():
return None
try:
print("正在获取用户资料...")
profile_url = self.config['API']['profile_url']
# 构造用户资料查询
query = {
"operationName": "userProfileQuery",
"variables": {"userId": ""},
"query": "query userProfileQuery($userId: String) { userProfile(userId: $userId) { userId userName avatar userBio followerCount followingCount } }"
}
response = self.session.post(
profile_url,
json=query,
headers=self.headers,
timeout=10
)
response.raise_for_status()
profile_data = response.json()
if 'data' in profile_data and 'userProfile' in profile_data['data']:
return profile_data['data']['userProfile']
else:
errors = profile_data.get('errors', [{'message': '未知错误'}])
print(f"获取用户资料失败: {errors[0]['message']}")
return None
except Exception as e:
print(f"获取用户资料异常: {str(e)}")
return None
def is_logged_in(self):
"""检查是否已登录"""
# 检查Cookie是否有效
return any(cookie.name == 'sessionid' for cookie in self.session.cookies)
def clear_session(self):
"""清除会话"""
if os.path.exists('kuaishou_cookies.txt'):
os.remove('kuaishou_cookies.txt')
self.session.cookies = LWPCookieJar()
print("会话已清除")
# 用户界面
class KuaishouLoginApp:
def __init__(self):
self.login_tool = KuaishouLogin()
self.current_user = None
def print_banner(self):
"""打印欢迎横幅"""
print("\n" + "=" * 50)
print("快手登录工具 v1.0")
print("=" * 50)
print(f"设备ID: {self.login_tool.device_info['device_id']}")
print(f"设备型号: {self.login_tool.device_info['device_brand']} {self.login_tool.device_info['device_model']}")
print("=" * 50)
def edit_config(self):
"""编辑配置文件"""
try:
# 读取当前配置
username = self.login_tool.config['ACCOUNT']['username']
password = self.login_tool.config['ACCOUNT']['password']
print("\n当前账号配置:")
print(f"1. 用户名: {username}")
print(f"2. 密码: {'*' * len(password)}")
print("3. 返回主菜单")
choice = input("请选择要修改的项 (1-3): ").strip()
if choice == '1':
new_username = input("请输入新用户名 (手机号): ").strip()
if new_username:
self.login_tool.config['ACCOUNT']['username'] = new_username
with open(self.login_tool.config_path, 'w') as configfile:
self.login_tool.config.write(configfile)
print("用户名已更新!")
else:
print("用户名不能为空")
elif choice == '2':
new_password = input("请输入新密码: ").strip()
if new_password:
self.login_tool.config['ACCOUNT']['password'] = new_password
with open(self.login_tool.config_path, 'w') as configfile:
self.login_tool.config.write(configfile)
print("密码已更新!")
else:
print("密码不能为空")
except Exception as e:
print(f"配置更新失败: {str(e)}")
def run(self):
"""运行主程序"""
self.print_banner()
# 主菜单
while True:
print("\n主菜单:")
print("1. 登录账号")
print("2. 获取用户资料")
print("3. 账号设置")
print("4. 清除会话")
print("5. 退出程序")
choice = input("请输入选项 (1-5): ").strip()
if choice == '1':
if self.login_tool.login():
self.current_user = self.login_tool.config['ACCOUNT']['username']
else:
self.current_user = None
elif choice == '2':
profile = self.login_tool.get_user_profile()
if profile:
print("\n用户资料:")
print(f"用户ID: {profile.get('userId', '未知')}")
print(f"用户名: {profile.get('userName', '未知')}")
print(f"头像: {profile.get('avatar', '无')[:30]}...")
print(f"简介: {profile.get('userBio', '无')}")
print(f"粉丝数: {profile.get('followerCount', '未知')}")
print(f"关注数: {profile.get('followingCount', '未知')}")
else:
print("获取用户资料失败")
elif choice == '3':
self.edit_config()
elif choice == '4':
self.login_tool.clear_session()
self.current_user = None
print("会话已清除")
elif choice == '5':
print("感谢使用,再见!")
break
else:
print("无效的选项,请重新输入")
# 程序入口
if __name__ == "__main__":
try:
app = KuaishouLoginApp()
app.run()
except KeyboardInterrupt:
print("\n程序已中断")
sys.exit(0)
except Exception as e:
print(f"程序发生错误: {str(e)}")
sys.exit(1)
帮我用以上的代码生成软件
最新发布