Compare commits

..

No commits in common. "8c53e8d1038e15be06cd57d447c9037db7e20730" and "51ac6664e10583bdd6274e0c0403ddfd8325a849" have entirely different histories.

2 changed files with 81 additions and 80 deletions

View File

@ -21,7 +21,7 @@ services:
libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm1 libasound2 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm1 libasound2
libatspi2.0-0 libxshmfence1 && python -m pip install --upgrade pip && pip libatspi2.0-0 libxshmfence1 && python -m pip install --upgrade pip && pip
install pyppeteer Pillow asyncio aiohttp opencv-python-headless ddddocr install pyppeteer Pillow asyncio aiohttp opencv-python-headless ddddocr
quart requests fake_useragent && rm -rf * && wget -O api.py quart && rm -rf * && wget -O api.py
https://raw.githubusercontent.com/zhao-zg/jd-login/main/api.py https://raw.githubusercontent.com/zhao-zg/jd-login/main/api.py
&& wget -O login.py && wget -O login.py
https://raw.githubusercontent.com/zhao-zg/jd-login/main/login.py https://raw.githubusercontent.com/zhao-zg/jd-login/main/login.py
@ -43,7 +43,7 @@ services:
environment: environment:
TZ: Asia/Shanghai TZ: Asia/Shanghai
command: > command: >
sh -c "rm -rf * && wget -O api.py && pip requests fake_useragent && sh -c "rm -rf * && wget -O api.py
https://raw.githubusercontent.com/zhao-zg/jd-login/main/api.py && wget -O https://raw.githubusercontent.com/zhao-zg/jd-login/main/api.py && wget -O
login.py https://raw.githubusercontent.com/zhao-zg/jd-login/main/login.py login.py https://raw.githubusercontent.com/zhao-zg/jd-login/main/login.py
&& python api.py" && python api.py"

157
login.py
View File

@ -18,7 +18,6 @@ import base64
import io import io
import re import re
import logging import logging
from fake_useragent import UserAgent
# 传参获得已初始化的ddddocr实例 # 传参获得已初始化的ddddocr实例
ocr = None ocr = None
@ -28,14 +27,6 @@ logger = logging.getLogger("login")
simple_format = "[%(asctime)s][%(levelname)s][%(filename)s:%(lineno)d] %(message)s" simple_format = "[%(asctime)s][%(levelname)s][%(filename)s:%(lineno)d] %(message)s"
logging.basicConfig(level=logging.INFO, format=simple_format, datefmt="%Y-%m-%d %H:%M:%S %z") logging.basicConfig(level=logging.INFO, format=simple_format, datefmt="%Y-%m-%d %H:%M:%S %z")
user_agents = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0",
]
# 支持的形状类型 # 支持的形状类型
supported_types = [ supported_types = [
"三角形", "三角形",
@ -59,6 +50,17 @@ supported_colors = {
"红色": ([0, 50, 50], [10, 255, 255]), "红色": ([0, 50, 50], [10, 255, 255]),
} }
async def deleteSessionDelay(workList, uid):
s = workList.get(uid, "")
if s:
await asyncio.sleep(15)
del workList[uid]
async def deleteSession(workList, uid):
s = workList.get(uid, "")
if s:
del workList[uid]
async def loginPhone(chromium_path, workList, uid, headless): async def loginPhone(chromium_path, workList, uid, headless):
# 判断账号密码错误 # 判断账号密码错误
async def isWrongAccountOrPassword(page, verify=False): async def isWrongAccountOrPassword(page, verify=False):
@ -91,9 +93,7 @@ async def loginPhone(chromium_path, workList, uid, headless):
# 判断验证码超时 # 判断验证码超时
async def needResendSMSCode(page): async def needResendSMSCode(page):
try: try:
if await page.querySelector('.getMsg-btn.text-btn.timer.active'): return await page.querySelector('.getMsg-btn.text-btn.timer.active');
return True
return False
except Exception as e: except Exception as e:
logger.info("needResendSMSCode " + str(e)) logger.info("needResendSMSCode " + str(e))
return False return False
@ -128,7 +128,7 @@ async def loginPhone(chromium_path, workList, uid, headless):
) )
page = await browser.newPage() page = await browser.newPage()
await page.setUserAgent( await page.setUserAgent(
UserAgent().random "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36"
) )
await page.setViewport({"width": 360, "height": 640}) await page.setViewport({"width": 360, "height": 640})
await page.goto( await page.goto(
@ -139,8 +139,8 @@ async def loginPhone(chromium_path, workList, uid, headless):
IN_SMS_TIMES = 0 IN_SMS_TIMES = 0
start_time = datetime.datetime.now() start_time = datetime.datetime.now()
sms_sent = False sms_sent = False
while True: try:
try: while True:
now_time = datetime.datetime.now() now_time = datetime.datetime.now()
logger.info("循环检测中...") logger.info("循环检测中...")
if (now_time - start_time).total_seconds() > 70: if (now_time - start_time).total_seconds() > 70:
@ -210,29 +210,16 @@ async def loginPhone(chromium_path, workList, uid, headless):
break break
await asyncio.sleep(1) await asyncio.sleep(1)
except Exception as e: except Exception as e:
logger.info("异常退出") workList[uid].msg = "服务器异常退出"
logger.error(e) workList[uid].status = "error"
workList[uid].status = "error" print("异常退出")
workList[uid].msg = "异常退出" print(e)
break await browser.close()
await deleteSessionDelay(workList, uid)
raise e
logger.info("任务完成退出") print("任务完成退出")
logger.info("任务完成退出")
logger.info("开始删除缓存文件......")
if os.path.exists("image.png"):
os.remove("image.png")
if os.path.exists("template.png"):
os.remove("template.png")
if os.path.exists("shape_image.png"):
os.remove("shape_image.png")
if os.path.exists("rgba_word_img.png"):
os.remove("rgba_word_img.png")
if os.path.exists("rgb_word_img.png"):
os.remove("rgb_word_img.png")
logger.info("缓存文件已删除!")
logger.info("开始关闭浏览器....")
await browser.close() await browser.close()
logger.info("浏览器已关闭!") logger.info("浏览器已关闭!")
return return
@ -259,8 +246,14 @@ async def loginPassword(chromium_path, workList, uid, headless):
# 判断验证码错误 # 判断验证码错误
async def isStillInSMSCodeSentPage(page): async def isStillInSMSCodeSentPage(page):
try: try:
if not await page.querySelector('.getMsg-btn.timer.active') and await page.querySelector('.acc-input.msgCode'): if await page.xpath('//*[@id="header"]/span[2]'):
return True element = await page.xpath('//*[@id="header"]/span[2]')
if element:
text = await page.evaluate(
"(element) => element.textContent", element[0]
)
if text == "手机短信验证":
return True
return False return False
except Exception as e: except Exception as e:
logger.info("isStillInSMSCodeSentPage " + str(e)) logger.info("isStillInSMSCodeSentPage " + str(e))
@ -269,8 +262,14 @@ async def loginPassword(chromium_path, workList, uid, headless):
# 判断验证码超时 # 判断验证码超时
async def needResendSMSCode(page): async def needResendSMSCode(page):
try: try:
if await page.querySelector('.getMsg-btn.timer.active'): if await page.xpath('//*[@id="app"]/div/div[2]/div[2]/button'):
return True element = await page.xpath('//*[@id="app"]/div/div[2]/div[2]/button')
if element:
text = await page.evaluate(
"(element) => element.textContent", element[0]
)
if text == "获取验证码":
return True
return False return False
except Exception as e: except Exception as e:
logger.info("needResendSMSCode " + str(e)) logger.info("needResendSMSCode " + str(e))
@ -307,7 +306,7 @@ async def loginPassword(chromium_path, workList, uid, headless):
) )
page = await browser.newPage() page = await browser.newPage()
await page.setUserAgent( await page.setUserAgent(
UserAgent().random "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36"
) )
await page.setViewport({"width": 360, "height": 640}) await page.setViewport({"width": 360, "height": 640})
await page.goto( await page.goto(
@ -317,9 +316,8 @@ async def loginPassword(chromium_path, workList, uid, headless):
IN_SMS_TIMES = 0 IN_SMS_TIMES = 0
start_time = datetime.datetime.now() start_time = datetime.datetime.now()
try:
while True: while True:
try:
now_time = datetime.datetime.now() now_time = datetime.datetime.now()
logger.info("循环检测中...") logger.info("循环检测中...")
if (now_time - start_time).total_seconds() > 120: if (now_time - start_time).total_seconds() > 120:
@ -492,20 +490,20 @@ async def loginPassword(chromium_path, workList, uid, headless):
break break
await asyncio.sleep(1) await asyncio.sleep(1)
except Exception as e: except Exception as e:
logger.info("异常退出") logger.info("异常退出")
logger.error(e) logger.error(e)
logger.info("异常退出,正在保存当前页面信息......") logger.info("异常退出,正在保存当前页面信息......")
dateTime = datetime.datetime.now().strftime('%Y%m%d %H_%M_%S.%f') dateTime = datetime.datetime.now().strftime('%Y%m%d %H_%M_%S.%f')
logger.info(f"页面截图保存到: error_{usernum}-screenshot-{dateTime}.png") logger.info(f"页面截图保存到: error_{usernum}-screenshot-{dateTime}.png")
await page.screenshot({'path': f"error_{usernum}-screenshot-{dateTime}.png"}) await page.screenshot({'path': f"error_{usernum}-screenshot-{dateTime}.png"})
logger.info(f"页面HTML保存到 error_{usernum}-html-{dateTime}.html") logger.info(f"页面HTML保存到 error_{usernum}-html-{dateTime}.html")
content = await page.content() content = await page.content()
with open(f"error_{usernum}-html-{dateTime}.html", 'w', encoding='utf-8') as f: with open(f"error_{usernum}-html-{dateTime}.html", 'w', encoding='utf-8') as f:
f.write(content) f.write(content)
workList[uid].status = "error" await browser.close()
workList[uid].msg = "异常退出" await deleteSessionDelay(workList, uid)
break raise e
logger.info("任务完成退出") logger.info("任务完成退出")
logger.info("开始删除缓存文件......") logger.info("开始删除缓存文件......")
@ -570,22 +568,21 @@ async def typephoneuser(page, usernum):
await page.waitFor(random.randint(200, 500)) await page.waitFor(random.randint(200, 500))
await page.click(".getMsg-btn.text-btn.timer") await page.click(".getMsg-btn.text-btn.timer")
await page.waitFor(random.randint(500, 1000)) await page.waitFor(random.randint(500, 1000))
async def typeuser(page, usernum, passwd): async def typeuser(page, usernum, passwd):
logger.info("开始输入账号密码") print("开始输入账号密码")
await page.waitForSelector(".J_ping.planBLogin") await page.waitForSelector(".J_ping.planBLogin")
await page.click(".J_ping.planBLogin") await page.click(".J_ping.planBLogin")
await page.type( await page.type(
"#username", usernum, {"delay": random.randint(60, 121)} "#username", usernum, {"delay": random.randint(10, 20)}
) )
await page.type( await page.type(
"#pwd", passwd, {"delay": random.randint(100, 151)} "#pwd", passwd, {"delay": random.randint(10, 20)}
) )
await page.waitFor(random.randint(100, 2000)) await page.waitFor(random.randint(200, 500))
await page.click(".policy_tip-checkbox") await page.click(".policy_tip-checkbox")
await page.waitFor(random.randint(100, 2000)) await page.waitFor(random.randint(200, 500))
await page.click(".btn.J_ping.btn-active") await page.click(".btn.J_ping.btn-active")
await page.waitFor(random.randint(100, 2000)) await page.waitFor(random.randint(500, 1000))
async def sendSMSDirectly(page): async def sendSMSDirectly(page):
@ -605,7 +602,7 @@ async def sendSMSDirectly(page):
try: try:
while True: while True:
if await page.xpath('//*[@id="small_img"]'): if await page.xpath('//*[@id="captcha_modal"]/div/div[3]/div'):
await verification(page) await verification(page)
elif await page.xpath('//*[@id="captcha_modal"]/div/div[3]/button'): elif await page.xpath('//*[@id="captcha_modal"]/div/div[3]/button'):
@ -647,7 +644,7 @@ async def sendSMS(page):
try: try:
while True: while True:
if await page.xpath('//*[@id="small_img"]'): if await page.xpath('//*[@id="captcha_modal"]/div/div[3]/div'):
await verification(page) await verification(page)
elif await page.xpath('//*[@id="captcha_modal"]/div/div[3]/button'): elif await page.xpath('//*[@id="captcha_modal"]/div/div[3]/button'):
@ -802,9 +799,6 @@ async def verification(page):
await page.mouse.move( await page.mouse.move(
box["x"] + distance, box["y"], {"steps": 10} box["x"] + distance, box["y"], {"steps": 10}
) )
await page.waitFor(
random.randint(200, 500)
)
await page.mouse.up() await page.mouse.up()
logger.info("过滑块结束") logger.info("过滑块结束")
@ -916,9 +910,7 @@ async def verification_shape(page):
# 文字点选的重试次数,超过将重启浏览器 # 文字点选的重试次数,超过将重启浏览器
retry_count = 10 retry_count = 10
i = 5 for i in range(5):
while i > 0:
i -= 1
await page.waitForSelector("div.captcha_footer img") await page.waitForSelector("div.captcha_footer img")
image_src = await page.Jeval( image_src = await page.Jeval(
"#cpc_img", 'el => el.getAttribute("src")' "#cpc_img", 'el => el.getAttribute("src")'
@ -1105,7 +1097,7 @@ async def download_file(url, file_path):
file.write(chunk) file.write(chunk)
downloaded_size += len(chunk) downloaded_size += len(chunk)
progress = (downloaded_size / file_size) * 100 progress = (downloaded_size / file_size) * 100
logger.info(f"已下载{progress:.2f}%...") logger.info(f"已下载{progress:.2f}%...", end="\r")
logger.info("下载完成,进行解压安装....") logger.info("下载完成,进行解压安装....")
@ -1191,8 +1183,6 @@ async def main(workList, uid, oocr, oocrDet):
logger.info("初始化浏览器。。。。。") logger.info("初始化浏览器。。。。。")
chromium_path = await init_chrome() chromium_path = await init_chrome()
headless = 'new' headless = 'new'
if platform.system() == "Windows":
headless = False
logger.info("进入选择登录方式流程") logger.info("进入选择登录方式流程")
try_time = 1 try_time = 1
@ -1208,5 +1198,16 @@ async def main(workList, uid, oocr, oocrDet):
await asyncio.sleep(random.uniform(2, 4)) await asyncio.sleep(random.uniform(2, 4))
logger.info(f"进行第{try_time}次重试") logger.info(f"进行第{try_time}次重试")
try_time += 1 try_time += 1
logger.info("登录完成") if os.path.exists("image.png"):
os.remove("image.png")
if os.path.exists("template.png"):
os.remove("template.png")
if os.path.exists("shape_image.png"):
os.remove("shape_image.png")
if os.path.exists("rgba_word_img.png"):
os.remove("rgba_word_img.png")
if os.path.exists("rgb_word_img.png"):
os.remove("rgb_word_img.png")
await deleteSessionDelay(workList, uid)
print("登录完成")
await asyncio.sleep(10) await asyncio.sleep(10)