From 567e88a9454d016a1658ffd8b74a2fbeeed03dd1 Mon Sep 17 00:00:00 2001
From: cycz <838143144@qq.com>
Date: Mon, 25 Jan 2021 00:27:56 +0800
Subject: [PATCH] goodbye
---
AreaTool.py | 11 -
README.md | 16 +-
config.py | 22 --
configDemo.ini | 40 ----
jdBuyMask.py | 488 ------------------------------------------
jdBuyMask_V2.py | 551 ------------------------------------------------
jdBuyMask_V3.py | 492 ------------------------------------------
jdEmail.py | 41 ----
jdProgram.py | 219 -------------------
jdlogger.py | 26 ---
message.py | 37 ----
util.py | 45 ----
wechat_ftqq.py | 31 ---
13 files changed, 5 insertions(+), 2014 deletions(-)
delete mode 100644 AreaTool.py
delete mode 100644 config.py
delete mode 100644 configDemo.ini
delete mode 100644 jdBuyMask.py
delete mode 100644 jdBuyMask_V2.py
delete mode 100644 jdBuyMask_V3.py
delete mode 100644 jdEmail.py
delete mode 100644 jdProgram.py
delete mode 100644 jdlogger.py
delete mode 100644 message.py
delete mode 100644 util.py
delete mode 100644 wechat_ftqq.py
diff --git a/AreaTool.py b/AreaTool.py
deleted file mode 100644
index 62afe52..0000000
--- a/AreaTool.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# -*- coding=utf-8 -*-
-from jdlogger import logger
-
-'''
-测试 https://c0.3.cn/stock?skuId=100003406321&area=19_1607_4773_0&venderId=1000000946&buyNum=1&choseSuitSkuIds=&cat=9192,9197,12588&extraParam={%22originid%22:%221%22}&fqsp=0&pdpin=jd_7c3992aa27d1a&pduid=1580535906442142991701&ch=1&callback=jQuery4291064
-请看教程寻找自己的url
-'''
-url = ''
-skuId = url.split('skuId=')[1].split('&')[0]
-area = url.split('area=')[1].split('&')[0]
-logger.info('你的area是[ %s ],链接的商品id是[ %s ]', area, skuId)
diff --git a/README.md b/README.md
index 38ab36e..6409df0 100644
--- a/README.md
+++ b/README.md
@@ -1,18 +1,12 @@
****
-ãݲˡ
+ٷֿ֪ͨʹ88
-exe汾ܹһʱڡ
+¼һ¿ֵѷԱʹü
-ף**Լ**Ŀ
-****
-ʹ÷ https://blog.csdn.net/cyz52/article/details/104239558
-## exe汾[С] 99ֿ
-ӣhttps://pan.baidu.com/s/1bgGXsH071GkHWGlLIwgRVw
-ȡ룺do3f
-
-ת֣ĽӿѾ
-Ҫ˵ԭȺҪɣ1053467385
+л湤ҲԺ˽ѯ
+ټ
+****
ף
diff --git a/config.py b/config.py
deleted file mode 100644
index 661a502..0000000
--- a/config.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# -*- coding: utf-8 -*-
-import os
-import configparser
-
-
-class Config(object):
- def __init__(self, config_file='configDemo.ini'):
- self._path = os.path.join(os.getcwd(), config_file)
- if not os.path.exists(self._path):
- raise FileNotFoundError("No such file: config.ini")
- self._config = configparser.ConfigParser()
- self._config.read(self._path, encoding='utf-8-sig')
- self._configRaw = configparser.RawConfigParser()
- self._configRaw.read(self._path, encoding='utf-8-sig')
-
- def get(self, section, name):
- return self._config.get(section, name)
-
- def getRaw(self, section, name):
- return self._configRaw.get(section, name)
-
-
diff --git a/configDemo.ini b/configDemo.ini
deleted file mode 100644
index 9a8083f..0000000
--- a/configDemo.ini
+++ /dev/null
@@ -1,40 +0,0 @@
-[config]
-
-
-# 地区id (不知道怎么获取的使用一下AreaTool.py工具)
-area = 19_1607_4773_0
-# cookie
-cookies_String = shshshfpa=21a5db2
-# 推送方式 1为邮箱,2为微信
-messageType =1
-# mail
-mail = xxxxxx@qq.com
-# sc_key 方糖微信推送的key 不知道的请看http://sc.ftqq.com/3.version
-sc_key = test
-
-# 支付密码
-# 如果你的账户中有可用的京券(注意不是东券)或 在上次购买订单中使用了京豆,
-# 那么京东可能会在下单时自动选择京券支付 或 自动勾选京豆支付。
-# 此时下单会要求输入六位数字的支付密码。请在下方配置你的支付密码,如 123456 。
-# 如果没有上述情况,下方请留空。
-payment_pwd =
-#暂时不填写
-
-
-[V2]
-# skuids 英文逗号[,]相隔 (分清楚英文和中文逗号) 末尾不要带逗号
-skuids = 3088512,65437208345,7498169,7498165,7263128,7498167,17449572304,37934196731,100001086804,56657322838,56657322841,100005294853,1938795,15595191653,15595191654,45923412989
-# V2版本下单速度区分 极速模式 【1】 和 正常模式 【2】(极速模式缩短不必要的流程)
-model = 1
-
-[V3]
-# v3版本的skuid,最多写一件
-skuid = 3088512
-
-
-[Temporary]
-#一般不需要修改
-eid =
-fp =
-# 打码服务器
-captchaUrl = http://122.51.18.81:8111/pic
\ No newline at end of file
diff --git a/jdBuyMask.py b/jdBuyMask.py
deleted file mode 100644
index 67461f8..0000000
--- a/jdBuyMask.py
+++ /dev/null
@@ -1,488 +0,0 @@
-# -*- coding=utf-8 -*-
-'''
-京东抢购口罩程序
-'''
-import requests
-import time
-import json
-import sys
-import random
-from bs4 import BeautifulSoup
-from jdlogger import logger
-from message import message
-import traceback
-
-'''
-需要修改
-'''
-# cookie 网页获取
-cookies_String = 'xxxxxxx'
-
-# 推送方式 1(mail)或 2(wechat)
-messageType = 1
-
-# 有货通知 收件邮箱
-mail = 'xxxxxx@qq.com'
-
-# 方糖微信推送的key 不知道的请看http://sc.ftqq.com/3.version
-sc_key = ''
-
-# 商品的url
-urls = [
- # 'https://c0.3.cn/stock?skuId=1336984&area=19_1607_4773_0&venderId=1000078145&buyNum=1&choseSuitSkuIds=&cat=9192,12190,1517&extraParam={%22originid%22:%221%22}&fqsp=0&pdpin=jd_7c3992aa27d1a&pduid=1580535906442142991701&ch=1&callback=jQuery6715489',
- # 'https://c0.3.cn/stock?skuId=4642656&area=19_1607_4773_0&venderId=1000006724&buyNum=1&choseSuitSkuIds=&cat=9192,12190,1517&extraParam={%22originid%22:%221%22}&fqsp=0&pdpin=jd_7c3992aa27d1a&pduid=1580535906442142991701&ch=1&callback=jQuery4552086',
- # 'https://c0.3.cn/stock?skuId=65466451629&area=19_1607_4773_0&venderId=127922&buyNum=1&choseSuitSkuIds=&cat=9855,9858,9924&extraParam={%22originid%22:%221%22}&fqsp=0&pdpin=jd_7c3992aa27d1a&pduid=1580535906442142991701&ch=1&callback=jQuery2790674',
- # 'https://c0.3.cn/stock?skuId=65437208345&area=19_1607_4773_0&venderId=127922&buyNum=1&choseSuitSkuIds=&cat=9855,9858,9924&extraParam={%22originid%22:%221%22}&fqsp=0&pdpin=jd_7c3992aa27d1a&pduid=1580535906442142991701&ch=1&callback=jQuery1749958',
- # 'https://c0.3.cn/stock?skuId=7498169&area=19_1607_4773_0&venderId=1000128491&buyNum=1&choseSuitSkuIds=&cat=9855,9858,9924&extraParam={%22originid%22:%221%22}&fqsp=0&pdpin=jd_7c3992aa27d1a&pduid=15631231857651045904648&ch=1&callback=jQuery4102801',
- # 'https://c0.3.cn/stock?skuId=7498165&area=19_1607_4773_0&venderId=1000128491&buyNum=1&choseSuitSkuIds=&cat=9855,9858,9924&extraParam={%22originid%22:%221%22}&fqsp=0&pdpin=jd_7c3992aa27d1a&pduid=15631231857651045904648&ch=1&callback=jQuery9614479',
- 'https://c0.3.cn/stock?skuId=7263128&area=19_1607_4773_0&venderId=1000128491&buyNum=1&choseSuitSkuIds=&cat=9855,9858,9924&extraParam={%22originid%22:%221%22}&fqsp=0&pdpin=jd_7c3992aa27d1a&pduid=15631231857651045904648&ch=1&callback=jQuery8872960',
- # 'https://c0.3.cn/stock?skuId=1739089&area=19_1607_4773_0&venderId=1000017287&buyNum=1&choseSuitSkuIds=&cat=15248,15250,15278&extraParam={%22originid%22:%221%22}&fqsp=0&pdpin=jd_7c3992aa27d1a&pduid=1580535906442142991701&ch=1&callback=jQuery4479703'
-]
-
-'''
-备用
-'''
-
-
-# eid
-eid = ''
-fp = ''
-# 支付密码
-payment_pwd = ''
-message = message(messageType=messageType, sc_key=sc_key, mail=mail)
-session = requests.session()
-session.headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Connection": "keep-alive"
-}
-manual_cookies = {}
-
-
-def get_tag_value(tag, key='', index=0):
- if key:
- value = tag[index].get(key)
- else:
- value = tag[index].text
- return value.strip(' \t\r\n')
-
-
-def response_status(resp):
- if resp.status_code != requests.codes.OK:
- print('Status: %u, Url: %s' % (resp.status_code, resp.url))
- return False
- return True
-
-
-for item in cookies_String.split(';'):
- name, value = item.strip().split('=', 1)
- # 用=号分割,分割1次
- manual_cookies[name] = value
- # 为字典cookies添加内容
-
-cookiesJar = requests.utils.cookiejar_from_dict(manual_cookies, cookiejar=None, overwrite=True)
-session.cookies = cookiesJar
-
-
-def validate_cookies():
- for flag in range(1, 3):
- try:
- targetURL = 'https://order.jd.com/center/list.action'
- payload = {
- 'rid': str(int(time.time() * 1000)),
- }
- resp = session.get(url=targetURL, params=payload, allow_redirects=False)
- if resp.status_code == requests.codes.OK:
- logger.info('登录成功')
- return True
- else:
- logger.info('第【%s】次请重新获取cookie', flag)
- time.sleep(5)
- continue
- except Exception as e:
- logger.info('第【%s】次请重新获取cookie', flag)
- time.sleep(5)
- continue
-
-
-def getUsername():
- userName_Url = 'https://passport.jd.com/new/helloService.ashx?callback=jQuery339448&_=' + str(
- int(time.time() * 1000))
- session.headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Referer": "https://order.jd.com/center/list.action",
- "Connection": "keep-alive"
- }
- resp = session.get(url=userName_Url, allow_redirects=True)
- resultText = resp.text
- resultText = resultText.replace('jQuery339448(', '')
- resultText = resultText.replace(')', '')
- usernameJson = json.loads(resultText)
- logger.info('登录账号名称' + usernameJson['nick'])
-
-
-'''
-检查是否有货
-'''
-
-
-def check_item_stock(itemUrl):
- response = session.get(itemUrl)
- if (response.text.find('无货') > 0):
- return True
- else:
- return False
-
-
-'''
-取消勾选购物车中的所有商品
-'''
-
-
-def cancel_select_all_cart_item():
- url = "https://cart.jd.com/cancelAllItem.action"
- data = {
- 't': 0,
- 'outSkus': '',
- 'random': random.random()
- }
- resp = session.post(url, data=data)
- if resp.status_code != requests.codes.OK:
- print('Status: %u, Url: %s' % (resp.status_code, resp.url))
- return False
- return True
-
-
-'''
-购物车详情
-'''
-
-
-def cart_detail():
- url = 'https://cart.jd.com/cart.action'
- headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Referer": "https://order.jd.com/center/list.action",
- "Host": "cart.jd.com",
- "Connection": "keep-alive"
- }
- resp = session.get(url, headers=headers)
- soup = BeautifulSoup(resp.text, "html.parser")
-
- cart_detail = dict()
- for item in soup.find_all(class_='item-item'):
- try:
- sku_id = item['skuid'] # 商品id
- except Exception as e:
- logger.info('购物车中有套装商品,跳过')
- continue
- try:
- # 例如:['increment', '8888', '100001071956', '1', '13', '0', '50067652554']
- # ['increment', '8888', '100002404322', '2', '1', '0']
- item_attr_list = item.find(class_='increment')['id'].split('_')
- p_type = item_attr_list[4]
- promo_id = target_id = item_attr_list[-1] if len(item_attr_list) == 7 else 0
-
- cart_detail[sku_id] = {
- 'name': get_tag_value(item.select('div.p-name a')), # 商品名称
- 'verder_id': item['venderid'], # 商家id
- 'count': int(item['num']), # 数量
- 'unit_price': get_tag_value(item.select('div.p-price strong'))[1:], # 单价
- 'total_price': get_tag_value(item.select('div.p-sum strong'))[1:], # 总价
- 'is_selected': 'item-selected' in item['class'], # 商品是否被勾选
- 'p_type': p_type,
- 'target_id': target_id,
- 'promo_id': promo_id
- }
- except Exception as e:
- logger.error("商品%s在购物车中的信息无法解析,报错信息: %s,该商品自动忽略", sku_id, e)
-
- logger.info('购物车信息:%s', cart_detail)
- return cart_detail
-
-
-'''
-修改购物车商品的数量
-'''
-
-
-def change_item_num_in_cart(sku_id, vender_id, num, p_type, target_id, promo_id):
- url = "https://cart.jd.com/changeNum.action"
- data = {
- 't': 0,
- 'venderId': vender_id,
- 'pid': sku_id,
- 'pcount': num,
- 'ptype': p_type,
- 'targetId': target_id,
- 'promoID': promo_id,
- 'outSkus': '',
- 'random': random.random(),
- # 'locationId'
- }
- session.headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Referer": "https://cart.jd.com/cart",
- "Connection": "keep-alive"
- }
- resp = session.post(url, data=data)
- return json.loads(resp.text)['sortedWebCartResult']['achieveSevenState'] == 2
-
-
-'''
-添加商品到购物车
-'''
-
-
-def add_item_to_cart(sku_id):
- url = 'https://cart.jd.com/gate.action'
- payload = {
- 'pid': sku_id,
- 'pcount': 1,
- 'ptype': 1,
- }
- resp = session.get(url=url, params=payload)
- if 'https://cart.jd.com/cart.action' in resp.url: # 套装商品加入购物车后直接跳转到购物车页面
- result = True
- else: # 普通商品成功加入购物车后会跳转到提示 "商品已成功加入购物车!" 页面
- soup = BeautifulSoup(resp.text, "html.parser")
- result = bool(soup.select('h3.ftx-02')) # [
商品已成功加入购物车!
]
-
- if result:
- logger.info('%s 已成功加入购物车', sku_id)
- else:
- logger.error('%s 添加到购物车失败', sku_id)
-
-
-def get_checkout_page_detail():
- """获取订单结算页面信息
-
- 该方法会返回订单结算页面的详细信息:商品名称、价格、数量、库存状态等。
-
- :return: 结算信息 dict
- """
- url = 'http://trade.jd.com/shopping/order/getOrderInfo.action'
- # url = 'https://cart.jd.com/gotoOrder.action'
- payload = {
- 'rid': str(int(time.time() * 1000)),
- }
- headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Referer": "https://cart.jd.com/cart.action",
- "Connection": "keep-alive",
- 'Host': 'trade.jd.com',
- }
- try:
- resp = session.get(url=url, params=payload, headers=headers)
- if not response_status(resp):
- logger.error('获取订单结算页信息失败')
- return ''
-
- soup = BeautifulSoup(resp.text, "html.parser")
- risk_control = get_tag_value(soup.select('input#riskControl'), 'value')
-
- order_detail = {
- 'address': soup.find('span', id='sendAddr').text[5:], # remove '寄送至: ' from the begin
- 'receiver': soup.find('span', id='sendMobile').text[4:], # remove '收件人:' from the begin
- 'total_price': soup.find('span', id='sumPayPriceId').text[1:], # remove '¥' from the begin
- 'items': []
- }
-
- logger.info("下单信息:%s", order_detail)
- return order_detail
- except requests.exceptions.RequestException as e:
- logger.error('订单结算页面获取异常:%s' % e)
- except Exception as e:
- logger.error('下单页面数据解析异常:%s', e)
- return risk_control
-
-
-def submit_order(risk_control,sku_id):
-
-
- """提交订单
-
- 重要:
- 1.该方法只适用于普通商品的提交订单(即可以加入购物车,然后结算提交订单的商品)
- 2.提交订单时,会对购物车中勾选✓的商品进行结算(如果勾选了多个商品,将会提交成一个订单)
-
- :return: True/False 订单提交结果
- """
- url = 'https://trade.jd.com/shopping/order/submitOrder.action'
- # js function of submit order is included in https://trade.jd.com/shopping/misc/js/order.js?r=2018070403091
-
- # overseaPurchaseCookies:
- # vendorRemarks: []
- # submitOrderParam.sopNotPutInvoice: false
- # submitOrderParam.trackID: TestTrackId
- # submitOrderParam.ignorePriceChange: 0
- # submitOrderParam.btSupport: 0
- # riskControl:
- # submitOrderParam.isBestCoupon: 1
- # submitOrderParam.jxj: 1
- # submitOrderParam.trackId:
-
- data = {
- 'overseaPurchaseCookies': '',
- 'vendorRemarks': '[]',
- 'submitOrderParam.sopNotPutInvoice': 'false',
- 'submitOrderParam.trackID': 'TestTrackId',
- 'submitOrderParam.ignorePriceChange': '0',
- 'submitOrderParam.btSupport': '0',
- 'riskControl': risk_control,
- 'submitOrderParam.isBestCoupon': 1,
- 'submitOrderParam.jxj': 1,
- 'submitOrderParam.trackId': '9643cbd55bbbe103eef18a213e069eb0', # Todo: need to get trackId
- # 'submitOrderParam.eid': eid,
- # 'submitOrderParam.fp': fp,
- 'submitOrderParam.needCheck': 1,
- }
-
- def encrypt_payment_pwd(payment_pwd):
- return ''.join(['u3' + x for x in payment_pwd])
-
- if len(payment_pwd) > 0:
- data['submitOrderParam.payPassword'] = encrypt_payment_pwd(payment_pwd)
-
- headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Referer": "http://trade.jd.com/shopping/order/getOrderInfo.action",
- "Connection": "keep-alive",
- 'Host': 'trade.jd.com',
- }
- for count in range(1, 2):
- logger.info('第[%s/%s]次尝试提交订单', count, 3)
- try:
- resp = session.post(url=url, data=data, headers=headers)
- resp_json = json.loads(resp.text)
-
- # 返回信息示例:
- # 下单失败
- # {'overSea': False, 'orderXml': None, 'cartXml': None, 'noStockSkuIds': '', 'reqInfo': None, 'hasJxj': False, 'addedServiceList': None, 'sign': None, 'pin': 'xxx', 'needCheckCode': False, 'success': False, 'resultCode': 60123, 'orderId': 0, 'submitSkuNum': 0, 'deductMoneyFlag': 0, 'goJumpOrderCenter': False, 'payInfo': None, 'scaleSkuInfoListVO': None, 'purchaseSkuInfoListVO': None, 'noSupportHomeServiceSkuList': None, 'msgMobile': None, 'addressVO': None, 'msgUuid': None, 'message': '请输入支付密码!'}
- # {'overSea': False, 'cartXml': None, 'noStockSkuIds': '', 'reqInfo': None, 'hasJxj': False, 'addedServiceList': None, 'orderXml': None, 'sign': None, 'pin': 'xxx', 'needCheckCode': False, 'success': False, 'resultCode': 60017, 'orderId': 0, 'submitSkuNum': 0, 'deductMoneyFlag': 0, 'goJumpOrderCenter': False, 'payInfo': None, 'scaleSkuInfoListVO': None, 'purchaseSkuInfoListVO': None, 'noSupportHomeServiceSkuList': None, 'msgMobile': None, 'addressVO': None, 'msgUuid': None, 'message': '您多次提交过快,请稍后再试'}
- # {'overSea': False, 'orderXml': None, 'cartXml': None, 'noStockSkuIds': '', 'reqInfo': None, 'hasJxj': False, 'addedServiceList': None, 'sign': None, 'pin': 'xxx', 'needCheckCode': False, 'success': False, 'resultCode': 60077, 'orderId': 0, 'submitSkuNum': 0, 'deductMoneyFlag': 0, 'goJumpOrderCenter': False, 'payInfo': None, 'scaleSkuInfoListVO': None, 'purchaseSkuInfoListVO': None, 'noSupportHomeServiceSkuList': None, 'msgMobile': None, 'addressVO': None, 'msgUuid': None, 'message': '获取用户订单信息失败'}
- # {"cartXml":null,"noStockSkuIds":"xxx","reqInfo":null,"hasJxj":false,"addedServiceList":null,"overSea":false,"orderXml":null,"sign":null,"pin":"xxx","needCheckCode":false,"success":false,"resultCode":600157,"orderId":0,"submitSkuNum":0,"deductMoneyFlag":0,"goJumpOrderCenter":false,"payInfo":null,"scaleSkuInfoListVO":null,"purchaseSkuInfoListVO":null,"noSupportHomeServiceSkuList":null,"msgMobile":null,"addressVO":{"pin":"xxx","areaName":"","provinceId":xx,"cityId":xx,"countyId":xx,"townId":xx,"paymentId":0,"selected":false,"addressDetail":"xx","mobile":"xx","idCard":"","phone":null,"email":null,"selfPickMobile":null,"selfPickPhone":null,"provinceName":null,"cityName":null,"countyName":null,"townName":null,"giftSenderConsigneeName":null,"giftSenderConsigneeMobile":null,"gcLat":0.0,"gcLng":0.0,"coord_type":0,"longitude":0.0,"latitude":0.0,"selfPickOptimize":0,"consigneeId":0,"selectedAddressType":0,"siteType":0,"helpMessage":null,"tipInfo":null,"cabinetAvailable":true,"limitKeyword":0,"specialRemark":null,"siteProvinceId":0,"siteCityId":0,"siteCountyId":0,"siteTownId":0,"skuSupported":false,"addressSupported":0,"isCod":0,"consigneeName":null,"pickVOname":null,"shipmentType":0,"retTag":0,"tagSource":0,"userDefinedTag":null,"newProvinceId":0,"newCityId":0,"newCountyId":0,"newTownId":0,"newProvinceName":null,"newCityName":null,"newCountyName":null,"newTownName":null,"checkLevel":0,"optimizePickID":0,"pickType":0,"dataSign":0,"overseas":0,"areaCode":null,"nameCode":null,"appSelfPickAddress":0,"associatePickId":0,"associateAddressId":0,"appId":null,"encryptText":null,"certNum":null,"used":false,"oldAddress":false,"mapping":false,"addressType":0,"fullAddress":"xxxx","postCode":null,"addressDefault":false,"addressName":null,"selfPickAddressShuntFlag":0,"pickId":0,"pickName":null,"pickVOselected":false,"mapUrl":null,"branchId":0,"canSelected":false,"address":null,"name":"xxx","message":null,"id":0},"msgUuid":null,"message":"xxxxxx商品无货"}
- # {'orderXml': None, 'overSea': False, 'noStockSkuIds': 'xxx', 'reqInfo': None, 'hasJxj': False, 'addedServiceList': None, 'cartXml': None, 'sign': None, 'pin': 'xxx', 'needCheckCode': False, 'success': False, 'resultCode': 600158, 'orderId': 0, 'submitSkuNum': 0, 'deductMoneyFlag': 0, 'goJumpOrderCenter': False, 'payInfo': None, 'scaleSkuInfoListVO': None, 'purchaseSkuInfoListVO': None, 'noSupportHomeServiceSkuList': None, 'msgMobile': None, 'addressVO': {'oldAddress': False, 'mapping': False, 'pin': 'xxx', 'areaName': '', 'provinceId': xx, 'cityId': xx, 'countyId': xx, 'townId': xx, 'paymentId': 0, 'selected': False, 'addressDetail': 'xxxx', 'mobile': 'xxxx', 'idCard': '', 'phone': None, 'email': None, 'selfPickMobile': None, 'selfPickPhone': None, 'provinceName': None, 'cityName': None, 'countyName': None, 'townName': None, 'giftSenderConsigneeName': None, 'giftSenderConsigneeMobile': None, 'gcLat': 0.0, 'gcLng': 0.0, 'coord_type': 0, 'longitude': 0.0, 'latitude': 0.0, 'selfPickOptimize': 0, 'consigneeId': 0, 'selectedAddressType': 0, 'newCityName': None, 'newCountyName': None, 'newTownName': None, 'checkLevel': 0, 'optimizePickID': 0, 'pickType': 0, 'dataSign': 0, 'overseas': 0, 'areaCode': None, 'nameCode': None, 'appSelfPickAddress': 0, 'associatePickId': 0, 'associateAddressId': 0, 'appId': None, 'encryptText': None, 'certNum': None, 'addressType': 0, 'fullAddress': 'xxxx', 'postCode': None, 'addressDefault': False, 'addressName': None, 'selfPickAddressShuntFlag': 0, 'pickId': 0, 'pickName': None, 'pickVOselected': False, 'mapUrl': None, 'branchId': 0, 'canSelected': False, 'siteType': 0, 'helpMessage': None, 'tipInfo': None, 'cabinetAvailable': True, 'limitKeyword': 0, 'specialRemark': None, 'siteProvinceId': 0, 'siteCityId': 0, 'siteCountyId': 0, 'siteTownId': 0, 'skuSupported': False, 'addressSupported': 0, 'isCod': 0, 'consigneeName': None, 'pickVOname': None, 'shipmentType': 0, 'retTag': 0, 'tagSource': 0, 'userDefinedTag': None, 'newProvinceId': 0, 'newCityId': 0, 'newCountyId': 0, 'newTownId': 0, 'newProvinceName': None, 'used': False, 'address': None, 'name': 'xx', 'message': None, 'id': 0}, 'msgUuid': None, 'message': 'xxxxxx商品无货'}
- # {"orderXml":null,"cartXml":null,"noStockSkuIds":"","reqInfo":null,"hasJxj":false,"overSea":false,"addedServiceList":null,"sign":null,"pin":null,"needCheckCode":true,"success":false,"resultCode":0,"orderId":0,"submitSkuNum":0,"deductMoneyFlag":0,"goJumpOrderCenter":false,"payInfo":null,"scaleSkuInfoListVO":null,"purchaseSkuInfoListVO":null,"noSupportHomeServiceSkuList":null,"msgMobile":null,"addressVO":null,"msgUuid":null,"message":"验证码不正确,请重新填写"}
- # 下单成功
- # {'overSea': False, 'orderXml': None, 'cartXml': None, 'noStockSkuIds': '', 'reqInfo': None, 'hasJxj': False, 'addedServiceList': None, 'sign': None, 'pin': 'xxx', 'needCheckCode': False, 'success': True, 'resultCode': 0, 'orderId': 8740xxxxx, 'submitSkuNum': 1, 'deductMoneyFlag': 0, 'goJumpOrderCenter': False, 'payInfo': None, 'scaleSkuInfoListVO': None, 'purchaseSkuInfoListVO': None, 'noSupportHomeServiceSkuList': None, 'msgMobile': None, 'addressVO': None, 'msgUuid': None, 'message': None}
-
- if resp_json.get('success'):
- logger.info('订单提交成功! 订单号:%s', resp_json.get('orderId'))
- return True
- else:
- resultMessage, result_code = resp_json.get('message'), resp_json.get('resultCode')
- if result_code == 0:
- # self._save_invoice()
- if '验证码不正确'in resultMessage:
- resultMessage = resultMessage + '(验证码错误)'
- else:
- resultMessage = resultMessage + '(下单商品可能为第三方商品,将切换为普通发票进行尝试)'
- elif result_code == 60077:
- resultMessage = resultMessage + '(可能是购物车为空 或 未勾选购物车中商品)'
- elif result_code == 60123:
- resultMessage = resultMessage + '(需要在payment_pwd参数配置支付密码)'
- for i in urls:
- if sku_id in i:
- urls.remove(i)
- logger.info('订单提交失败,避免死循环去除异常id[%s]',sku_id)
- logger.info('订单提交失败, 错误码:%s, 返回信息:%s', result_code, resultMessage)
- logger.info(resp_json)
- return False
- except Exception as e:
- print(traceback.format_exc())
- continue
-
-
-'''
-
-'''
-
-
-def item_removed(sku_id):
- headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Referer": "http://trade.jd.com/shopping/order/getOrderInfo.action",
- "Connection": "keep-alive",
- 'Host': 'item.jd.com',
- }
- url = 'https://item.jd.com/{}.html'.format(sku_id)
- page = requests.get(url=url, headers=headers)
- return '该商品已下柜' not in page.text
-
-
-'''
-购买环节
-测试三次
-'''
-
-
-def buyMask(sku_id):
- cancel_select_all_cart_item()
- cart = cart_detail()
- if sku_id in cart:
- logger.info('%s 已在购物车中,调整数量为 %s', sku_id, 1)
- cart_item = cart.get(sku_id)
- change_item_num_in_cart(
- sku_id=sku_id,
- vender_id=cart_item.get('vender_id'),
- num=1,
- p_type=cart_item.get('p_type'),
- target_id=cart_item.get('target_id'),
- promo_id=cart_item.get('promo_id')
- )
- else:
- add_item_to_cart(sku_id)
- risk_control = get_checkout_page_detail()
- if len(risk_control) > 0:
- if submit_order(risk_control,sku_id):
- return True
- return False
-
-
-flag = 1
-while (1):
- try:
- if flag == 1:
- validate_cookies()
- getUsername()
- checkSession = requests.Session()
- checkSession.headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Connection": "keep-alive"
- }
- logger.info('第' + str(flag) + '次 ')
- flag += 1
- for i in urls:
- # 商品url
- skuId = i.split('skuId=')[1].split('&')[0]
- skuidUrl = 'https://item.jd.com/' + skuId + '.html'
- response = checkSession.get(i)
- if (response.text.find('无货') > 0):
- logger.info('[%s]类型口罩无货', skuId)
- else:
- if item_removed(skuId):
- logger.info('[%s]类型口罩有货啦!马上下单', skuId)
- if buyMask(skuId):
- message.send(skuidUrl, False)
- sys.exit(1)
- else:
- message.send(skuidUrl, False)
- else:
- logger.info('[%s]类型口罩有货,但已下柜商品', skuId)
- timesleep = random.randint(3, 8)
- time.sleep(timesleep)
- if flag % 20 == 0:
- logger.info('校验是否还在登录')
- validate_cookies()
- except Exception as e:
-
- print(traceback.format_exc())
- time.sleep(10)
diff --git a/jdBuyMask_V2.py b/jdBuyMask_V2.py
deleted file mode 100644
index 2d67f53..0000000
--- a/jdBuyMask_V2.py
+++ /dev/null
@@ -1,551 +0,0 @@
-# -*- coding=utf-8 -*-
-'''
-2020/2/13
-(避免滥用,代码已经废弃,现已不更新,有需要请适量使用exe版本)
-京东抢购口罩程序
-通过商品的skuid、地区id抢购
-'''
-import sys
-
-import requests
-from bs4 import BeautifulSoup
-
-from config import Config
-from jdProgram import *
-from message import message
-from util import getconfigMd5, _setDNSCache
-
-global cookies_String, mail, sc_key, messageType, modelType, area, skuidsString, skuids, captchaUrl, eid, fp, payment_pwd
-
-
-def getconfig():
- global cookies_String, mail, sc_key, messageType, modelType, area, skuidsString, skuids, captchaUrl, eid, fp, payment_pwd
- global_config = Config()
- # cookie 网页获取
- cookies_String = global_config.getRaw('config', 'cookies_String')
- # 有货通知 收件邮箱
- mail = global_config.getRaw('config', 'mail')
- # 方糖微信推送的key 不知道的请看http://sc.ftqq.com/3.version
- sc_key = global_config.getRaw('config', 'sc_key')
- # 推送方式 1(mail)或 2(wechat)
- messageType = global_config.getRaw('config', 'messageType')
- # 下单模式
- modelType = global_config.getRaw('V2', 'model')
- # 地区id
- area = global_config.getRaw('config', 'area')
- # 商品id
- skuidsString = global_config.getRaw('V2', 'skuids')
- skuids = str(skuidsString).split(',')
- # 验证码服务地址
- captchaUrl = global_config.getRaw('Temporary', 'captchaUrl')
- if not modelType:
- logger.error('请在configDemo.ini文件填写下单model')
-
- if len(skuids[0]) == 0:
- logger.error('请在configDemo.ini文件中输入你的商品id')
- sys.exit(1)
- '''
- 备用
- '''
- # eid
- eid = global_config.getRaw('Temporary', 'eid')
- fp = global_config.getRaw('Temporary', 'fp')
- # 支付密码
- payment_pwd = global_config.getRaw('config', 'payment_pwd')
-
-
-# 初次
-configTime = int(time.time())
-getconfig()
-configMd5 = getconfigMd5()
-message = message(messageType=messageType, sc_key=sc_key, mail=mail)
-
-is_Submit_captcha = False
-submit_captcha_rid = ''
-submit_captcha_text = ''
-encryptClientInfo = ''
-submit_Time = 0
-session = requests.session()
-session.headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Connection": "keep-alive"
-}
-checksession = requests.session()
-checksession.headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Connection": "keep-alive"
-}
-manual_cookies = {}
-
-
-def get_tag_value(tag, key='', index=0):
- if key:
- value = tag[index].get(key)
- else:
- value = tag[index].text
- return value.strip(' \t\r\n')
-
-
-for item in cookies_String.split(';'):
- name, value = item.strip().split('=', 1)
- # 用=号分割,分割1次
- manual_cookies[name] = value
- # 为字典cookies添加内容
-
-cookiesJar = requests.utils.cookiejar_from_dict(manual_cookies, cookiejar=None, overwrite=True)
-session.cookies = cookiesJar
-
-
-def validate_cookies():
- for flag in range(1, 3):
- try:
- targetURL = 'https://order.jd.com/center/list.action'
- payload = {
- 'rid': str(int(time.time() * 1000)),
- }
- resp = session.get(url=targetURL, params=payload, allow_redirects=False)
- if resp.status_code == requests.codes.OK:
- logger.info('校验是否登录[成功]')
- return True
- else:
- logger.info('校验是否登录[失败]')
- logger.info('请在configDemo.ini文件下更新cookie')
- time.sleep(5)
- continue
- except Exception as e:
- logger.info('第【%s】次请重新获取cookie', flag)
- time.sleep(5)
- continue
- message.sendAny('脚本登录cookie失效了,请重新登录')
- sys.exit(1)
-
-
-def getUsername():
- userName_Url = 'https://passport.jd.com/new/helloService.ashx?callback=jQuery339448&_=' + str(
- int(time.time() * 1000))
- session.headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Referer": "https://order.jd.com/center/list.action",
- "Connection": "keep-alive"
- }
- resp = session.get(url=userName_Url, allow_redirects=True)
- resultText = resp.text
- resultText = resultText.replace('jQuery339448(', '')
- resultText = resultText.replace(')', '')
- usernameJson = json.loads(resultText)
- logger.info('登录账号名称[%s]', usernameJson['nick'])
-
-
-'''
-检查是否有货
-'''
-
-
-def check_item_stock(itemUrl):
- response = session.get(itemUrl)
- if (response.text.find('无货') > 0):
- return True
- else:
- return False
-
-
-'''
-取消勾选购物车中的所有商品
-'''
-
-
-def cancel_select_all_cart_item():
- url = "https://cart.jd.com/cancelAllItem.action"
- data = {
- 't': 0,
- 'outSkus': '',
- 'random': random.random()
- }
- resp = session.post(url, data=data)
- if resp.status_code != requests.codes.OK:
- print('Status: %u, Url: %s' % (resp.status_code, resp.url))
- return False
- return True
-
-
-'''
-购物车详情
-'''
-
-
-def cart_detail():
- url = 'https://cart.jd.com/cart.action'
- headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Referer": "https://order.jd.com/center/list.action",
- "Host": "cart.jd.com",
- "Connection": "keep-alive"
- }
- resp = session.get(url, headers=headers)
- soup = BeautifulSoup(resp.text, "html.parser")
-
- cart_detail = dict()
- for item in soup.find_all(class_='item-item'):
- try:
- sku_id = item['skuid'] # 商品id
- except Exception as e:
- logger.info('购物车中有套装商品,跳过')
- continue
- try:
- # 例如:['increment', '8888', '100001071956', '1', '13', '0', '50067652554']
- # ['increment', '8888', '100002404322', '2', '1', '0']
- item_attr_list = item.find(class_='increment')['id'].split('_')
- p_type = item_attr_list[4]
- promo_id = target_id = item_attr_list[-1] if len(item_attr_list) == 7 else 0
-
- cart_detail[sku_id] = {
- 'name': get_tag_value(item.select('div.p-name a')), # 商品名称
- 'verder_id': item['venderid'], # 商家id
- 'count': int(item['num']), # 数量
- 'unit_price': get_tag_value(item.select('div.p-price strong'))[1:], # 单价
- 'total_price': get_tag_value(item.select('div.p-sum strong'))[1:], # 总价
- 'is_selected': 'item-selected' in item['class'], # 商品是否被勾选
- 'p_type': p_type,
- 'target_id': target_id,
- 'promo_id': promo_id
- }
- except Exception as e:
- logger.error("商品%s在购物车中的信息无法解析,报错信息: %s,该商品自动忽略", sku_id, e)
-
- logger.info('购物车信息:%s', cart_detail)
- return cart_detail
-
-
-'''
-修改购物车商品的数量
-'''
-
-
-def change_item_num_in_cart(sku_id, vender_id, num, p_type, target_id, promo_id):
- url = "https://cart.jd.com/changeNum.action"
- data = {
- 't': 0,
- 'venderId': vender_id,
- 'pid': sku_id,
- 'pcount': num,
- 'ptype': p_type,
- 'targetId': target_id,
- 'promoID': promo_id,
- 'outSkus': '',
- 'random': random.random(),
- # 'locationId'
- }
- session.headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Referer": "https://cart.jd.com/cart",
- "Connection": "keep-alive"
- }
- resp = session.post(url, data=data)
- return json.loads(resp.text)['sortedWebCartResult']['achieveSevenState'] == 2
-
-
-'''
-添加商品到购物车
-'''
-
-
-def add_item_to_cart(sku_id):
- url = 'https://cart.jd.com/gate.action'
- payload = {
- 'pid': sku_id,
- 'pcount': 1,
- 'ptype': 1,
- }
- resp = session.get(url=url, params=payload)
- if 'https://cart.jd.com/cart.action' in resp.url: # 套装商品加入购物车后直接跳转到购物车页面
- result = True
- else: # 普通商品成功加入购物车后会跳转到提示 "商品已成功加入购物车!" 页面
- soup = BeautifulSoup(resp.text, "html.parser")
- result = bool(soup.select('h3.ftx-02')) # [商品已成功加入购物车!
]
-
- if result:
- logger.info('%s 已成功加入购物车', sku_id)
- else:
- logger.error('%s 添加到购物车失败', sku_id)
-
-
-def get_checkout_page_detail():
- """获取订单结算页面信息
-
- 该方法会返回订单结算页面的详细信息:商品名称、价格、数量、库存状态等。
-
- :return: 结算信息 dict
- """
- url = 'http://trade.jd.com/shopping/order/getOrderInfo.action'
- # url = 'https://cart.jd.com/gotoOrder.action'
- payload = {
- 'rid': str(int(time.time() * 1000)),
- }
- headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Referer": "https://cart.jd.com/cart.action",
- "Connection": "keep-alive",
- 'Host': 'trade.jd.com',
- }
- try:
- resp = session.get(url=url, params=payload, headers=headers)
- if not response_status(resp):
- logger.error('获取订单结算页信息失败')
- return ''
- if '刷新太频繁了' in resp.text:
- return '刷新太频繁了'
- soup = BeautifulSoup(resp.text, "html.parser")
- risk_control = get_tag_value(soup.select('input#riskControl'), 'value')
- showCheckCode = get_tag_value(soup.select('input#showCheckCode'), 'value')
- if not showCheckCode:
- pass
- else:
- if showCheckCode == 'true':
- logger.info('提交订单需要验证码')
- global is_Submit_captcha, encryptClientInfo
- encryptClientInfo = get_tag_value(soup.select('input#encryptClientInfo'), 'value')
- is_Submit_captcha = True
-
- order_detail = {
- 'address': soup.find('span', id='sendAddr').text[5:], # remove '寄送至: ' from the begin
- 'receiver': soup.find('span', id='sendMobile').text[4:], # remove '收件人:' from the begin
- 'total_price': soup.find('span', id='sumPayPriceId').text[1:], # remove '¥' from the begin
- 'items': []
- }
-
- logger.info("下单信息:%s", order_detail)
- return risk_control
- except requests.exceptions.RequestException as e:
- logger.error('订单结算页面获取异常:%s' % e)
- except Exception as e:
- logger.error('下单页面数据解析异常:%s', e)
- return ''
-
-
-'''
-下柜商品检测
-'''
-
-
-def item_removed(sku_id):
- headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Referer": "http://trade.jd.com/shopping/order/getOrderInfo.action",
- "Connection": "keep-alive",
- 'Host': 'item.jd.com',
- }
- url = 'https://item.jd.com/{}.html'.format(sku_id)
- page = requests.get(url=url, headers=headers)
- return '该商品已下柜' not in page.text
-
-
-'''
-购买环节
-测试三次
-'''
-
-
-def normalModeBuyMask(sku_id):
- cancel_select_all_cart_item()
- cart = cart_detail()
- if sku_id in cart:
- logger.info('%s 已在购物车中,调整数量为 %s', sku_id, 1)
- cart_item = cart.get(sku_id)
- change_item_num_in_cart(
- sku_id=sku_id,
- vender_id=cart_item.get('vender_id'),
- num=1,
- p_type=cart_item.get('p_type'),
- target_id=cart_item.get('target_id'),
- promo_id=cart_item.get('promo_id')
- )
- else:
- add_item_to_cart(sku_id)
- risk_control = get_checkout_page_detail()
- if risk_control == '刷新太频繁了':
- return False
- if len(risk_control) > 0:
- if submit_order(session, risk_control, sku_id, skuids, submit_Time, encryptClientInfo, is_Submit_captcha,
- payment_pwd, submit_captcha_text, submit_captcha_rid):
- return True
- return False
-
-
-def fastModeBuyMask(sku_id):
- add_item_to_cart(sku_id)
- risk_control = get_checkout_page_detail()
- if risk_control == '刷新太频繁了':
- return False
- if len(risk_control) > 0:
- if submit_order(session, risk_control, sku_id, skuids, submit_Time, encryptClientInfo, is_Submit_captcha,
- payment_pwd, submit_captcha_text, submit_captcha_rid):
- return True
- return False
-
-
-'''
-删除购物车选中商品
-'''
-
-
-def remove_item():
- url = "https://cart.jd.com/batchRemoveSkusFromCart.action"
- data = {
- 't': 0,
- 'null': '',
- 'outSkus': '',
- 'random': random.random(),
- 'locationId': '19-1607-4773-0'
- }
- headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.37",
- "Accept": "application/json, text/javascript, */*; q=0.01",
- "Referer": "https://cart.jd.com/cart.action",
- "Host": "cart.jd.com",
- "Content-Type": "application/x-www-form-urlencoded",
- "Accept-Encoding": "gzip, deflate, br",
- "Accept-Encoding": "zh-CN,zh;q=0.9,ja;q=0.8",
- "Origin": "https://cart.jd.com",
- "Connection": "keep-alive"
- }
- resp = session.post(url, data=data, headers=headers)
- logger.info('清空购物车')
- if resp.status_code != requests.codes.OK:
- print('Status: %u, Url: %s' % (resp.status_code, resp.url))
- return False
- return True
-
-
-def select_all_cart_item():
- url = "https://cart.jd.com/selectAllItem.action"
- data = {
- 't': 0,
- 'outSkus': '',
- 'random': random.random()
- }
- resp = session.post(url, data=data)
- if resp.status_code != requests.codes.OK:
- print('Status: %u, Url: %s' % (resp.status_code, resp.url))
- return False
- return True
-
-
-def normalModeAutoBuy(inStockSkuid):
- for skuId in inStockSkuid:
- if item_removed(skuId):
- global submit_Time
- submit_Time = int(time.time() * 1000)
- logger.info('[%s]类型口罩有货啦!马上下单', skuId)
- skuidUrl = 'https://item.jd.com/' + skuId + '.html'
- if normalModeBuyMask(skuId):
- message.send(skuidUrl, True)
- sys.exit(1)
- else:
- message.send(skuidUrl, False)
- else:
- logger.info('[%s]类型口罩有货,但已下柜商品', skuId)
-
-
-def fastModeAutoBuy(inStockSkuid):
- for skuId in inStockSkuid:
- global submit_Time
- submit_Time = int(time.time() * 1000)
- logger.info('[%s]类型口罩有货啦!马上下单', skuId)
- skuidUrl = 'https://item.jd.com/' + skuId + '.html'
- if fastModeBuyMask(skuId):
- message.send(skuidUrl, True)
- sys.exit(1)
- else:
- if item_removed(skuId):
- message.send(skuidUrl, False)
- else:
- logger.info('[%s]商品已下柜,商品列表中踢出', skuId)
- skuids.remove(skuId)
- select_all_cart_item()
- remove_item()
-
-
-def check_Config():
- global configMd5, configTime
- nowMd5 = getconfigMd5()
- configTime = time.time()
- if not nowMd5 == configMd5:
- logger.info('配置文件修改,重新读取文件')
- getconfig()
- configMd5 = nowMd5
-
-
-def normalMode():
- flag = 1
- while (1):
- try:
- if flag == 1:
- validate_cookies()
- getUsername()
- # 检测配置文件是否修改
- if int(time.time()) - configTime >= 60:
- check_Config()
- # modelType
- logger.info('第' + str(flag) + '次 ')
- flag += 1
- # 检测库存
- inStockSkuid = check_stock(checksession, skuids, area)
- # 下单任务
- normalModeAutoBuy(inStockSkuid)
- # 休眠模块
- timesleep = random.randint(1, 3) / 10
- time.sleep(timesleep)
- # 校验是否还在登录模块
- if flag % 100 == 0:
- logger.info('校验是否还在登录')
- validate_cookies()
- except Exception as e:
- print(traceback.format_exc())
- time.sleep(10)
-
-
-def fastMode():
- flag = 1
- while (1):
- try:
- if flag == 1:
- validate_cookies()
- getUsername()
- select_all_cart_item()
- remove_item()
- # 检测配置文件修改
- if int(time.time()) - configTime >= 600:
- check_Config()
- # modelType
- logger.info('第' + str(flag) + '次 ')
- flag += 1
- # 检测库存
- inStockSkuid = check_stock(checksession, skuids, area)
- # 下单任务
- fastModeAutoBuy(inStockSkuid)
- # 休眠模块
- timesleep = random.randint(1, 3) / 10
- time.sleep(timesleep)
- # 校验是否还在登录模块
- if flag % 100 == 0:
- logger.info('校验是否还在登录')
- validate_cookies()
- except Exception as e:
- print(traceback.format_exc())
- time.sleep(10)
-
-
-# _setDNSCache()
-if modelType == '2':
- logger.info('V2版本当前模式[普通模式]')
- normalMode()
-elif modelType == '1':
- logger.info('V2版本当前模式[极速模式]')
- fastMode()
diff --git a/jdBuyMask_V3.py b/jdBuyMask_V3.py
deleted file mode 100644
index 8774464..0000000
--- a/jdBuyMask_V3.py
+++ /dev/null
@@ -1,492 +0,0 @@
-# -*- coding=utf-8 -*-
-'''
-2020/2/13
-(避免滥用,代码已经废弃,现已不更新,有需要请适量使用exe版本)
-京东抢购口罩程序V3版本
-'''
-import sys
-import traceback
-
-from bs4 import BeautifulSoup
-
-from config import Config
-from jdProgram import *
-from jdlogger import logger
-from message import message
-from util import *
-from util import _setDNSCache
-
-'''
-需要修改
-'''
-global cookies_String, mail, sc_key, messageType, area, skuidsString, skuids, captchaUrl, eid, fp, payment_pwd
-
-
-def getconfig():
- global_config = Config()
- global cookies_String, mail, sc_key, messageType, area, skuidsString, skuids, captchaUrl, eid, fp, payment_pwd
- # cookie 网页获取
- cookies_String = global_config.getRaw('config', 'cookies_String')
- # 有货通知 收件邮箱
- mail = global_config.getRaw('config', 'mail')
- # 方糖微信推送的key 不知道的请看http://sc.ftqq.com/3.version
- sc_key = global_config.getRaw('config', 'sc_key')
- # 推送方式 1(mail)或 2(wechat)
- messageType = global_config.getRaw('config', 'messageType')
- # 地区id
- area = global_config.getRaw('config', 'area')
- # 商品id
- skuidsString = global_config.getRaw('V3', 'skuid')
- skuids = str(skuidsString).split(',')
- # 验证码服务地址
- captchaUrl = global_config.getRaw('Temporary', 'captchaUrl')
- if len(skuids[0]) == 0:
- logger.error('请在configDemo.ini文件中输入你的商品id')
- sys.exit(1)
- '''
- 备用
- '''
- # eid
- eid = global_config.getRaw('Temporary', 'eid')
- fp = global_config.getRaw('Temporary', 'fp')
- # 支付密码
- payment_pwd = global_config.getRaw('config', 'payment_pwd')
-
-
-# 初次
-configTime = int(time.time())
-getconfig()
-configMd5 = getconfigMd5()
-message = message(messageType=messageType, sc_key=sc_key, mail=mail)
-
-is_Submit_captcha = False
-submit_captcha_rid = ''
-submit_captcha_text = ''
-encryptClientInfo = ''
-submit_Time = 0
-session = requests.session()
-checksession = requests.session()
-session.headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Connection": "keep-alive"
-}
-checksession.headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Connection": "keep-alive"
-}
-manual_cookies = {}
-
-
-def get_tag_value(tag, key='', index=0):
- if key:
- value = tag[index].get(key)
- else:
- value = tag[index].text
- return value.strip(' \t\r\n')
-
-
-def response_status(resp):
- if resp.status_code != requests.codes.OK:
- print('Status: %u, Url: %s' % (resp.status_code, resp.url))
- return False
- return True
-
-
-for item in cookies_String.split(';'):
- name, value = item.strip().split('=', 1)
- # 用=号分割,分割1次
- manual_cookies[name] = value
- # 为字典cookies添加内容
-
-cookiesJar = requests.utils.cookiejar_from_dict(manual_cookies, cookiejar=None, overwrite=True)
-session.cookies = cookiesJar
-
-
-def validate_cookies():
- for flag in range(1, 3):
- try:
- targetURL = 'https://order.jd.com/center/list.action'
- payload = {
- 'rid': str(int(time.time() * 1000)),
- }
- resp = session.get(url=targetURL, params=payload, allow_redirects=False)
- if resp.status_code == requests.codes.OK:
- logger.info('登录成功')
- return True
- else:
- logger.info('第【%s】次请重新获取cookie', flag)
- time.sleep(5)
- continue
- except Exception as e:
- logger.info('第【%s】次请重新获取cookie', flag)
- time.sleep(5)
- continue
- message.sendAny('脚本登录cookie失效了,请重新登录')
- sys.exit(1)
-
-
-def getUsername():
- userName_Url = 'https://passport.jd.com/new/helloService.ashx?callback=jQuery339448&_=' + str(
- int(time.time() * 1000))
- session.headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Referer": "https://order.jd.com/center/list.action",
- "Connection": "keep-alive"
- }
- resp = session.get(url=userName_Url, allow_redirects=True)
- resultText = resp.text
- resultText = resultText.replace('jQuery339448(', '')
- resultText = resultText.replace(')', '')
- usernameJson = json.loads(resultText)
- logger.info('登录账号名称' + usernameJson['nick'])
-
-
-'''
-检查是否有货
-'''
-
-
-def check_item_stock(itemUrl):
- response = session.get(itemUrl)
- if (response.text.find('无货') > 0):
- return True
- else:
- return False
-
-
-'''
-取消勾选购物车中的所有商品
-'''
-
-
-def cancel_select_all_cart_item():
- url = "https://cart.jd.com/cancelAllItem.action"
- data = {
- 't': 0,
- 'outSkus': '',
- 'random': random.random()
- }
- resp = session.post(url, data=data)
- if resp.status_code != requests.codes.OK:
- print('Status: %u, Url: %s' % (resp.status_code, resp.url))
- return False
- return True
-
-
-'''
-勾选购物车中的所有商品
-'''
-
-
-def select_all_cart_item():
- url = "https://cart.jd.com/selectAllItem.action"
- data = {
- 't': 0,
- 'outSkus': '',
- 'random': random.random()
- }
- resp = session.post(url, data=data)
- if resp.status_code != requests.codes.OK:
- print('Status: %u, Url: %s' % (resp.status_code, resp.url))
- return False
- return True
-
-
-'''
-删除购物车选中商品
-'''
-
-
-def remove_item():
- url = "https://cart.jd.com/batchRemoveSkusFromCart.action"
- data = {
- 't': 0,
- 'null': '',
- 'outSkus': '',
- 'random': random.random(),
- 'locationId': '19-1607-4773-0'
- }
- headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.37",
- "Accept": "application/json, text/javascript, */*; q=0.01",
- "Referer": "https://cart.jd.com/cart.action",
- "Host": "cart.jd.com",
- "Content-Type": "application/x-www-form-urlencoded",
- "Accept-Encoding": "gzip, deflate, br",
- "Accept-Encoding": "zh-CN,zh;q=0.9,ja;q=0.8",
- "Origin": "https://cart.jd.com",
- "Connection": "keep-alive"
- }
- resp = session.post(url, data=data, headers=headers)
- logger.info('清空购物车')
- if resp.status_code != requests.codes.OK:
- print('Status: %u, Url: %s' % (resp.status_code, resp.url))
- return False
- return True
-
-
-'''
-购物车详情
-'''
-
-
-def cart_detail():
- url = 'https://cart.jd.com/cart.action'
- headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Referer": "https://order.jd.com/center/list.action",
- "Host": "cart.jd.com",
- "Connection": "keep-alive"
- }
- resp = session.get(url, headers=headers)
- soup = BeautifulSoup(resp.text, "html.parser")
-
- cart_detail = dict()
- for item in soup.find_all(class_='item-item'):
- try:
- sku_id = item['skuid'] # 商品id
- except Exception as e:
- logger.info('购物车中有套装商品,跳过')
- continue
- try:
- # 例如:['increment', '8888', '100001071956', '1', '13', '0', '50067652554']
- # ['increment', '8888', '100002404322', '2', '1', '0']
- item_attr_list = item.find(class_='increment')['id'].split('_')
- p_type = item_attr_list[4]
- promo_id = target_id = item_attr_list[-1] if len(item_attr_list) == 7 else 0
-
- cart_detail[sku_id] = {
- 'name': get_tag_value(item.select('div.p-name a')), # 商品名称
- 'verder_id': item['venderid'], # 商家id
- 'count': int(item['num']), # 数量
- 'unit_price': get_tag_value(item.select('div.p-price strong'))[1:], # 单价
- 'total_price': get_tag_value(item.select('div.p-sum strong'))[1:], # 总价
- 'is_selected': 'item-selected' in item['class'], # 商品是否被勾选
- 'p_type': p_type,
- 'target_id': target_id,
- 'promo_id': promo_id
- }
- except Exception as e:
- logger.error("商品%s在购物车中的信息无法解析,报错信息: %s,该商品自动忽略", sku_id, e)
-
- logger.info('购物车信息:%s', cart_detail)
- return cart_detail
-
-
-'''
-修改购物车商品的数量
-'''
-
-
-def change_item_num_in_cart(sku_id, vender_id, num, p_type, target_id, promo_id):
- url = "https://cart.jd.com/changeNum.action"
- data = {
- 't': 0,
- 'venderId': vender_id,
- 'pid': sku_id,
- 'pcount': num,
- 'ptype': p_type,
- 'targetId': target_id,
- 'promoID': promo_id,
- 'outSkus': '',
- 'random': random.random(),
- # 'locationId'
- }
- session.headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Referer": "https://cart.jd.com/cart",
- "Connection": "keep-alive"
- }
- resp = session.post(url, data=data)
- return json.loads(resp.text)['sortedWebCartResult']['achieveSevenState'] == 2
-
-
-'''
-添加商品到购物车
-'''
-
-
-def add_item_to_cart(sku_id):
- url = 'https://cart.jd.com/gate.action'
- payload = {
- 'pid': sku_id,
- 'pcount': 1,
- 'ptype': 1,
- }
- resp = session.get(url=url, params=payload)
- if 'https://cart.jd.com/cart.action' in resp.url: # 套装商品加入购物车后直接跳转到购物车页面
- result = True
- else: # 普通商品成功加入购物车后会跳转到提示 "商品已成功加入购物车!" 页面
- soup = BeautifulSoup(resp.text, "html.parser")
- result = bool(soup.select('h3.ftx-02')) # [商品已成功加入购物车!
]
-
- if result:
- logger.info('%s 已成功加入购物车', sku_id)
- else:
- logger.error('%s 添加到购物车失败', sku_id)
-
-
-def get_checkout_page_detail():
- """获取订单结算页面信息
-
- 该方法会返回订单结算页面的详细信息:商品名称、价格、数量、库存状态等。
-
- :return: 结算信息 dict
- """
- url = 'http://trade.jd.com/shopping/order/getOrderInfo.action'
- # url = 'https://cart.jd.com/gotoOrder.action'
- payload = {
- 'rid': str(int(time.time() * 1000)),
- }
- headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Referer": "https://cart.jd.com/cart.action",
- "Connection": "keep-alive",
- 'Host': 'trade.jd.com',
- }
- try:
- resp = session.get(url=url, params=payload, headers=headers)
- if not response_status(resp):
- logger.error('获取订单结算页信息失败')
- return ''
- if '刷新太频繁了' in resp.text:
- return '刷新太频繁了'
- soup = BeautifulSoup(resp.text, "html.parser")
- showCheckCode = get_tag_value(soup.select('input#showCheckCode'), 'value')
- if not showCheckCode:
- pass
- else:
- if showCheckCode == 'true':
- logger.info('提交订单需要验证码')
- global is_Submit_captcha, encryptClientInfo
- encryptClientInfo = get_tag_value(soup.select('input#encryptClientInfo'), 'value')
- is_Submit_captcha = True
- risk_control = get_tag_value(soup.select('input#riskControl'), 'value')
-
- order_detail = {
- 'address': soup.find('span', id='sendAddr').text[5:], # remove '寄送至: ' from the begin
- 'receiver': soup.find('span', id='sendMobile').text[4:], # remove '收件人:' from the begin
- 'total_price': soup.find('span', id='sumPayPriceId').text[1:], # remove '¥' from the begin
- 'items': []
- }
-
- logger.info("下单信息:%s", order_detail)
- return risk_control
- except requests.exceptions.RequestException as e:
- logger.error('订单结算页面获取异常:%s' % e)
- except Exception as e:
- logger.error('下单页面数据解析异常:%s', e)
- return ''
-
-
-'''
-商品下柜检测
-'''
-
-
-def item_removed(sku_id):
- headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Referer": "http://trade.jd.com/shopping/order/getOrderInfo.action",
- "Connection": "keep-alive",
- 'Host': 'item.jd.com',
- }
- url = 'https://item.jd.com/{}.html'.format(sku_id)
- page = requests.get(url=url, headers=headers)
- return '该商品已下柜' not in page.text
-
-
-'''
-购买环节
-测试三次
-'''
-
-
-def buyMask(sku_id):
- risk_control = get_checkout_page_detail()
- if risk_control == '刷新太频繁了':
- return False
- if len(risk_control) > 0:
- if submit_order(session, risk_control, sku_id, skuids, submit_Time, encryptClientInfo, is_Submit_captcha,
- payment_pwd, submit_captcha_text, submit_captcha_rid):
- return True
-
-
-def V3check(skuId):
- select_all_cart_item()
- remove_item()
- validate_cookies()
- logger.info('校验是否还在登录')
- add_item_to_cart(skuId)
- if not item_removed(skuId):
- logger.info('[%s]已下柜商品', skuId)
- sys.exit(1)
-
-
-def V3AutoBuy(inStockSkuid):
- if skuId in inStockSkuid:
- global submit_Time
- submit_Time = int(time.time() * 1000)
- logger.info('[%s]类型口罩有货啦!马上下单', skuId)
- skuidUrl = 'https://item.jd.com/' + skuId + '.html'
- if buyMask(skuId):
- message.send(skuidUrl, True)
- sys.exit(1)
- else:
- if item_removed(skuId):
- message.send(skuidUrl, False)
- else:
- logger.info('[%s]已下柜商品', skuId)
- sys.exit(1)
-
-
-def check_Config():
- global configMd5, configTime
- nowMd5 = getconfigMd5()
- configTime = time.time()
- if not nowMd5 == configMd5:
- logger.info('配置文件修改,重新读取文件')
- getconfig()
- configMd5 = nowMd5
-
-
-# _setDNSCache()
-if len(skuids) != 1:
- logger.info('请准备一件商品')
-skuId = skuids[0]
-flag = 1
-while (1):
- try:
- # 初始化校验
- if flag == 1:
- logger.info('当前是V3版本')
- validate_cookies()
- getUsername()
- select_all_cart_item()
- remove_item()
- add_item_to_cart(skuId)
- # 检测配置文件修改
- if int(time.time()) - configTime >= 60:
- check_Config()
- logger.info('第' + str(flag) + '次 ')
- flag += 1
- # 检查库存模块
- inStockSkuid = check_stock(checksession, skuids, area)
- # 自动下单模块
- V3AutoBuy(inStockSkuid)
- # 休眠模块
- timesleep = random.randint(1, 3) / 10
- time.sleep(timesleep)
- # 校验是否还在登录模块
- if flag % 100 == 0:
- V3check(skuId)
- except Exception as e:
- print(traceback.format_exc())
- time.sleep(10)
diff --git a/jdEmail.py b/jdEmail.py
deleted file mode 100644
index 292c80f..0000000
--- a/jdEmail.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# -*- coding=utf-8 -*-
-'''
-发送邮件模块
-'''
-import traceback
-
-
-def sendMail(mail, msgtext):
- try:
- import smtplib
- from email.mime.text import MIMEText
- # email 用于构建邮件内容
- from email.header import Header
-
- # 用于构建邮件头
- # 发信方的信息:发信邮箱,QQ 邮箱授权码
- from_addr = 'jdbuymask@163.com'
- password = 'alpsneahcyz123'
-
- # 收信方邮箱
- to_addr = mail
- # 发信服务器
- smtp_server = 'smtp.163.com'
- # 邮箱正文内容,第一个参数为内容,第二个参数为格式(plain 为纯文本),第三个参数为编码
- msg = MIMEText(msgtext, 'plain', 'utf-8')
- # 邮件头信息
- # msg['From'] = Header(from_addr)
- msg['From'] = Header(u'from Mark<{}>'.format(from_addr), 'utf-8')
- msg['To'] = Header(to_addr)
- msg['Subject'] = Header('京东口罩监控','utf-8')
- # 开启发信服务,这里使用的是加密传输
- server = smtplib.SMTP_SSL(host=smtp_server)
- server.connect(smtp_server, 465)
- # 登录发信邮箱
- server.login(from_addr, password)
- # 发送邮件
- server.sendmail(from_addr, to_addr, msg.as_string())
- # 关闭服务器
- server.quit()
- except Exception as e:
- print(traceback.format_exc())
diff --git a/jdProgram.py b/jdProgram.py
deleted file mode 100644
index 780e714..0000000
--- a/jdProgram.py
+++ /dev/null
@@ -1,219 +0,0 @@
-# -*- coding=utf-8 -*-
-
-import json
-import random
-import time
-from io import BytesIO
-
-from PIL import Image
-
-from jdlogger import logger
-from util import parse_json, response_status
-import traceback
-
-'''
-2020/2/13
-(避免滥用,代码已经废弃,现已不更新,有需要请适量使用exe版本)
-'''
-'''
-查询库存(旧)
-'''
-
-
-def check_stock(checksession, skuids, area):
- start = int(time.time() * 1000)
- skuidString = ','.join(skuids)
- callback = 'jQuery' + str(random.randint(1000000, 9999999))
- headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Referer": "https://cart.jd.com/cart.action",
- "Connection": "keep-alive",
- "Host": "c0.3.cn"
- }
- #
- url = 'https://c0.3.cn/stocks'
- payload = {
- 'type': 'getstocks',
- 'skuIds': skuidString,
- 'area': area,
- 'callback': callback,
- '_': int(time.time() * 1000),
- }
- resp = checksession.get(url=url, params=payload, headers=headers)
- inStockSkuid = []
- nohasSkuid = []
- unUseSkuid = []
- for sku_id, info in parse_json(resp.text).items():
- sku_state = info.get('skuState') # 商品是否上架
- stock_state = info.get('StockState') # 商品库存状态
- if sku_state == 1 and stock_state in (33, 40):
- inStockSkuid.append(sku_id)
- if sku_state == 0:
- unUseSkuid.append(sku_id)
- if stock_state == 34:
- nohasSkuid.append(sku_id)
- logger.info('检测[%s]个口罩有货,[%s]个口罩无货,[%s]个口罩下柜,耗时[%s]ms', len(inStockSkuid), len(nohasSkuid), len(unUseSkuid),
- int(time.time() * 1000) - start)
-
- if len(unUseSkuid) > 0:
- logger.info('[%s]口罩已经下柜', ','.join(unUseSkuid))
- return inStockSkuid
-
-
-'''
-提交订单
-'''
-
-
-def submit_order(session, risk_control, sku_id, skuids, submit_Time, encryptClientInfo, is_Submit_captcha, payment_pwd,
- submit_captcha_text, submit_captcha_rid):
- """
-
- 重要:
- 1.该方法只适用于普通商品的提交订单(即可以加入购物车,然后结算提交订单的商品)
- 2.提交订单时,会对购物车中勾选✓的商品进行结算(如果勾选了多个商品,将会提交成一个订单)
-
- :return: True/False 订单提交结果
- """
- url = 'https://trade.jd.com/shopping/order/submitOrder.action'
- # js function of submit order is included in https://trade.jd.com/shopping/misc/js/order.js?r=2018070403091
-
- data = {
- 'overseaPurchaseCookies': '',
- 'vendorRemarks': '[]',
- 'submitOrderParam.sopNotPutInvoice': 'false',
- 'submitOrderParam.trackID': 'TestTrackId',
- 'submitOrderParam.ignorePriceChange': '0',
- 'submitOrderParam.btSupport': '0',
- 'riskControl': risk_control,
- 'submitOrderParam.isBestCoupon': 1,
- 'submitOrderParam.jxj': 1,
- 'submitOrderParam.trackId': '9643cbd55bbbe103eef18a213e069eb0', # Todo: need to get trackId
- # 'submitOrderParam.eid': eid,
- # 'submitOrderParam.fp': fp,
- 'submitOrderParam.needCheck': 1,
- }
-
- def encrypt_payment_pwd(payment_pwd):
- return ''.join(['u3' + x for x in payment_pwd])
-
- if len(payment_pwd) > 0:
- data['submitOrderParam.payPassword'] = encrypt_payment_pwd(payment_pwd)
-
- headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Referer": "http://trade.jd.com/shopping/order/getOrderInfo.action",
- "Connection": "keep-alive",
- 'Host': 'trade.jd.com',
- }
- for count in range(1, 3):
- logger.info('第[%s/%s]次尝试提交订单', count, 3)
- try:
- if is_Submit_captcha:
- captcha_result = page_detail_captcha(session, encryptClientInfo)
- # 验证码服务错误
- if not captcha_result:
- logger.error('验证码服务异常')
- continue
- data['submitOrderParam.checkcodeTxt'] = submit_captcha_text
- data['submitOrderParam.checkCodeRid'] = submit_captcha_rid
- resp = session.post(url=url, data=data, headers=headers)
- resp_json = json.loads(resp.text)
- logger.info('本次提交订单耗时[%s]毫秒', str(int(time.time() * 1000) - submit_Time))
- # 返回信息示例:
- # 下单失败
- # {'overSea': False, 'orderXml': None, 'cartXml': None, 'noStockSkuIds': '', 'reqInfo': None, 'hasJxj': False, 'addedServiceList': None, 'sign': None, 'pin': 'xxx', 'needCheckCode': False, 'success': False, 'resultCode': 60123, 'orderId': 0, 'submitSkuNum': 0, 'deductMoneyFlag': 0, 'goJumpOrderCenter': False, 'payInfo': None, 'scaleSkuInfoListVO': None, 'purchaseSkuInfoListVO': None, 'noSupportHomeServiceSkuList': None, 'msgMobile': None, 'addressVO': None, 'msgUuid': None, 'message': '请输入支付密码!'}
- # {'overSea': False, 'cartXml': None, 'noStockSkuIds': '', 'reqInfo': None, 'hasJxj': False, 'addedServiceList': None, 'orderXml': None, 'sign': None, 'pin': 'xxx', 'needCheckCode': False, 'success': False, 'resultCode': 60017, 'orderId': 0, 'submitSkuNum': 0, 'deductMoneyFlag': 0, 'goJumpOrderCenter': False, 'payInfo': None, 'scaleSkuInfoListVO': None, 'purchaseSkuInfoListVO': None, 'noSupportHomeServiceSkuList': None, 'msgMobile': None, 'addressVO': None, 'msgUuid': None, 'message': '您多次提交过快,请稍后再试'}
- # {'overSea': False, 'orderXml': None, 'cartXml': None, 'noStockSkuIds': '', 'reqInfo': None, 'hasJxj': False, 'addedServiceList': None, 'sign': None, 'pin': 'xxx', 'needCheckCode': False, 'success': False, 'resultCode': 60077, 'orderId': 0, 'submitSkuNum': 0, 'deductMoneyFlag': 0, 'goJumpOrderCenter': False, 'payInfo': None, 'scaleSkuInfoListVO': None, 'purchaseSkuInfoListVO': None, 'noSupportHomeServiceSkuList': None, 'msgMobile': None, 'addressVO': None, 'msgUuid': None, 'message': '获取用户订单信息失败'}
- # {"cartXml":null,"noStockSkuIds":"xxx","reqInfo":null,"hasJxj":false,"addedServiceList":null,"overSea":false,"orderXml":null,"sign":null,"pin":"xxx","needCheckCode":false,"success":false,"resultCode":600157,"orderId":0,"submitSkuNum":0,"deductMoneyFlag":0,"goJumpOrderCenter":false,"payInfo":null,"scaleSkuInfoListVO":null,"purchaseSkuInfoListVO":null,"noSupportHomeServiceSkuList":null,"msgMobile":null,"addressVO":{"pin":"xxx","areaName":"","provinceId":xx,"cityId":xx,"countyId":xx,"townId":xx,"paymentId":0,"selected":false,"addressDetail":"xx","mobile":"xx","idCard":"","phone":null,"email":null,"selfPickMobile":null,"selfPickPhone":null,"provinceName":null,"cityName":null,"countyName":null,"townName":null,"giftSenderConsigneeName":null,"giftSenderConsigneeMobile":null,"gcLat":0.0,"gcLng":0.0,"coord_type":0,"longitude":0.0,"latitude":0.0,"selfPickOptimize":0,"consigneeId":0,"selectedAddressType":0,"siteType":0,"helpMessage":null,"tipInfo":null,"cabinetAvailable":true,"limitKeyword":0,"specialRemark":null,"siteProvinceId":0,"siteCityId":0,"siteCountyId":0,"siteTownId":0,"skuSupported":false,"addressSupported":0,"isCod":0,"consigneeName":null,"pickVOname":null,"shipmentType":0,"retTag":0,"tagSource":0,"userDefinedTag":null,"newProvinceId":0,"newCityId":0,"newCountyId":0,"newTownId":0,"newProvinceName":null,"newCityName":null,"newCountyName":null,"newTownName":null,"checkLevel":0,"optimizePickID":0,"pickType":0,"dataSign":0,"overseas":0,"areaCode":null,"nameCode":null,"appSelfPickAddress":0,"associatePickId":0,"associateAddressId":0,"appId":null,"encryptText":null,"certNum":null,"used":false,"oldAddress":false,"mapping":false,"addressType":0,"fullAddress":"xxxx","postCode":null,"addressDefault":false,"addressName":null,"selfPickAddressShuntFlag":0,"pickId":0,"pickName":null,"pickVOselected":false,"mapUrl":null,"branchId":0,"canSelected":false,"address":null,"name":"xxx","message":null,"id":0},"msgUuid":null,"message":"xxxxxx商品无货"}
- # {'orderXml': None, 'overSea': False, 'noStockSkuIds': 'xxx', 'reqInfo': None, 'hasJxj': False, 'addedServiceList': None, 'cartXml': None, 'sign': None, 'pin': 'xxx', 'needCheckCode': False, 'success': False, 'resultCode': 600158, 'orderId': 0, 'submitSkuNum': 0, 'deductMoneyFlag': 0, 'goJumpOrderCenter': False, 'payInfo': None, 'scaleSkuInfoListVO': None, 'purchaseSkuInfoListVO': None, 'noSupportHomeServiceSkuList': None, 'msgMobile': None, 'addressVO': {'oldAddress': False, 'mapping': False, 'pin': 'xxx', 'areaName': '', 'provinceId': xx, 'cityId': xx, 'countyId': xx, 'townId': xx, 'paymentId': 0, 'selected': False, 'addressDetail': 'xxxx', 'mobile': 'xxxx', 'idCard': '', 'phone': None, 'email': None, 'selfPickMobile': None, 'selfPickPhone': None, 'provinceName': None, 'cityName': None, 'countyName': None, 'townName': None, 'giftSenderConsigneeName': None, 'giftSenderConsigneeMobile': None, 'gcLat': 0.0, 'gcLng': 0.0, 'coord_type': 0, 'longitude': 0.0, 'latitude': 0.0, 'selfPickOptimize': 0, 'consigneeId': 0, 'selectedAddressType': 0, 'newCityName': None, 'newCountyName': None, 'newTownName': None, 'checkLevel': 0, 'optimizePickID': 0, 'pickType': 0, 'dataSign': 0, 'overseas': 0, 'areaCode': None, 'nameCode': None, 'appSelfPickAddress': 0, 'associatePickId': 0, 'associateAddressId': 0, 'appId': None, 'encryptText': None, 'certNum': None, 'addressType': 0, 'fullAddress': 'xxxx', 'postCode': None, 'addressDefault': False, 'addressName': None, 'selfPickAddressShuntFlag': 0, 'pickId': 0, 'pickName': None, 'pickVOselected': False, 'mapUrl': None, 'branchId': 0, 'canSelected': False, 'siteType': 0, 'helpMessage': None, 'tipInfo': None, 'cabinetAvailable': True, 'limitKeyword': 0, 'specialRemark': None, 'siteProvinceId': 0, 'siteCityId': 0, 'siteCountyId': 0, 'siteTownId': 0, 'skuSupported': False, 'addressSupported': 0, 'isCod': 0, 'consigneeName': None, 'pickVOname': None, 'shipmentType': 0, 'retTag': 0, 'tagSource': 0, 'userDefinedTag': None, 'newProvinceId': 0, 'newCityId': 0, 'newCountyId': 0, 'newTownId': 0, 'newProvinceName': None, 'used': False, 'address': None, 'name': 'xx', 'message': None, 'id': 0}, 'msgUuid': None, 'message': 'xxxxxx商品无货'}
- # {"orderXml":null,"cartXml":null,"noStockSkuIds":"","reqInfo":null,"hasJxj":false,"overSea":false,"addedServiceList":null,"sign":null,"pin":null,"needCheckCode":true,"success":false,"resultCode":0,"orderId":0,"submitSkuNum":0,"deductMoneyFlag":0,"goJumpOrderCenter":false,"payInfo":null,"scaleSkuInfoListVO":null,"purchaseSkuInfoListVO":null,"noSupportHomeServiceSkuList":null,"msgMobile":null,"addressVO":null,"msgUuid":null,"message":"验证码不正确,请重新填写"}
- # {'overSea': False, 'orderXml': None, 'cartXml': None, 'noStockSkuIds': '', 'reqInfo': None, 'hasJxj': False, 'addedServiceList': None, 'sign': None, 'pin': 'jd_7c3992aa27d1a', 'needCheckCode': False, 'success': False, 'resultCode': 60070, 'orderId': 0, 'submitSkuNum': 0, 'deductMoneyFlag': 0, 'goJumpOrderCenter': False, 'payInfo': None, 'scaleSkuInfoListVO': None, 'purchaseSkuInfoListVO': None, 'noSupportHomeServiceSkuList': None, 'msgMobile': None, 'addressVO': None, 'msgUuid': None, 'message': '抱歉,您当前选择的省份无法购买商品星工 KN95口罩防雾霾防尘防花粉PM2.5 硅胶鼻垫带阀耳戴透气 工业粉尘防护口罩 白色25只独立包装'}
- # 下单成功
- # {'overSea': False, 'orderXml': None, 'cartXml': None, 'noStockSkuIds': '', 'reqInfo': None, 'hasJxj': False, 'addedServiceList': None, 'sign': None, 'pin': 'xxx', 'needCheckCode': False, 'success': True, 'resultCode': 0, 'orderId': 8740xxxxx, 'submitSkuNum': 1, 'deductMoneyFlag': 0, 'goJumpOrderCenter': False, 'payInfo': None, 'scaleSkuInfoListVO': None, 'purchaseSkuInfoListVO': None, 'noSupportHomeServiceSkuList': None, 'msgMobile': None, 'addressVO': None, 'msgUuid': None, 'message': None}
- if resp_json.get('success'):
- logger.info('订单提交成功! 订单号:%s', resp_json.get('orderId'))
- return True
- else:
- resultMessage, result_code = resp_json.get('message'), resp_json.get('resultCode')
- if result_code == 0:
- # self._save_invoice()
- if '验证码不正确' in resultMessage:
- resultMessage = resultMessage + '(验证码错误)'
- logger.info('提交订单验证码[错误]')
- continue
- else:
- resultMessage = resultMessage + '(下单商品可能为第三方商品,将切换为普通发票进行尝试)'
- elif result_code == 60077:
- resultMessage = resultMessage + '(可能是购物车为空 或 未勾选购物车中商品)'
- elif result_code == 60123:
- resultMessage = resultMessage + '(需要在payment_pwd参数配置支付密码)'
- elif result_code == 60070:
- resultMessage = resultMessage + '(省份不支持销售)'
- skuids.remove(sku_id)
- logger.info('[%s]类型口罩不支持销售踢出', sku_id)
- logger.info('订单提交失败, 错误码:%s, 返回信息:%s', result_code, resultMessage)
- logger.info(resp_json)
- return False
- except Exception as e:
- print(traceback.format_exc())
- continue
-
-
-'''
-订单页面验证码
-'''
-
-
-def page_detail_captcha(session, isId):
- url = 'https://captcha.jd.com/verify/image'
- acid = '{}_{}'.format(random.random(), random.random())
- payload = {
- 'acid': acid,
- 'srcid': 'trackWeb',
- 'is': isId,
- }
- headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36",
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Referer": "https://trade.jd.com/shopping/order/getOrderInfo.action",
- "Connection": "keep-alive",
- 'Host': 'captcha.jd.com',
- }
- try:
- resp = session.get(url=url, params=payload, headers=headers)
- if not response_status(resp):
- logger.error('获取订单验证码失败')
- return ''
- logger.info('解析验证码开始')
- image = Image.open(BytesIO(resp.content))
- image.save('captcha.jpg')
- result = analysis_captcha(resp.content)
- if not result:
- logger.error('解析订单验证码失败')
- return ''
- global submit_captcha_text, submit_captcha_rid
- submit_captcha_text = result
- submit_captcha_rid = acid
- return result
- except Exception as e:
- logger.error('订单验证码获取异常:%s', e)
- return ''
-
-
-def analysis_captcha(session, captchaUrl, pic):
- for i in range(1, 10):
- try:
- url = captchaUrl
- resp = session.post(url, pic)
- if not response_status(resp):
- logger.error('解析验证码失败')
- continue
- logger.info('解析验证码[%s]', resp.text)
- return resp.text
- except Exception as e:
- print(traceback.format_exc())
- continue
- return ''
diff --git a/jdlogger.py b/jdlogger.py
deleted file mode 100644
index d8c5f17..0000000
--- a/jdlogger.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding=utf-8 -*-
-import logging
-import logging.handlers
-'''
-日志模块
-'''
-LOG_FILENAME = 'jdBuyMask.log'
-
-logger = logging.getLogger()
-
-
-def set_logger():
- logger.setLevel(logging.INFO)
- formatter = logging.Formatter('%(asctime)s %(levelname)s: %(message)s')
-
- console_handler = logging.StreamHandler()
- console_handler.setFormatter(formatter)
- logger.addHandler(console_handler)
-
- file_handler = logging.handlers.RotatingFileHandler(
- LOG_FILENAME, maxBytes=10485760, backupCount=5, encoding="utf-8")
- file_handler.setFormatter(formatter)
- logger.addHandler(file_handler)
-
-
-set_logger()
diff --git a/message.py b/message.py
deleted file mode 100644
index bc4faac..0000000
--- a/message.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# -*- encoding=utf8 -*-
-from jdEmail import sendMail
-from wechat_ftqq import sendWechat
-
-
-class message(object):
- """消息推送类"""
-
- def __init__(self, messageType, sc_key, mail):
- if messageType == '2':
- if not sc_key:
- raise Exception('sc_key can not be empty')
- self.sc_key = sc_key
- elif messageType == '1':
- if not mail:
- raise Exception('mail can not be empty')
- self.mail = mail
- self.messageType = messageType
-
- def send(self, desp='', isOrder=False):
- desp = str(desp)
- if isOrder:
- msg = desp + ' 类型口罩,已经下单了。24小时内付款'
- else:
- msg = desp + ' 类型口罩,下单失败了'
- if self.messageType == '1':
- sendMail(self.mail, msg)
- if self.messageType == '2':
- sendWechat(sc_key=self.sc_key, desp=msg)
-
- def sendAny(self, desp=''):
- desp = str(desp)
- msg = desp
- if self.messageType == '1':
- sendMail(self.mail, msg)
- if self.messageType == '2':
- sendWechat(sc_key=self.sc_key, desp=msg)
diff --git a/util.py b/util.py
deleted file mode 100644
index 2761aab..0000000
--- a/util.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# -*- coding=utf-8 -*-
-import hashlib
-import json
-import socket
-import requests
-
-_dnscache = {}
-
-def parse_json(s):
- begin = s.find('{')
- end = s.rfind('}') + 1
- return json.loads(s[begin:end])
-
-
-def getconfigMd5():
- with open('configDemo.ini', 'r', encoding='utf-8') as f:
- configText = f.read()
- return hashlib.md5(configText.encode('utf-8')).hexdigest()
-
-def response_status(resp):
- if resp.status_code != requests.codes.OK:
- print('Status: %u, Url: %s' % (resp.status_code, resp.url))
- return False
- return True
-
-
-def _setDNSCache():
- """
- Makes a cached version of socket._getaddrinfo to avoid subsequent DNS requests.
- """
-
- def _getaddrinfo(*args, **kwargs):
- global _dnscache
- if args in _dnscache:
- # print(str(args) + " in cache")
- return _dnscache[args]
-
- else:
- # print(str(args) + " not in cache")
- _dnscache[args] = socket._getaddrinfo(*args, **kwargs)
- return _dnscache[args]
-
- if not hasattr(socket, '_getaddrinfo'):
- socket._getaddrinfo = socket.getaddrinfo
- socket.getaddrinfo = _getaddrinfo
diff --git a/wechat_ftqq.py b/wechat_ftqq.py
deleted file mode 100644
index 55cb00f..0000000
--- a/wechat_ftqq.py
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/usr/bin/env python
-# -*- encoding=utf8 -*-
-import datetime
-import json
-
-import requests
-
-from jdlogger import logger
-
-
-def sendWechat(sc_key, text='京东商品监控', desp=''):
- if not text.strip():
- logger.error('Text of message is empty!')
- return
-
- now_time = str(datetime.datetime.now())
- desp = '[{0}]'.format(now_time) if not desp else '{0} [{1}]'.format(desp, now_time)
-
- try:
- resp = requests.get(
- 'https://sc.ftqq.com/{}.send?text={}&desp={}'.format(sc_key, text, desp)
- )
- resp_json = json.loads(resp.text)
- if resp_json.get('errno') == 0:
- logger.info('Message sent successfully [text: %s, desp: %s]', text, desp)
- else:
- logger.error('Fail to send message, reason: %s', resp.text)
- except requests.exceptions.RequestException as req_error:
- logger.error('Request error: %s', req_error)
- except Exception as e:
- logger.error('Fail to send message [text: %s, desp: %s]: %s', text, desp, e)
--
GitLab