alidrive_checkin.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. #!/usr/bin/env python
  2. # -*- encoding: utf-8 -*-
  3. '''
  4. @Contact : liuyuqi.gov@msn.cn
  5. @Time : 2025/09/30 22:31:02
  6. @License : Copyright © 2017-2022 liuyuqi. All Rights Reserved.
  7. @Desc : alidriver_checkin crawler class
  8. '''
  9. import requests
  10. import pickle
  11. import os
  12. # 数据目录
  13. DATA_DIR = 'data'
  14. # 确保data目录存在
  15. if not os.path.exists(DATA_DIR):
  16. os.makedirs(DATA_DIR)
  17. class AliDriverCheckin:
  18. _host = 'https://www.aliyundrive.com'
  19. headers = {
  20. 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36',
  21. 'Accept': 'application/json',
  22. 'Content-Type': 'application/json',
  23. 'Origin': 'https://lycheeshare.com',
  24. 'Referer': 'https://lycheeshare.com/profile'
  25. }
  26. def generate_account(self, number:int=20):
  27. """Generate random account credentials.
  28. :param int number: Number of accounts to generate.
  29. :return: A tuple of (username, password, email).
  30. """
  31. import random
  32. import string
  33. # 常用单词和拼音列表
  34. words = ['sky', 'sun', 'moon', 'star', 'cloud', 'rain', 'wind', 'fire', 'water', 'earth',
  35. 'cat', 'dog', 'bird', 'fish', 'tiger', 'lion', 'bear', 'wolf', 'fox', 'deer',
  36. 'blue', 'red', 'green', 'black', 'white', 'gold', 'silver', 'purple', 'orange',
  37. 'happy', 'lucky', 'smart', 'cool', 'fast', 'strong', 'brave', 'super', 'magic',
  38. 'wang', 'li', 'zhang', 'liu', 'chen', 'yang', 'huang', 'zhao', 'wu', 'zhou',
  39. 'xiao', 'ming', 'hong', 'wei', 'jie', 'lei', 'tao', 'jun', 'feng', 'long']
  40. if number < 1:
  41. number = 1
  42. if number > 100:
  43. number = 100
  44. accounts = []
  45. for _ in range(number):
  46. # 组合单词/拼音和数字
  47. # word1 = random.choice(words)
  48. # word2 = random.choice(words)
  49. num = random.randint(100000000, 999999999)
  50. username = f"1{num}"
  51. # 密码:字母+数字组合,8-12位
  52. password_len = random.randint(8, 12)
  53. password = ''.join(random.choices(string.ascii_letters + string.digits, k=password_len))
  54. email = f"{username}@qq.com"
  55. accounts.append((username, email, password))
  56. with open(os.path.join(DATA_DIR, 'generate_account.txt'), 'w') as f:
  57. for account in accounts:
  58. f.write(','.join(account) + '\n')
  59. return accounts
  60. def __init__(self, email, password):
  61. self.email = email
  62. self.password = password
  63. self.session = requests.Session()
  64. self.session.headers.update(self.headers)
  65. self.token = None
  66. self.cookie_file = os.path.join(DATA_DIR, "cookie" ,f'cookies_{email.replace("@", "_at_").replace(".", "_")}.pkl')
  67. self.x_client_id = self._get_x_client_id() or 'mgn9qt0o-3d5ecd48cff583a6'
  68. def get_captcha(self):
  69. """Send verification code to email."""
  70. return True, "000000"
  71. def register(self, username, code):
  72. """Register a new account with verification code."""
  73. url = f'{self._host}/api/auth/register'
  74. data = {
  75. 'email': self.email,
  76. 'password': self.password,
  77. 'username': username,
  78. 'code': code
  79. }
  80. try:
  81. response = self.session.post(url, json=data)
  82. result = response.json()
  83. if response.status_code == 200 and result.get('code') == 0:
  84. print(f"注册成功: {username}")
  85. return True, result
  86. else:
  87. print(f"注册失败: {result}")
  88. return False, result
  89. except Exception as e:
  90. print(f"注册异常: {e}")
  91. return False, str(e)
  92. def login(self):
  93. """Login to account and save auth token."""
  94. url = f'{self._host}/api/auth/login'
  95. data = {
  96. 'email': self.email,
  97. 'password': self.password
  98. }
  99. try:
  100. response = self.session.post(url, json=data)
  101. result = response.json()
  102. if response.status_code == 200 and result.get('code') == 0:
  103. # Token在 data.token 中
  104. if 'data' in result and 'token' in result['data']:
  105. self.token = result['data']['token']
  106. # 设置 auth-token cookie
  107. self.session.cookies.set('auth-token', self.token, domain='lycheeshare.com', path='/')
  108. self.session.headers.update({'Authorization': f'Bearer {self.token}'})
  109. # Save cookies to file
  110. self.save_cookies()
  111. print(f"登录成功: {self.email}")
  112. return True, result
  113. print(f"登录失败: {result}")
  114. return False, result
  115. except Exception as e:
  116. print(f"登录异常: {e}")
  117. return False, str(e)
  118. def _get_x_client_id(self):
  119. """Fetch x-client-id from the homepage.
  120. 访问:https://lycheeshare.com ,在源码中查找类似如下内容:
  121. window.__CLIENT_ID__ = 'mgn9qt0o-3d5ecd48cff583a6';
  122. """
  123. try:
  124. response = self.session.get(self._host)
  125. if response.status_code == 200:
  126. import re
  127. match = re.search(r"window\.__CLIENT_ID__\s*=\s*'([a-z0-9\-]+)'", response.text)
  128. if match:
  129. print(f"获取 x-client-id: {match.group(1)}")
  130. return match.group(1)
  131. print("无法获取 x-client-id")
  132. return None
  133. except Exception as e:
  134. print(f"获取 x-client-id 异常: {e}")
  135. return None
  136. def checkin(self):
  137. """Daily check-in to earn rewards."""
  138. url = f'{self._host}/api/user/checkin'
  139. try:
  140. self.session.headers.update({'x-client-id': self.x_client_id})
  141. response = self.session.post(url)
  142. result = response.json()
  143. if response.status_code == 200 and result.get('code') == 0:
  144. print(f"签到成功: {self.email} - {result.get('message', '')}")
  145. return True, result
  146. else:
  147. print(f"签到失败: {self.email} - {result}")
  148. return False, result
  149. except Exception as e:
  150. print(f"签到异常: {e}")
  151. return False, str(e)
  152. def reset_token(self):
  153. """Reset API token if get token fails."""
  154. url = f'{self._host}/api/user/reset-api-token'
  155. try:
  156. response = self.session.post(url)
  157. result = response.json()
  158. if response.status_code == 200 and result.get('code') == 0:
  159. print(f"重置Token成功: {self.email}")
  160. return True, result
  161. else:
  162. print(f"重置Token失败: {result}")
  163. return False, result
  164. except Exception as e:
  165. print(f"重置Token异常: {e}")
  166. return False, str(e)
  167. def get_token(self):
  168. """Get API token for the account. If fails, reset and try again."""
  169. url = f'{self._host}/api/user/get-api-token'
  170. try:
  171. response = self.session.get(url)
  172. result = response.json()
  173. if response.status_code == 200 and result.get('code') == 0:
  174. api_token = None
  175. if 'data' in result:
  176. api_token = result['data'].get('token') or result['data'].get('api_token')
  177. if api_token:
  178. print(f"获取Token成功: {self.email}")
  179. print(f"API Token: {api_token}")
  180. # Save to file
  181. with open(os.path.join(DATA_DIR, 'api_tokens.txt'), 'a') as f:
  182. f.write(f"{self.email},{api_token}\n")
  183. return True, result
  184. else:
  185. # Token为空,尝试重置
  186. print(f"Token为空,尝试重置Token: {self.email}")
  187. success, reset_result = self.reset_token()
  188. if success:
  189. # 重置成功后再次获取
  190. import time
  191. time.sleep(1)
  192. response = self.session.get(url)
  193. result = response.json()
  194. if response.status_code == 200 and result.get('code') == 0:
  195. if 'data' in result:
  196. api_token = result['data'].get('token') or result['data'].get('api_token')
  197. if api_token:
  198. print(f"重置后获取Token成功: {self.email}")
  199. print(f"API Token: {api_token}")
  200. with open(os.path.join(DATA_DIR, 'api_tokens.txt'), 'a') as f:
  201. f.write(f"{self.email},{api_token}\n")
  202. return True, result
  203. return False, result
  204. else:
  205. # 如果获取失败,尝试重置token
  206. print(f"获取Token失败,尝试重置Token: {self.email}")
  207. success, reset_result = self.reset_token()
  208. if success:
  209. # 重置成功后再次获取
  210. import time
  211. time.sleep(1)
  212. response = self.session.get(url)
  213. result = response.json()
  214. if response.status_code == 200 and result.get('code') == 0:
  215. if 'data' in result:
  216. api_token = result['data'].get('token') or result['data'].get('api_token')
  217. if api_token:
  218. print(f"重置后获取Token成功: {self.email}")
  219. print(f"API Token: {api_token}")
  220. with open(os.path.join(DATA_DIR, 'api_tokens.txt'), 'a') as f:
  221. f.write(f"{self.email},{api_token}\n")
  222. return True, result
  223. return False, result
  224. except Exception as e:
  225. print(f"获取Token异常: {e}")
  226. return False, str(e)
  227. def get_credit(self):
  228. """查询账户额度信息"""
  229. # 确保有有效会话
  230. try:
  231. self.session.get(f'{self._host}/profile')
  232. except:
  233. pass
  234. url = f'{self._host}/api/user/credit-bundles'
  235. try:
  236. response = self.session.get(url)
  237. result = response.json()
  238. if response.status_code == 200 and result.get('code') == 0:
  239. if 'data' in result:
  240. credit_data = result['data']
  241. print(credit_data)
  242. total_credit = credit_data["summary"].get('total_credit', 0)
  243. used_credit = credit_data["summary"].get('used_credit', 0)
  244. available_credit = credit_data["summary"].get('available_credit', 0)
  245. print(f"额度查询成功: {self.email}")
  246. print(f" 总额度: {total_credit}")
  247. print(f" 已使用: {used_credit}")
  248. print(f" 可用额度: {available_credit}")
  249. # 保存到文件
  250. with open(os.path.join(DATA_DIR, 'credits.txt'), 'a') as f:
  251. f.write(f"{self.email},{total_credit},{used_credit},{available_credit}\n")
  252. return True, result
  253. else:
  254. print(f"额度数据为空: {self.email}")
  255. return False, result
  256. else:
  257. print(f"查询额度失败: {self.email} - {result}")
  258. return False, result
  259. except Exception as e:
  260. print(f"查询额度异常: {e}")
  261. return False, str(e)
  262. def save_cookies(self):
  263. """Save session cookies to file."""
  264. try:
  265. # 确保cookie目录存在
  266. cookie_dir = os.path.dirname(self.cookie_file)
  267. if not os.path.exists(cookie_dir):
  268. os.makedirs(cookie_dir)
  269. with open(self.cookie_file, 'wb') as f:
  270. pickle.dump({
  271. 'cookies': self.session.cookies,
  272. 'token': self.token
  273. }, f)
  274. print(f"Cookies已保存到 {self.cookie_file}")
  275. except Exception as e:
  276. print(f"保存Cookies失败: {e}")
  277. def load_cookies(self):
  278. """Load session cookies from file and validate."""
  279. if os.path.exists(self.cookie_file):
  280. try:
  281. with open(self.cookie_file, 'rb') as f:
  282. data = pickle.load(f)
  283. self.session.cookies.update(data['cookies'])
  284. self.token = data.get('token')
  285. if self.token:
  286. self.session.headers.update({'Authorization': f'Bearer {self.token}'})
  287. print(f"Cookies已加载: {self.cookie_file}")
  288. # 验证cookie有效性
  289. print("验证Cookie有效性...")
  290. url = f'{self._host}/api/user/credit-bundles'
  291. try:
  292. response = self.session.get(url)
  293. if response.status_code == 200 and response.json().get('code') == 0:
  294. print("Cookie有效")
  295. return True
  296. else:
  297. print(f"Cookie已失效 (状态码: {response.status_code}),需要重新登录")
  298. return False
  299. except Exception as e:
  300. print(f"验证Cookie时出错: {e},需要重新登录")
  301. return False
  302. except Exception as e:
  303. print(f"加载Cookies失败: {e}")
  304. return False
  305. return False