How to use Python Grab masks on Jingdong

National anti Japanese War " Epidemic disease " It's been so long to see the dawn , Stayed at home for nearly a month , Now I can finally go to work , But I found that I couldn't buy the necessary masks to go out . Recently, I saw that there is a second killing activity of masks on Jingdong every day , I tried several times, but I couldn't get it , It's time to snap up , The browser page doesn't refresh at all , When the brush comes out, the second kill is over . Now only 10000 are released every day , There are millions of people robbing , I really want to know how others got it , So on the Internet to find a big god open out of the rush to buy code . Look at the code. It's not complicated , Now let's take a look at it with a learning attitude .

Using modules

First, open the project requirements.txt file , Take a look at the modules it needs :

  • requests: similar urllib, It's mainly used to send HTTP request .
  • beautifulsoup4:HTML Parser , Is used to HTML The document is transformed into a complex tree structure .
  • pillow:Python Image processing standard library , Used to identify captcha .
## The configuration file
In general projects, we need to put some configurable content into the configuration file , Now let's look at the main configuration items here :
# Mailing area ID
area = 123456
# This is the product of configuration ID
skuid = 6828101
# The address of the coding server
captchaUrl = http://xxx/pic
# Notification email
mail = xxxxxx@qq.com
# cookie Set up
cookies_String = shshshfpa21jsda8923892949204923123

OK, With the configuration file , Then we have to have a piece of code to read the configuration file , This code implements loading the configuration content into memory .

import os
import configparser
# Load profile
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)

Main program module

I think GitHub On the Internet, there are also programs that run through Jingdong App Scan the code and log in , And then by logging in Cookie Visit the website , But it's not used here , After all, we can easily get the login information by opening the browser developer tool Cookie, Here is the will Cookie The way to put it directly in the configuration file .

# Main program entry
# Check if there are ports to be snapped up , And then go into the loop scan
if len(skuids) != 1:
logger.info(' Please prepare a product ')
skuId = skuids[0]
flag = 1
# Cycle to scan if the product is in stock , When there is stock, the order will be placed automatically , If there is no stock, continue scanning after sleep
while (1):
try:
# Initialization verification
if flag == 1:
logger.info(' Now it's V3 edition ')
validate_cookies() # Check the login status
getUsername() # Get login user information
select_all_cart_item() # Shopping cart all
remove_item() # Delete shopping cart
add_item_to_cart(skuId) # Increase the number of items to be snapped up
# Detect profile modification
if int(time.time()) - configTime >= 60:
check_Config()
logger.info(' The first ' + str(flag) + ' Time ')
# Counter
flag += 1
# Check the inventory module
inStockSkuid = check_stock(checksession, skuids, area)
# Automatic order module
V3AutoBuy(inStockSkuid)
# Sleep module
timesleep = random.randint(1, 3) / 10
time.sleep(timesleep)
# Verify that the module is still logged in
if flag % 100 == 0:
V3check(skuId)
except Exception as e:
print(traceback.format_exc())
time.sleep(10)

The above is the main program of the project , I've added some comments to the code , It makes it easier for us to understand the meaning of the code . Now let's select a few key code analysis .

Login status verification

# Check the login status
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(' Login successful ')
return True
else:
logger.info(' The first 【%s】 Please get it again cookie', flag)
time.sleep(5)
continue
except Exception as e:
logger.info(' The first 【%s】 Please get it again cookie', flag)
time.sleep(5)
continue
message.sendAny(' Script login cookie It doesn't work , Please login again ')
sys.exit(1)

The above code is called every time , Loop twice to get through session Get the current login status , If it still fails after two times, exit the program .

Add items to cart

Next, let's look at how to add items to the shopping cart , The code is as follows :

def add_item_to_cart(sku_id):
# Request to add product url
url = 'https://cart.jd.com/gate.action'
payload = {
'pid': sku_id,
'pcount': 1,
'ptype': 1,
}
# Return results
resp = session.get(url=url, params=payload)
# After the package product is added to the shopping cart, it will jump to the shopping cart page directly
if 'https://cart.jd.com/cart.action' in resp.url:
result = True
else:
# After the general merchandise is successfully added to the shopping cart, it will jump to the prompt " The product has been successfully added to the shopping cart !" page
soup = BeautifulSoup(resp.text, "html.parser")
result = bool(soup.select('h3.ftx-02')) # [<h3 class="ftx-02"> The product has been successfully added to the shopping cart !</h3>]
if result:
logger.info('%s Successfully joined the shopping cart ', sku_id)
else:
logger.error('%s Add to cart failed ', sku_id)

ad locum , Just a few lines of code can add the port to the shopping cart , What's more, different types of products are distinguished here. The result of adding to the page returned by the shopping cart is different , So we have to make a distinction .

Purchase goods

Added items to the shopping cart , Next we have to submit the settlement page , That is to submit the goods to the payment page , It's a little bit of code , I simplified it and added some notes :

def submit_order(session, risk_control, sku_id, skuids, submit_Time, encryptClientInfo, is_Submit_captcha, payment_pwd,
submit_captcha_text, submit_captcha_rid):
# Submit port url
url = 'https://trade.jd.com/shopping/order/submitOrder.action'
# Submit parameters
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.needCheck': 1,
}
# If you use Jingdou, you need to enter the payment password
def encrypt_payment_pwd(payment_pwd):
return ''.join(['u3' + x for x in payment_pwd])
# Verify payment password
if len(payment_pwd) > 0:
data['submitOrderParam.payPassword'] = encrypt_payment_pwd(payment_pwd)
# Request header
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',
}
# Order submission will try twice
for count in range(1, 3):
logger.info(' The first [%s/%s] First attempt to submit an order ', count, 3)
try:
# Check codes that may exist
if is_Submit_captcha:
captcha_result = page_detail_captcha(session, encryptClientInfo)
# Captcha service error
if not captcha_result:
logger.error(' Captcha service exception ')
continue
data['submitOrderParam.checkcodeTxt'] = submit_captcha_text
data['submitOrderParam.checkCodeRid'] = submit_captcha_rid
# place order
resp = session.post(url=url, data=data, headers=headers)
resp_json = json.loads(resp.text)
logger.info(' It takes time to submit this order [%s] millisecond ', str(int(time.time() * 1000) - submit_Time))
# Judge whether the submission is successful
if resp_json.get('success'):
logger.info(' Order submitted successfully ! The order number :%s', resp_json.get('orderId'))
return True
else:
# There are many reasons for submission failure to return
resultMessage, result_code = resp_json.get('message'), resp_json.get('resultCode')
if result_code == 0:
# self._save_invoice()
if ' The verification code is incorrect ' in resultMessage:
resultMessage = resultMessage + '( Verification code error )'
logger.info(' Submit order verification code [ error ]')
continue
else:
resultMessage = resultMessage + '( The order may be a third party product , Will switch to ordinary invoice to try )'
elif result_code == 60077:
resultMessage = resultMessage + '( Maybe the shopping cart is empty or The item in the shopping cart is not checked )'
elif result_code == 60123:
resultMessage = resultMessage + '( Need to be in payment_pwd Parameter configuration payment password )'
elif result_code == 60070:
resultMessage = resultMessage + '( Provinces don't support sales )'
skuids.remove(sku_id)
logger.info('[%s] Type masks do not support sales ', sku_id)
logger.info(' Order submission failed , Error code :%s, Return information :%s', result_code, resultMessage)
logger.info(resp_json)
return False
except Exception as e:
print(traceback.format_exc())
continue

The above code realizes the automatic submission of goods to the settlement page , This is obviously more complicated than adding a shopping cart , Sure enough, everything about money is not simple . Okay , To the settlement page, the rest is the payment , This one doesn't need to be robbed any more , After all, no one will rush to pay you .

summary

This article introduces a small tool that Jingdong rushes to buy , It does a scan for inventory , When you find that there is stock, you can place an order automatically , And can be automatically submitted to the settlement page . And the way it's implemented is not too complicated , Further analysis of its part of the code , If you are interested, you can go to the end of the article GitHub Learn more on the project website , Thank you again for your contribution and sharing .

Reference resources

GitHub Project website :https://github.com/cycz/jdBuyMask