提示: 部分模塊方法未自定義,就沒貼了哈! 不過貼了註釋javascript
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # @Time: 2019/9/17 16:26 # @Author: 餘浪人 # @email: yulangren520@gmail.com import asyncio import random from time import sleep import requests, base64, json, re from lxml import etree from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_v1_5 as pk from pyppeteer import launch from conf import SpiderConf from my_mysql import mysql from my_redis import redis_write, redisCli session = requests.session() # 聲明一個session prefix = SpiderConf.ZG_PREFIX # 前綴 baseUrl = 'https://passport.meituan.com' get_url = 'https://passport.meituan.com/account/unitivelogin?service=phoenix&continue=https%3A%2F%2Fwww.zhenguo.com%2Fauth%2Fauthenticated%2F%3Fcontinue%3D%252F&risk_partner=93' # 登陸地址 proxies = { "http": "http://113.138.138.244:3617", # 添加代理 } # 生成加密密碼串 def createPassword(password: str): # 核心 網站加密前端採用非對稱加密 public_key = '''-----BEGIN RSA PRIVATE KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCRD8YahHualjGxPMzeIWnAqVGMIrWrrkr5L7gw+5XT55iIuYXZYLaUFMTOD9iSyfKlL9mvD3ReUX6Lieph3ajJAPPGEuSHwoj5PN1UiQXK3wzAPKcpwrrA2V4Agu1/RZsyIuzboXgcPexyUYxYUTJH48DeYBGJe2GrYtsmzuIu6QIDAQAB\n-----END RSA PRIVATE KEY----- ''' # 目前的公鑰 pass_word = password.encode(encoding='utf-8') rsaKey = RSA.importKey(public_key) cipher = pk.new(rsaKey) cipherText = base64.b64encode(cipher.encrypt(pass_word)).decode('utf-8') return cipherText # 返回轉換後的密碼串> 用於登陸密碼參數 # 登陸> 正常POST def baseLogin(account, password, requestCode=None, responseCode=None): # 常規登陸 global cookie headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'} # 頭 response = session.get(get_url, headers=headers, proxies=proxies) # 獲取登陸頁面 cookie = requests.utils.dict_from_cookiejar(response.cookies) # 將獲取到的cookie字典化 html_obj = etree.HTML(response.text) # 樹對象 postUrl = baseUrl + ''.join(html_obj.xpath('//form[@id="J-normal-form"]/@action')) # 提取並構造完整url csrf = ''.join(html_obj.xpath('//span[@id="csrf"]/text()')) headers['Referer'] = get_url headers['X-CSRF-Token'] = csrf headers['X-Client'] = 'javascript' headers['X-Requested-With'] = 'XMLHttpRequest' param_data = { 'ountrycode': '86', 'email': account, 'password': password, 'origin': 'account-login', 'csrf': csrf, 'requestCode': requestCode, 'responseCode': responseCode, # 須要滑動驗證碼後獲得 } # 構造登陸參數 response = session.post(postUrl, data=param_data, headers=headers, proxies=proxies) # 登陸請求 rawData = response.json() # 接收json響應 return rawData, response # 登陸用戶信息獲取 def acquireInfo(resData: dict, account: str, passWord: str): data = resData.get('data') token = data.get('token') # 登陸成功token _continue = data.get('continue') # 成功後跳轉地址 headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36' } param_data = { 'token': token, 'expire': '0', 'isdialog': '0', 'autologin': '0', 'logintype': 'normal', } response = session.post(_continue, data=param_data, headers=headers, proxies=proxies) if response.status_code == 200: html = etree.HTML(response.text) # 樹對象 imgUrl = 'https:' + ''.join(html.xpath('//img[@class="navbarDropdown__avatar"]/@src')) # 頭像地址 userName = 'https:' + ''.join(html.xpath('//span[@class="navbarDropdown__text"]/text()')) # 暱稱 userId = ''.join(''.join(html.xpath('//a[text()="個人主頁"]/@href')).split('/')[-2:-1]) # 提取用戶信息 response = session.get('https://www.zhenguo.com/?logout=1', headers=headers, proxies=proxies) if response.status_code == 200: cookies = requests.utils.dict_from_cookiejar(response.cookies) cookies['time_out'] = 30 cookies['_userID_'] = userId cookies['_userName_'] = userName cookies.update(cookie) # 添加自定義信息,方便獲取及作自動cookie續期 redis_write(prefix, account, cookies) # cookie 存入reids mysql.autoUser(prefix, account, passWord, '榛果民宿', userImg=imgUrl, nickname=userName) # 用戶存mysql 用戶作自動登陸 return True # 成功返回True print('登陸成功, cookie獲取失敗!') return print('登陸後頁面獲取失敗!') # 登陸入口 def loginMain(account: str, passWord: str): password = createPassword(passWord) rawData, response = baseLogin(account, password) if 'success' in json.dumps(rawData) and not rawData.get('success'): error = rawData.get('error').get('message') # 錯誤信息 errorCode = rawData.get('error').get('code') # 錯誤碼 if errorCode == 101190: # 風控驗證 >滑動驗證碼 responseData = gmailLogin(account, password) # 調用pyppeteer模擬登陸 elif errorCode == 101157: # 短信驗證碼 # dynamicStu = dynamicVerif(rawData) # 登陸短信驗證時處理 responseData = {"status": 1, "msg": '動態驗證失敗,請稍後登陸!'} elif errorCode == 101005: # 密碼錯誤 responseData = {"status": 1, "msg": error} elif errorCode == 101144: # 頻繁提交 responseData = {"status": 1, "msg": error} else: responseData = {"status": 1, "msg": '登陸錯誤,請從新登陸!'} else: # 能夠添加其餘錯誤信息處理 loginStu = acquireInfo(rawData, account, passWord) responseData = {"status": 0, "msg": f'{account}: 登陸成功!'} if loginStu else {"status": 1, "msg": f'{account}: 異常,登陸失敗!'} return responseData
須要其餘方法能夠郵件或留言喲!html