1
0
mirror of https://github.com/okyyds/yyds.git synced 2026-07-12 21:51:17 +08:00
Files
yyds/backUp/jd_OpenCard.py
2022-02-04 03:32:46 +08:00

1301 lines
52 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/env python3
# -*- coding: utf-8 -*
'''
项目名称: JD_OpenCard
Author: Curtin
功能JD入会开卡领取京豆
CreateDate: 2021/5/4 下午1:47
UpdateTime: 2021/6/19
'''
version = 'v1.2.2'
readmes = """
# JD入会领豆小程序
![JD入会领豆小程序](https://raw.githubusercontent.com/curtinlv/JD-Script/main/OpenCrad/resultCount.png)
## 使用方法
#### [手机用户(参考) https://mp.weixin.qq.com/s/ih6aOURXWM-iKrhvMyR3mw](https://mp.weixin.qq.com/s/ih6aOURXWM-iKrhvMyR3mw)
#### [PC用户 (参考) https://mp.weixin.qq.com/s/JmLxAecZAlEc4L2sZWnn1A](https://mp.weixin.qq.com/s/JmLxAecZAlEc4L2sZWnn1A)
#### [v4-bot用户 (参考) https://github.com/curtinlv/JD-Script/pull/12#issue-652134788](https://github.com/curtinlv/JD-Script/pull/12#issue-652134788)
## 目录结构
JD-Script/ #仓库
|-- LICENSE
|-- OpenCard # 主目录
| |-- jd_OpenCard.py # 主代码 (必要)
| |-- log # 临时目录(可删除)
| |-- OpenCardConfig.ini # 只配置文件(必要)
| |-- Readme.md # 说明书
| `-- start.sh # shell脚本非必要
`-- README.md
log目录结构、临时目录可删除
log
├── memory.json # 记忆、统计功能临时存放参数
├── shopid-2021-05-23.txt # 记录所有送豆的shopid
├── 入会N豆以上的shopid-2021-05-23.txt # 记录满足入会条件的shopid
├── 入会汇总.txt # 记录所有入会店铺送豆的加入、注销链接
├── 可退会账号【账号id】.txt # 记录跑脚本之前已经过入会且目前送豆的注销链接(可优先退会)
### `【兼容环境】`
1.Python3.3+ 环境
2.兼容ios设备软件Pythonista 3、Pyto(已测试正常跑,其他软件自行测试)
3.Windows exe
安装依赖模块 :
pip3 install requests
执行:
python3 jd_OpenCard.py
start.sh 脚本运行方法:
1.适合定时任务或不想依赖ini配置文件。
2.支持单号跑多开,如
cp start.sh start_2.sh
sh start_2.sh #只跑里面配置的参数如cookie
3.定时任务(参考):
0 8 * * * sh /home/curtin/JD-Script/OpenCard/start.sh
2 8 * * * sh /home/curtin/JD-Script/OpenCard/start_2.sh
## `【更新记录】`
2021.6.19: (v1.2.2)
* 修复多线程报错
2021.6.14: (v1.2.1)
* 新增单双线程控制
* 修复一些问题,如腾讯云跑异常报错。
2021.5.28v1.2.0
* 新增单或多账号并发
- Concurrent=yes #开启
* 新增企业微信、Bark推送
* 优化一些逻辑
- 如随机账号查询礼包,仅开启单账号时候
- 京豆统计
2021.5.23(v1.1.1)
* 修复一些问题及优化一些代码
* 修复Env环境读取变量问题
* 新增 start.sh 运行脚本可Env环境使用
- 运行方式 sh start.sh
2021.5.21(v1.1.0)
* 修复一些问题及优化一些代码:
- 修复最后统计显示为0新增开卡个数统计
- 修复记忆功能一些bug
- 等等一些小问题
* 新增机器人通知
- 开启远程shopid、配合crontab 坐等收豆
2021.5.15(v1.0.5)
* 新增远程获取shopid功能
- isRemoteSid=yes #开启
* 修改已知Bug
2021.5.9(v1.0.4 Beta)
* 优化代码逻辑
* 打包exe版本测试
2021.5.8(v1.0.3)
* 优化记忆功能逻辑:
- cookiek个数检测
- shopid个数检测
- 上一次中断最后记录的账号id检测不存在本次ck里面
- 临时文件log/memory.json是否存在
- 以上任意一条命中则记忆接力功能不生效。
2021.5.7(v1.0.2)
* 优化代码逻辑
* 修复已知Bug
2021.5.5(v1.0.1)
* 新增记忆功能,如中断后下次跑会接着力跑(默认开启)
- memory= True
* 新增仅记录shopid不入会功能默认关闭
- onlyRecord = no
* 修复已知Bug
2021.5.4(v1.0.0)
* 支持多账号
- JD_COOKIE=pt_key=xxx;pt_pin=xxx;&pt_key=xxx;pt_pin=xxx; #多账号&分隔
* 限制京豆数量入会例如只入50豆以上
- openCardBean = 50
* 双线程运行
- 默认开启,且您没得选择。
* 记录满足条件的shopid 【record= True】默认开启 ./log 目录可删除)
- log/可销卡汇总.txt #记录开卡送豆的店铺销卡链接
- log/shopid-yyyy-mm-dd.txt #记录当天所有入会送豆的shopid
- log/可销卡账号xxx.txt #记录账号可销卡的店铺
### `【账号参数配置说明】`
### 主配置文件[ OpenCardConfig.ini ] 请保持utf-8默认格式
变量 | 值 | 说明
---- | ----- | ------
JD_COOKIE | pt_key=xxx;pt_pin=xxx; | 必要(多账号&分隔)
openCardBean | 30 | int入会送豆满足此值否则不入会
record | False或True | 布尔值是否记录符合条件的shopid(默认True)
onlyRecord | False或True |布尔值, True:仅记录,不入会(默认False)
memory | False或True | 布尔值,开启记忆功能,接力上一次异常中断位置继续。(默认yes)
printlog | False或True | 布尔值True只打印部分日志 False:打印所有日志
sleepNum | False或True | Float限制速度单位秒如果请求过快报错适当调整0.5秒以上
isRemoteSid | False或True | 布尔值True:使用作者远程仓库更新的idFalse使用本地shopid.txt的id
#### 兼容Env环境如有配置则优先使用适合AC、云服务环境等
export JD_COOKIE='pt_key=xxx;pt_pin=xxx;' (多账号&分隔)
export openCardBean=30
export xxx=xxx
#### Ps:您可以到以下途径获取最新的shopid.txt定期更新
###### [GitHub仓库 https://github.com/curtinlv/JD-Script](https://github.com/curtinlv/JD-Script)
###### [Gitee仓库 https://gitee.com/curtinlv/JD-Script](https://gitee.com/curtinlv/JD-Script)
###### [TG频道 https://t.me/TopStyle2021](https://t.me/TopStyle2021)
###### [TG群 https://t.me/topStyle996](https://t.me/topStyle996)
###### 关注公众号【TopStyle】回复shopid
![TopStyle](https://gitee.com/curtinlv/img/raw/master/gzhcode.jpg)
#
@Last Version: %s
@Last Time: 2021-06-19 13:55
@Author: Curtin
#### **仅以学习交流为主,请勿商业用途、禁止违反国家法律 ,转载请留个名字,谢谢!**
# End.
[回到顶部](#readme)
""" % version
################################ 【Main】################################
import time, os, sys, datetime
import requests
import random, string
import re, json, base64
from urllib.parse import unquote, quote_plus
from threading import Thread
from configparser import RawConfigParser
# 定义一些要用到参数
requests.packages.urllib3.disable_warnings()
scriptHeader = """
════════════════════════════════════════
║ ║
║ JD 入 会 领 豆 ║
║ ║
════════════════════════════════════════
@Version: {}""".format(version)
remarks = '\n\n\tTG交流 : https://t.me/topstyle996\n\n\tTG频道 : https://t.me/TopStyle2021\n\n\t公众号 : TopStyle\n\n\t\t\t--By Curtin\n'
timestamp = int(round(time.time() * 1000))
today = datetime.datetime.now().strftime('%Y-%m-%d')
# 获取当前工作目录
pwd = os.path.dirname(os.path.abspath(__file__)) + os.sep
######
openCardBean = 0
sleepNum = 0.0
record = True
onlyRecord = False
memory = True
printlog = True
isRemoteSid = True
Concurrent = True
TG_BOT_TOKEN = ''
TG_USER_ID = ''
PUSH_PLUS_TOKEN = ''
TG_PROXY_IP = ''
TG_PROXY_PORT = ''
TG_API_HOST = ''
QYWX_AM = ''
BARK = ''
DoubleThread = True
# 获取账号参数
try:
configinfo = RawConfigParser()
try:
configinfo.read(pwd + "OpenCardConfig.ini", encoding="UTF-8")
except Exception as e:
with open(pwd + "OpenCardConfig.ini", "r", encoding="UTF-8") as config:
getConfig = config.read().encode('utf-8').decode('utf-8-sig')
with open(pwd + "OpenCardConfig.ini", "w", encoding="UTF-8") as config:
config.write(getConfig)
try:
configinfo.read(pwd + "OpenCardConfig.ini", encoding="UTF-8")
except:
configinfo.read(pwd + "OpenCardConfig.ini", encoding="gbk")
cookies = configinfo.get('main', 'JD_COOKIE')
openCardBean = configinfo.getint('main', 'openCardBean')
sleepNum = configinfo.getfloat('main', 'sleepNum')
record = configinfo.getboolean('main', 'record')
onlyRecord = configinfo.getboolean('main', 'onlyRecord')
memory = configinfo.getboolean('main', 'memory')
printlog = configinfo.getboolean('main', 'printlog')
isRemoteSid = configinfo.getboolean('main', 'isRemoteSid')
TG_BOT_TOKEN = configinfo.get('main', 'TG_BOT_TOKEN')
TG_USER_ID = configinfo.get('main', 'TG_USER_ID')
PUSH_PLUS_TOKEN = configinfo.get('main', 'PUSH_PLUS_TOKEN')
TG_PROXY_IP = configinfo.get('main', 'TG_PROXY_IP')
TG_PROXY_PORT = configinfo.get('main', 'TG_PROXY_PORT')
TG_API_HOST = configinfo.get('main', 'TG_API_HOST')
QYWX_AM = configinfo.get('main', 'QYWX_AM')
Concurrent = configinfo.getboolean('main', 'Concurrent')
DoubleThread = configinfo.getboolean('main', 'DoubleThread')
BARK = configinfo.get('main', 'BARK')
except Exception as e:
OpenCardConfigLabel = 1
print("参数配置有误请检查OpenCardConfig.ini\nError:", e)
print("尝试从Env环境获取")
def getBool(label):
try:
if label == 'True' or label == 'yes' or label == 'true' or label == 'Yes':
return True
elif label == 'False' or label == 'no' or label == 'false' or label == 'No':
return False
else:
return True
except Exception as e:
print(e)
# 获取系统ENV环境参数优先使用 适合Ac、云服务等环境
# JD_COOKIE=cookie (多账号&分隔)
if "JD_COOKIE" in os.environ:
if len(os.environ["JD_COOKIE"]) > 10:
cookies = os.environ["JD_COOKIE"]
print("已获取并使用Env环境 Cookie")
# 只入送豆数量大于此值
if "openCardBean" in os.environ:
if len(os.environ["openCardBean"]) > 0:
openCardBean = int(os.environ["openCardBean"])
print("已获取并使用Env环境 openCardBean:", openCardBean)
elif not openCardBean:
openCardBean = 0
# 是否开启双线程
if "DoubleThread" in os.environ:
if len(os.environ["DoubleThread"]) > 1:
DoubleThread = getBool(os.environ["DoubleThread"])
print("已获取并使用Env环境 DoubleThread", DoubleThread)
# 多账号并发
if "Concurrent" in os.environ:
if len(os.environ["Concurrent"]) > 1:
Concurrent = getBool(os.environ["Concurrent"])
print("已获取并使用Env环境 Concurrent", Concurrent)
elif not Concurrent:
Concurrent = True
# 限制速度单位秒如果请求过快报错适当调整0.5秒以上
if "sleepNum" in os.environ:
if len(os.environ["sleepNum"]) > 0:
sleepNum = float(os.environ["sleepNum"])
print("已获取并使用Env环境 sleepNum:", sleepNum)
elif not sleepNum:
sleepNum = 0
if "printlog" in os.environ:
if len(os.environ["printlog"]) > 1:
printlog = getBool(os.environ["printlog"])
print("已获取并使用Env环境 printlog:", printlog)
elif not printlog:
printlog = True
# 是否记录符合条件的shopid输出文件【OpenCardlog/yes_shopid.txt】 False|True
if "record" in os.environ:
if len(os.environ["record"]) > 1:
record = getBool(os.environ["record"])
print("已获取并使用Env环境 record:", record)
elif not record:
record = True
# 仅记录不入会。入会有豆的shopid输出文件
if "onlyRecord" in os.environ:
if len(os.environ["onlyRecord"]) > 1:
onlyRecord = getBool(os.environ["onlyRecord"])
print("已获取并使用Env环境 onlyRecord:", onlyRecord)
elif not onlyRecord:
onlyRecord = False
# 开启记忆, 需要record=True且 memory= True 才生效
if "memory" in os.environ:
if len(os.environ["memory"]) > 1:
memory = getBool(os.environ["memory"])
print("已获取并使用Env环境 memory:", memory)
elif not memory:
memory = True
# 是否启用远程shopid
if "isRemoteSid" in os.environ:
if len(os.environ["isRemoteSid"]) > 1:
isRemoteSid = getBool(os.environ["isRemoteSid"])
print("已获取并使用Env环境 isRemoteSid:", isRemoteSid)
elif not isRemoteSid:
isRemoteSid = True
# 获取TG_BOT_TOKEN
if "TG_BOT_TOKEN" in os.environ:
if len(os.environ["TG_BOT_TOKEN"]) > 1:
TG_BOT_TOKEN = os.environ["TG_BOT_TOKEN"]
print("已获取并使用Env环境 TG_BOT_TOKEN")
# 获取TG_USER_ID
if "TG_USER_ID" in os.environ:
if len(os.environ["TG_USER_ID"]) > 1:
TG_USER_ID = os.environ["TG_USER_ID"]
print("已获取并使用Env环境 TG_USER_ID")
# 获取代理ip
if "TG_PROXY_IP" in os.environ:
if len(os.environ["TG_PROXY_IP"]) > 1:
TG_PROXY_IP = os.environ["TG_PROXY_IP"]
print("已获取并使用Env环境 TG_PROXY_IP")
# 获取TG 代理端口
if "TG_PROXY_PORT" in os.environ:
if len(os.environ["TG_PROXY_PORT"]) > 1:
TG_PROXY_PORT = os.environ["TG_PROXY_PORT"]
print("已获取并使用Env环境 TG_PROXY_PORT")
elif not TG_PROXY_PORT:
TG_PROXY_PORT = ''
# 获取TG TG_API_HOST
if "TG_API_HOST" in os.environ:
if len(os.environ["TG_API_HOST"]) > 1:
TG_API_HOST = os.environ["TG_API_HOST"]
print("已获取并使用Env环境 TG_API_HOST")
# 获取pushplus+ PUSH_PLUS_TOKEN
if "PUSH_PLUS_TOKEN" in os.environ:
if len(os.environ["PUSH_PLUS_TOKEN"]) > 1:
PUSH_PLUS_TOKEN = os.environ["PUSH_PLUS_TOKEN"]
print("已获取并使用Env环境 PUSH_PLUS_TOKEN")
# 获取企业微信应用推送 QYWX_AM
if "QYWX_AM" in os.environ:
if len(os.environ["QYWX_AM"]) > 1:
QYWX_AM = os.environ["QYWX_AM"]
print("已获取并使用Env环境 QYWX_AM")
# 获取企业微信应用推送 QYWX_AM
if "BARK" in os.environ:
if len(os.environ["BARK"]) > 1:
BARK = os.environ["BARK"]
print("已获取并使用Env环境 BARK")
# 判断参数是否存在
try:
cookies
except NameError as e:
var_exists = False
print("[OpenCardConfig.ini] 和 [Env环境] 都无法获取到您的cookies请配置!\nError:", e)
time.sleep(60)
exit(1)
else:
var_exists = True
# 创建临时目录
if not os.path.exists(pwd + "log"):
os.mkdir(pwd + "log")
# 记录功能json
memoryJson = {}
message_info = ''
notify_mode = []
################################### Function ################################
class TaskThread(Thread):
"""
处理task相关的线程类
"""
def __init__(self, func, args=()):
super(TaskThread, self).__init__()
self.func = func # 要执行的task类型
self.args = args # 要传入的参数
def run(self):
self.result = self.func(*self.args) # 将任务执行结果赋值给self.result变量
def get_result(self):
# 改方法返回task函数的执行结果,方法名不是非要get_result
try:
return self.result
except Exception as ex:
print(ex)
return "ERROR"
def nowtime():
return datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
def printinfo(context, label: bool):
if label == False:
print(context)
def exitCodeFun(code):
try:
if sys.platform == 'win32' or sys.platform == 'cygwin':
print("连按回车键即可退出窗口!")
exitCode = input()
exit(code)
except:
time.sleep(3)
exit(code)
def message(str_msg):
global message_info
print(str_msg)
message_info = "{}\n{}".format(message_info, str_msg)
sys.stdout.flush()
# 获取通知,
if PUSH_PLUS_TOKEN:
notify_mode.append('pushplus')
if TG_BOT_TOKEN and TG_USER_ID:
notify_mode.append('telegram_bot')
if QYWX_AM:
notify_mode.append('wecom_app')
if BARK:
notify_mode.append('bark')
# tg通知
def telegram_bot(title, content):
try:
print("\n")
bot_token = TG_BOT_TOKEN
user_id = TG_USER_ID
if not bot_token or not user_id:
print("tg服务的bot_token或者user_id未设置!!\n取消推送")
return
print("tg服务启动")
if TG_API_HOST:
if 'http' in TG_API_HOST:
url = f"{TG_API_HOST}/bot{TG_BOT_TOKEN}/sendMessage"
else:
url = f"https://{TG_API_HOST}/bot{TG_BOT_TOKEN}/sendMessage"
else:
url = f"https://api.telegram.org/bot{TG_BOT_TOKEN}/sendMessage"
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
payload = {'chat_id': str(TG_USER_ID), 'text': f'{title}\n\n{content}', 'disable_web_page_preview': 'true'}
proxies = None
if TG_PROXY_IP and TG_PROXY_PORT:
proxyStr = "http://{}:{}".format(TG_PROXY_IP, TG_PROXY_PORT)
proxies = {"http": proxyStr, "https": proxyStr}
try:
response = requests.post(url=url, headers=headers, params=payload, proxies=proxies).json()
except:
print('推送失败!')
if response['ok']:
print('推送成功!')
else:
print('推送失败!')
except Exception as e:
print(e)
# push推送
def pushplus_bot(title, content):
try:
print("\n")
if not PUSH_PLUS_TOKEN:
print("PUSHPLUS服务的token未设置!!\n取消推送")
return
print("PUSHPLUS服务启动")
url = 'http://www.pushplus.plus/send'
data = {
"token": PUSH_PLUS_TOKEN,
"title": title,
"content": content
}
body = json.dumps(data).encode(encoding='utf-8')
headers = {'Content-Type': 'application/json'}
response = requests.post(url=url, data=body, headers=headers).json()
if response['code'] == 200:
print('推送成功!')
else:
print('推送失败!')
except Exception as e:
print(e)
# BARK
def bark_push(title, content):
print("\n")
if not BARK:
print("bark服务的bark_token未设置!!\n取消推送")
return
print("bark服务启动")
try:
response = requests.get('''https://api.day.app/{0}/{1}/{2}'''.format(BARK, title, quote_plus(content))).json()
if response['code'] == 200:
print('推送成功!')
else:
print('推送失败!')
except Exception as e:
print(e)
print('Bark推送失败')
def send(title, content):
"""
使用 bark, telegram bot, dingding bot, serverJ 发送手机推送
:param title:
:param content:
:return:
"""
content = content + "\n\n" + footer
for i in notify_mode:
if i == 'telegram_bot':
if TG_BOT_TOKEN and TG_USER_ID:
telegram_bot(title=title, content=content)
else:
print('未启用 telegram机器人')
continue
elif i == 'pushplus':
if PUSH_PLUS_TOKEN:
pushplus_bot(title=title, content=content)
else:
print('未启用 PUSHPLUS机器人')
continue
elif i == 'wecom_app':
if QYWX_AM:
wecom_app(title=title, content=content)
else:
print('未启用企业微信应用消息推送')
continue
elif i == 'bark':
if BARK:
bark_push(title=title, content=content)
else:
print('未启用Bark APP应用消息推送')
continue
else:
print('此类推送方式不存在')
# 企业微信 APP 推送
def wecom_app(title, content):
try:
if not QYWX_AM:
print("QYWX_AM 并未设置!!\n取消推送")
return
QYWX_AM_AY = re.split(',', QYWX_AM)
if 4 < len(QYWX_AM_AY) > 5:
print("QYWX_AM 设置错误!!\n取消推送")
return
corpid = QYWX_AM_AY[0]
corpsecret = QYWX_AM_AY[1]
touser = QYWX_AM_AY[2]
agentid = QYWX_AM_AY[3]
try:
media_id = QYWX_AM_AY[4]
except:
media_id = ''
wx = WeCom(corpid, corpsecret, agentid)
# 如果没有配置 media_id 默认就以 text 方式发送
if not media_id:
message = title + '\n\n' + content
response = wx.send_text(message, touser)
else:
response = wx.send_mpnews(title, content, media_id, touser)
if response == 'ok':
print('推送成功!')
else:
print('推送失败!错误信息如下:\n', response)
except Exception as e:
print(e)
class WeCom:
def __init__(self, corpid, corpsecret, agentid):
self.CORPID = corpid
self.CORPSECRET = corpsecret
self.AGENTID = agentid
def get_access_token(self):
url = 'https://qyapi.weixin.qq.com/cgi-bin/gettoken'
values = {'corpid': self.CORPID,
'corpsecret': self.CORPSECRET,
}
req = requests.post(url, params=values)
data = json.loads(req.text)
return data["access_token"]
def send_text(self, message, touser="@all"):
send_url = 'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=' + self.get_access_token()
send_values = {
"touser": touser,
"msgtype": "text",
"agentid": self.AGENTID,
"text": {
"content": message
},
"safe": "0"
}
send_msges = (bytes(json.dumps(send_values), 'utf-8'))
respone = requests.post(send_url, send_msges)
respone = respone.json()
return respone["errmsg"]
def send_mpnews(self, title, message, media_id, touser="@all"):
send_url = 'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=' + self.get_access_token()
send_values = {
"touser": touser,
"msgtype": "mpnews",
"agentid": self.AGENTID,
"mpnews": {
"articles": [
{
"title": title,
"thumb_media_id": media_id,
"author": "Author",
"content_source_url": "",
"content": message.replace('\n', '<br/>'),
"digest": message
}
]
}
}
send_msges = (bytes(json.dumps(send_values), 'utf-8'))
respone = requests.post(send_url, send_msges)
respone = respone.json()
return respone["errmsg"]
# 检测cookie格式是否正确
def iscookie():
"""
:return: cookiesList,userNameList,pinNameList
"""
cookiesList = []
userNameList = []
pinNameList = []
if 'pt_key=' in cookies and 'pt_pin=' in cookies:
r = re.compile(r"pt_key=.*?pt_pin=.*?;", re.M | re.S | re.I)
result = r.findall(cookies)
if len(result) >= 1:
message("您已配置{}个账号".format(len(result)))
u = 1
for i in result:
r = re.compile(r"pt_pin=(.*?);")
pinName = r.findall(i)
pinName = unquote(pinName[0])
# 获取账号名
ck, nickname = getUserInfo(i, pinName, u)
if nickname != False:
cookiesList.append(ck)
userNameList.append(nickname)
pinNameList.append(pinName)
else:
u += 1
continue
u += 1
if len(cookiesList) > 0 and len(userNameList) > 0:
return cookiesList, userNameList, pinNameList
else:
message("没有可用Cookie已退出")
exitCodeFun(3)
else:
message("cookie 格式错误!...本次操作已退出")
exitCodeFun(4)
else:
message("cookie 格式错误!...本次操作已退出")
exitCodeFun(4)
# 检查是否有更新版本
def gettext(url):
try:
resp = requests.get(url, timeout=60).text
if '该内容无法显示' in resp:
return gettext(url)
return resp
except Exception as e:
print(e)
def isUpdate():
global footer, readme1, readme2, readme3, uPversion
url = base64.decodebytes(
b"aHR0cHM6Ly9naXRlZS5jb20vY3VydGlubHYvUHVibGljL3Jhdy9tYXN0ZXIvT3BlbkNhcmQvdXBkYXRlLmpzb24=")
try:
result = gettext(url)
result = json.loads(result)
isEnable = result['isEnable']
uPversion = result['version']
info = result['info']
readme1 = result['readme1']
readme2 = result['readme2']
readme3 = result['readme3']
pError = result['m']
footer = result['footer']
getWait = result['s']
if isEnable > 50 and isEnable < 150:
if version != uPversion:
print(f"\n当前最新版本:【{uPversion}\n\n{info}\n")
message(f"{readme1}{readme2}{readme3}")
time.sleep(getWait)
else:
message(f"{readme1}{readme2}{readme3}")
time.sleep(getWait)
else:
print(pError)
time.sleep(300)
exit(666)
except:
message("请检查您的环境/版本是否正常!")
time.sleep(10)
exit(666)
def getUserInfo(ck, pinName, userNum):
url = 'https://me-api.jd.com/user_new/info/GetJDUserInfoUnion?orgFlag=JD_PinGou_New&callSource=mainorder&channel=4&isHomewhite=0&sceneval=2&sceneval=2&callback=GetJDUserInfoUnion'
headers = {
'Cookie': ck,
'Accept': '*/*',
'Connection': 'close',
'Referer': 'https://home.m.jd.com/myJd/home.action',
'Accept-Encoding': 'gzip, deflate, br',
'Host': 'me-api.jd.com',
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.2 Mobile/15E148 Safari/604.1',
'Accept-Language': 'zh-cn'
}
try:
resp = requests.get(url=url, verify=False, headers=headers, timeout=60).text
r = re.compile(r'GetJDUserInfoUnion.*?\((.*?)\)')
result = r.findall(resp)
userInfo = json.loads(result[0])
nickname = userInfo['data']['userInfo']['baseInfo']['nickname']
return ck, nickname
except Exception:
context = f"账号{userNum}{pinName}】Cookie 已失效!请重新获取。"
message(context)
send("【JD入会领豆】Cookie 已失效!", context)
return ck, False
# 设置Headers
def setHeaders(cookie, intype):
if intype == 'mall':
headers = {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Host": "mall.jd.com",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.2 Safari/605.1.15",
"Accept-Language": "zh-cn",
"Accept-Encoding": "gzip, deflate, br",
"Connection": "close"
}
return headers
elif intype == 'JDApp':
headers = {
'Cookie': cookie,
'Accept': "*/*",
'Connection': "close",
'Referer': "https://shopmember.m.jd.com/shopcard/?",
'Accept-Encoding': "gzip, deflate, br",
'Host': "api.m.jd.com",
'User-Agent': "jdapp;iPhone;9.4.8;14.3;809409cbd5bb8a0fa8fff41378c1afe91b8075ad;network/wifi;ADID/201EDE7F-5111-49E8-9F0D-CCF9677CD6FE;supportApplePay/0;hasUPPay/0;hasOCPay/0;model/iPhone13,4;addressid/;supportBestPay/0;appBuild/167629;jdSupportDarkMode/0;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1",
'Accept-Language': "zh-cn"
}
return headers
elif intype == 'mh5':
headers = {
'Cookie': cookie,
'Accept': "*/*",
'Connection': "close",
'Referer': "https://shopmember.m.jd.com/shopcard/?",
'Accept-Encoding': "gzip, deflate, br",
'Host': "api.m.jd.com",
'User-Agent': "Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1",
'Accept-Language': "zh-cn"
}
return headers
# 记录符合件的shopid到本地文件保存 当前目录OpenCardlog/shopid-yyyy-mm-dd.txt 或 log-yyyy-mm-dd.txt
def outfile(filename, context, iscover):
"""
:param filename: 文件名 默认txt格式
:param context: 写入内容
:param iscover: 是否覆盖 False or True
:return:
"""
if record == True:
try:
if iscover == False:
with open(pwd + "log/{0}".format(filename), "a+", encoding="utf-8") as f1:
f1.write("{}\n".format(context))
f1.close()
elif iscover == True:
with open(pwd + "{0}".format(filename), "w+", encoding="utf-8") as f1:
f1.write("{}".format(context))
f1.close()
except Exception as e:
print(e)
# 记忆功能 默认双线程
def memoryFun(startNum, threadNum, usernameLabel, username, getallbean, userCount):
global memoryJson
if memory == True:
if usernameLabel == True:
memoryJson['allShopidNum'] = endShopidNum
memoryJson['currUser{}'.format(threadNum)] = username
memoryJson['t{}_startNum'.format(threadNum)] = startNum
memoryJson['allUserCount'] = userCount
if usernameLabel == False:
try:
memoryJson['{}'.format(username)]
memoryJson['{}'.format(username)] += getallbean
except:
memoryJson['{}'.format(username)] = getallbean
try:
memoryJson['{}_ok'.format(username)]
memoryJson['{}_ok'.format(username)] += 1
except:
memoryJson['{}_ok'.format(username)] = 1
try:
if os.path.exists(pwd + "log"):
with open(pwd + "log/memory.json", "w+", encoding="utf-8") as f:
json.dump(memoryJson, f, indent=4)
else:
pass
except Exception as e:
print(e)
# 修复记忆功能一些问题如记录累计京豆统计显示为0等
def isMemoryEnable():
global memoryJson
memoryJson = getMemory()
# 获取记忆配置
def getMemory():
"""
:return: memoryJson
"""
if os.path.exists(pwd + "log/memory.json"):
with open(pwd + "log/memory.json", "r", encoding="utf-8") as f:
memoryJson = json.load(f)
if len(memoryJson) > 0:
return memoryJson
else:
pass
def rmCount():
if os.path.exists(pwd + "log/入会汇总.txt"):
os.remove(pwd + "log/入会汇总.txt")
if os.path.exists(pwd + "log/memory.json"):
os.remove(pwd + "log/memory.json")
# 判断是否启用记忆功能
def isMemory(memorylabel, startNum1, startNum2, midNum, endNum, pinNameList):
"""
:param memorylabel: 记忆标签
:param startNum1: 线程1默认开始位置
:param startNum2: 线程2默认开始位置
:param midNum: 线程1默认结束位置
:param endNum: 线程2默认结束位置
:return: startNum1, startNum2, memorylabel
"""
if memory == True and memorylabel == 0:
try:
memoryJson = getMemory()
if memoryJson['allShopidNum'] == endNum:
currUserLabel = 0
if memoryJson['allUserCount'] == allUserCount:
for u in pinNameList:
if memoryJson['currUser1'] == u:
currUserLabel += 1
elif memoryJson['currUser2'] == u:
currUserLabel += 1
if memoryJson['currUser1'] == memoryJson['currUser2']:
currUserLabel = 2
if currUserLabel < 2:
print("通知检测到您配置的CK有变更本次记忆功能不生效。")
rmCount()
return startNum1, startNum2, memorylabel
if memoryJson['t1_startNum'] + 1 == midNum and memoryJson['t2_startNum'] + 1 == endNum:
print(
f"\n上次已完成所有shopid\n\nPs:您可以关注公众号或TG频道获取最新shopid。\n公众号: TopStyle\n电报TG:https://t.me/TopStyle2021\n\n请输入 0 或 1\n0 : 退出。\n1 : 重新跑一次,以防有漏")
try:
getyourNum = int(input("正在等待您的选择:"))
if getyourNum == 1:
print("Ok,那就重新跑一次~")
rmCount()
memorylabel = 1
return startNum1, startNum2, memorylabel
elif getyourNum == 0:
print("Ok,已退出~")
time.sleep(10)
exit(0)
except:
# print("Error: 您的输入有误!已退出。")
exitCodeFun(3)
else:
isMemoryEnable()
if memoryJson['t1_startNum']:
startNum1 = memoryJson['t1_startNum']
message(f"已启用记忆功能 memory= True线程1从第【{startNum1}】店铺开始")
if memoryJson['t2_startNum']:
startNum2 = memoryJson['t2_startNum']
message(f"已启用记忆功能 memory= True线程2从第【{startNum2}】店铺开始")
memorylabel = 1
return startNum1, startNum2, memorylabel
else:
message("通知检测到您配置的CK有变更本次记忆功能不生效。")
rmCount()
return startNum1, startNum2, memorylabel
else:
message("通知检测到shopid有更新本次记忆功能不生效。")
rmCount()
memorylabel = 1
return startNum1, startNum2, memorylabel
except Exception as e:
memorylabel = 1
return startNum1, startNum2, memorylabel
else:
rmCount()
memorylabel = 1
return startNum1, startNum2, memorylabel
# 获取VenderId
def getVenderId(shopId, headers):
"""
:param shopId:
:param headers
:return: venderId
"""
url = 'https://mall.jd.com/index-{0}.html'.format(shopId)
resp = requests.get(url=url, verify=False, headers=headers, timeout=60)
resulttext = resp.text
r = re.compile(r'shopId=\d+&id=(\d+)"')
venderId = r.findall(resulttext)
return venderId[0]
# 查询礼包
def getShopOpenCardInfo(venderId, headers, shopid, userName, user_num):
"""
:param venderId:
:param headers:
:return: activityId,getBean 或 返回 0:没豆 1:有豆已是会员 2:记录模式(不入会)
"""
num1 = string.digits
v_num1 = ''.join(random.sample(["1", "2", "3", "4", "5", "6", "7", "8", "9"], 1)) + ''.join(
random.sample(num1, 4)) # 随机生成一窜4位数字
url = 'https://api.m.jd.com/client.action?appid=jd_shop_member&functionId=getShopOpenCardInfo&body=%7B%22venderId%22%3A%22{2}%22%2C%22channel%22%3A406%7D&client=H5&clientVersion=9.2.0&uuid=&jsonp=jsonp_{0}_{1}'.format(
timestamp, v_num1, venderId)
resp = requests.get(url=url, verify=False, headers=headers, timeout=60)
time.sleep(sleepNum)
resulttxt = resp.text
r = re.compile(r'jsonp_.*?\((.*?)\)\;', re.M | re.S | re.I)
result = r.findall(resulttxt)
cardInfo = json.loads(result[0])
venderCardName = cardInfo['result']['shopMemberCardInfo']['venderCardName'] # 店铺名称
if user_num == 1:
printinfo(f"\t└查询入会礼包【{venderCardName}", printlog)
openCardStatus = cardInfo['result']['userInfo']['openCardStatus'] # 是否会员
interestsRuleList = cardInfo['result']['interestsRuleList']
if interestsRuleList == None:
if user_num == 1:
printinfo("\t\t└查询该店入会没有送豆,不入会", printlog)
return 0, 0
try:
if len(interestsRuleList) > 0:
for i in interestsRuleList:
if "京豆" in i['prizeName']:
getBean = int(i['discountString'])
activityId = i['interestsInfo']['activityId']
context = "{0}".format(shopid)
outfile(f"shopid-{today}.txt", context, False) # 记录所有送豆的shopid
in_url = 'https://shop.m.jd.com/?shopId={}'.format(shopid)
url = 'https://shopmember.m.jd.com/member/memberCloseAccount?venderId={}'.format(venderId)
context = "[{0}]:入会{2}豆店铺【{1}\n\t加入会员:{4}\n\t解绑会员:{3}".format(nowtime(), venderCardName, getBean,
url, in_url) # 记录
if user_num == 1:
outfile("入会汇总.txt", context, False)
if getBean >= openCardBean: # 判断豆是否符合您的需求
print(f"\t└账号{user_num}{userName}{venderCardName}:入会赠送【{getBean}豆】,可入会")
context = "{0}".format(shopid)
outfile(f"入会{openCardBean}豆以上的shopid-{today}.txt", context, False)
if onlyRecord == True:
if user_num == 1:
print("已开启仅记录,不入会。")
return 2, 2
if openCardStatus == 1:
url = 'https://shopmember.m.jd.com/member/memberCloseAccount?venderId={}'.format(venderId)
print("\t\t└[账号:{0}]:您已经是本店会员请注销会员卡24小时后再来~\n注销链接:{1}".format(userName, url))
context = "[{3}]:入会{1}豆,{0}销卡:{2}".format(venderCardName, getBean, url, nowtime())
outfile("可退会账号【{0}】.txt".format(userName), context, False)
return 1, 1
return activityId, getBean
else:
if user_num == 1:
print(f'\t\t{venderCardName}:入会送【{getBean}】豆少于【{openCardBean}豆】,不入...')
if onlyRecord == True:
if user_num == 1:
print("已开启仅记录,不入会。")
return 2, 2
return 0, openCardStatus
else:
pass
if user_num == 1:
printinfo("\t\t└查询该店入会没有送豆,不入会", printlog)
return 0, 0
else:
return 0, 0
except Exception as e:
print(e)
# 开卡
def bindWithVender(venderId, shopId, activityId, channel, headers):
"""
:param venderId:
:param shopId:
:param activityId:
:param channel:
:param headers:
:return: result : 开卡结果
"""
num = string.ascii_letters + string.digits
v_name = ''.join(random.sample(num, 10))
num1 = string.digits
v_num1 = ''.join(random.sample(["1", "2", "3", "4", "5", "6", "7", "8", "9"], 1)) + ''.join(random.sample(num1, 4))
qq_num = ''.join(random.sample(["1", "2", "3", "4", "5", "6", "7", "8", "9"], 1)) + ''.join(
random.sample(num1, 8)) + "@qq.com"
url = 'https://api.m.jd.com/client.action?appid=jd_shop_member&functionId=bindWithVender&body=%7B%22venderId%22%3A%22{4}%22%2C%22shopId%22%3A%22{7}%22%2C%22bindByVerifyCodeFlag%22%3A1%2C%22registerExtend%22%3A%7B%22v_sex%22%3A%22%E6%9C%AA%E7%9F%A5%22%2C%22v_name%22%3A%22{0}%22%2C%22v_birthday%22%3A%221990-03-18%22%2C%22v_email%22%3A%22{6}%22%7D%2C%22writeChildFlag%22%3A0%2C%22activityId%22%3A{5}%2C%22channel%22%3A{3}%7D&client=H5&clientVersion=9.2.0&uuid=&jsonp=jsonp_{1}_{2}'.format(
v_name, timestamp, v_num1, channel, venderId, activityId, qq_num, shopId)
try:
respon = requests.get(url=url, verify=False, headers=headers, timeout=60)
result = respon.text
return result
except Exception as e:
print(e)
# 获取开卡结果
def getResult(resulttxt, userName, user_num):
r = re.compile(r'jsonp_.*?\((.*?)\)\;', re.M | re.S | re.I)
result = r.findall(resulttxt)
for i in result:
result_data = json.loads(i)
busiCode = result_data['busiCode']
if busiCode == '0':
message = result_data['message']
try:
result = result_data['result']['giftInfo']['giftList']
print(f"\t\t└账号{user_num}{userName}】:{message}")
for i in result:
print("\t\t\t{0}:{1} ".format(i['prizeTypeName'], i['discount']))
except:
print(f'\t\t└账号{user_num}{userName}】:{message}')
return busiCode
else:
print("\t\t└账号{0}{1}】:{2}".format(user_num, userName, result_data['message']))
return busiCode
def getRemoteShopid():
global shopidList, venderidList
shopidList = []
venderidList = []
url = base64.decodebytes(
b"aHR0cHM6Ly9naXRlZS5jb20vY3VydGlubHYvUHVibGljL3Jhdy9tYXN0ZXIvT3BlbkNhcmQvc2hvcGlkLnR4dA==")
try:
rShopid = gettext(url)
rShopid = rShopid.split("\n")
for i in rShopid:
if len(i) > 0:
shopidList.append(i.split(':')[0])
venderidList.append(i.split(':')[1])
return shopidList, venderidList
except:
print("无法从远程获取shopid")
exitCodeFun(999)
# 读取shopid.txt
def getShopID():
shopid_path = pwd + "shopid.txt"
try:
with open(shopid_path, "r", encoding="utf-8") as f:
shopid = f.read()
if len(shopid) > 0:
shopid = shopid.split("\n")
return shopid
else:
print("Error:请检查shopid.txt文件是否正常\n")
exitCodeFun(2)
except Exception as e:
print("Error:请检查shopid.txt文件是否正常\n", e)
exitCodeFun(2)
# 进度条
def progress_bar(start, end, threadNum):
print("\r", end="")
if threadNum == 2:
start2 = start - midNum
end2 = end - midNum
print("\n###[{1}]:线程{2}【当前进度: {0}%\n".format(round(start2 / end2 * 100, 2), nowtime(), threadNum))
elif threadNum == 1:
print("\n###[{1}]:线程{2}【当前进度: {0}%\n".format(round(start / end * 100, 2), nowtime(), threadNum))
sys.stdout.flush()
## 多账号并发
def sss(ii, ck, userName, pinName, endNum, user_num, shopids, threadNum):
if ii % 10 == 0 and ii != 0 and user_num == 1:
progress_bar(ii, endNum, threadNum)
try:
if len(shopids[ii]) > 0:
headers_b = setHeaders(ck, "mall") # 获取请求头
if isRemoteSid:
venderId = venderidList[shopidList.index(shopids[ii])]
else:
venderId = getVenderId(shopids[ii], headers_b) # 获取venderId
time.sleep(sleepNum) # 根据您需求是否限制请求速度
# 新增记忆功能
memoryFun(ii, threadNum, True, pinName, 0, allUserCount)
headers_a = setHeaders(ck, "mh5")
activityId, getBean = getShopOpenCardInfo(venderId, headers_a, shopids[ii], userName, user_num) # 获取入会礼包结果
# activityId,getBean 或 返回 0:没豆 1:有豆已是会员 2:记录模式(不入会)
time.sleep(sleepNum) # 根据账号需求是否限制请求速度
if activityId == 0 or activityId == 2:
pass
elif activityId > 10:
headers = setHeaders(ck, "JDApp")
result = bindWithVender(venderId, shopids[ii], activityId, 208, headers)
busiCode = getResult(result, userName, user_num)
if busiCode == '0':
memoryFun(ii, threadNum, False, pinName, getBean, allUserCount)
memoryJson = getMemory()
print(f"账号{user_num}:【{userName}】累计获得:{memoryJson['{}'.format(pinName)]} 京豆")
time.sleep(sleepNum)
else:
pass
except Exception as e:
if user_num == 1:
print(f"【Error】多账号并发报错请求过快建议适当调整 sleepNum 参数限制速度 \n{e}")
# 为多线程准备
def OpenVipCard(startNum: int, endNum: int, shopids, cookies, userNames, pinNameList, threadNum):
sssLabel = 0
for i in range(startNum, endNum):
user_num = 1
if Concurrent:
if sssLabel == 0 and threadNum == 1:
if DoubleThread:
message("当前模式: 双线程,多账号并发运行")
else:
message("当前模式: 单线程,多账号并发运行")
sssLabel = 1
threads = []
for ck, userName, pinName in zip(cookies, userNames, pinNameList):
tt = TaskThread(sss, args=(i, ck, userName, pinName, endNum, user_num, shopids, threadNum))
threads.append(tt)
tt.start()
user_num += 1
time.sleep(sleepNum)
for t in threads:
t.join()
time.sleep(sleepNum)
else:
if sssLabel == 0 and threadNum == 1:
if DoubleThread:
message("当前模式: 双线程,单账号运行")
else:
message("当前模式: 单线程,单账号运行")
sssLabel = 1
activityIdLabel = 0
for ck, userName, pinName in zip(cookies, userNames, pinNameList):
if i % 10 == 0 and i != 0:
progress_bar(i, endNum, threadNum)
try:
if len(shopids[i]) > 0:
headers_b = setHeaders(ck, "mall") # 获取请求头
venderId = getVenderId(shopids[i], headers_b) # 获取venderId
time.sleep(sleepNum) # 根据账号需求是否限制请求速度
# 新增记忆功能
memoryFun(i, threadNum, True, pinName, 0, allUserCount)
if activityIdLabel == 0:
s = random.randint(0, allUserCount - 1)
headers_a = setHeaders(cookies[s], "mh5")
activityId, getBean = getShopOpenCardInfo(venderId, headers_a, shopids[i], userName,
user_num) # 获取入会礼包结果
# activityId,getBean 或 返回 0:没豆 1:有豆已是会员 2:记录模式(不入会)
time.sleep(sleepNum) # 根据账号需求是否限制请求速度
if activityId == 0 or activityId == 2:
break
elif activityId == 1:
user_num += 1
continue
elif activityId > 10:
activityIdLabel = 1
headers = setHeaders(ck, "JDApp")
result = bindWithVender(venderId, shopids[i], activityId, 208, headers)
busiCode = getResult(result, userName, user_num)
if busiCode == '0':
memoryFun(i, threadNum, False, pinName, getBean, allUserCount)
memoryJson = getMemory()
print(f"账号{user_num}:【{userName}】累计获得:{memoryJson['{}'.format(pinName)]} 京豆")
time.sleep(sleepNum)
else:
break
except Exception as e:
user_num += 1
print(e)
continue
user_num += 1
# start
def start():
global allUserCount
print(scriptHeader)
outfile("Readme.md", readmes, True)
isUpdate()
global endShopidNum, midNum, allUserCount
if isRemoteSid:
message("已启用远程获取shopid")
allShopid, venderidList = getRemoteShopid()
else:
message("从本地shopid.txt获取shopid")
allShopid = getShopID()
allShopid = list(set(allShopid))
endShopidNum = len(allShopid)
midNum = int(endShopidNum / 2)
message("获取到店铺数量: {}".format(endShopidNum))
message(f"您已设置入会条件:{openCardBean} 京豆")
print("获取账号...")
cookies, userNames, pinNameList = iscookie()
allUserCount = len(cookies)
message("{}个有效账号".format(allUserCount))
memorylabel = 0
startNum1 = 0
startNum2 = midNum
starttime = time.perf_counter() # 记录时间开始
if endShopidNum > 1 and DoubleThread:
# 如果启用记忆功能,则获取上一次记忆位置
startNum1, startNum2, memorylabel = isMemory(memorylabel, startNum1, startNum2, midNum, endShopidNum,
pinNameList)
# 多线程部分
threads = []
t1 = Thread(target=OpenVipCard, args=(startNum1, midNum, allShopid, cookies, userNames, pinNameList, 1))
threads.append(t1)
t2 = Thread(target=OpenVipCard, args=(startNum2, endShopidNum, allShopid, cookies, userNames, pinNameList, 2))
threads.append(t2)
try:
for t in threads:
t.setDaemon(True)
t.start()
for t in threads:
t.join()
isSuccess = True
progress_bar(1, 1, 1)
progress_bar(1, 1, 2)
except:
isSuccess = False
elif endShopidNum == 1 or not DoubleThread:
startNum1, startNum2, memorylabel = isMemory(memorylabel, startNum1, startNum2, midNum, endShopidNum,
pinNameList)
OpenVipCard(startNum1, endShopidNum, allShopid, cookies, userNames, pinNameList, 1)
isSuccess = True
else:
message("获取到shopid数量为0")
exitCodeFun(9)
endtime = time.perf_counter() # 记录时间结束
if os.path.exists(pwd + "log/memory.json"):
memoryJson = getMemory()
n = 1
message("\n###【本次统计 {}】###\n".format(nowtime()))
all_get_bean = 0
for name, pinname in zip(userNames, pinNameList):
try:
userCountBean = memoryJson['{}'.format(pinname)]
successJoin = memoryJson['{}_ok'.format(pinname)]
message(f"账号{n}:【{name}\n\t└成功入会【{successJoin}】个,收获【{userCountBean}】京豆")
all_get_bean += userCountBean
except Exception as e:
message(f"账号{n}:【{name}\n\t└成功入会【0】个收获【0】京豆")
n += 1
message(f"\n本次总累计获得:{all_get_bean} 京豆")
time.sleep(1)
message("\n------- 入会总耗时 : %.03f 秒 seconds -------" % (endtime - starttime))
print("{0}\n{1}\n{2}".format("*" * 30, scriptHeader, remarks))
send("【JD入会领豆】", message_info)
exitCodeFun(0)
if __name__ == '__main__':
start()