Article | xiao-fei li \
Source: Python Technology “ID: pythonall”
Last time I wrote how to make an appointment for a child’s equestrian course, see here Python appointment [1]. I wanted to make an appointment once and for all, but the good times didn’t last long. The appointment system was upgraded, and the service provider was changed, from the previous H5 application of the public account to a small program
He met a father who was a programmer? I can do this. Let’s do it
The difference between applets
Different from accessing H5, the small program is equivalent to an APP. The operations on it are encapsulated by wechat, so the request link and data cannot be directly obtained, and the returned data cannot be obtained either
Like an app, its requests are built into the app
In this case, you need to use a packet capture tool, such as Charles
The principle is that when a small program or APP sends a request as a proxy for the request, the request is first sent to the proxy, and then the proxy sends the request to the server, and the return process is the same
This is also known as a man-in-the-middle attack
Man-in-the-middle attack
If you want to get a specific request from an applet or app, you need to let the agent get the request and the corresponding data in this way
How do you play it? Directly refer to the Charles tutorial or a search on the Internet, you will know, here is a recommended Android capture package -Charles[2], for your reference
Over Https protocol
Once configured, you might notice that Charles has captured packages that are garbled because the applet must use the Https protocol
This is to encrypt the request data on top of the Http assistance to prevent man-in-the-middle attacks
The principle of Https is also very simple. The target URL applies for an Https certificate, and then publishes the public key of its symmetric key on the website that issues the certificate
When the target server is visited by the request, the target server will ask it to make a refill request, which is the client program will automatically go to the certificate issuing site to download the target website’s public key, that is, the certificate
The requested data is encrypted with the public key and sent to the target server. After receiving the request, the target server decrypts the requested data with its private key and converts it into plaintext for further processing
The same is true when the response is returned, except that the target server encrypts it with its private key and the client decrypts it with its public key
For details, please refer to the diagram HTTP[3]
Here you just need to follow Charles’ instructions, and then follow the certificate issued by Charles on the mobile phone
However, if you are running Android, please note that Google has updated its security policy since Android 7.0 to no longer support self-installed certificates
There are two solutions:
- Root the mobile phone, and then modify the security policy of the mobile phone. For details, please refer to: Capture Android Https link data through Charles [4]
- Find a phone that has not been upgraded to Android 7.0
I dug out a phone from a few years ago, charged it, turned it on, and checked the version. It was Android 6
After installing the certificate and capturing the packet again, you can see the requested data \
Charles caught
Get familiar
Once you have the request link and the request data, you can write Python scripts as you did last time
Last time, the request data was retrieved via a browser request. In Charles, it is also easy to retrieve, as shown below
Charles fetch request
Obtain the curl request data from the shortcut menu and copy it to curl.trillworks.com/[5]
Charles fetch request
Then copy the Python code to a file and execute it. Easy enough, see the previous article: This is the correct way to use Python! [6]
further
There’s another problem that needs to be solved here. Maybe I’m too lazy as a dad
Because of the May Day holiday, the Saturday after the holiday is a working day, and the previous procedure will book the course of every Saturday. If it is a working day, it just conflicts
So need to avoid working days, so the first thing to think of is to judge the holiday library available, find a circle, found some API can, but not need to pay is the need to register, more trouble, so directly go to the calendar to grab
Lock a universal calendar website wannianrili.bmcx.com, marked clear, accurate data, and free
calendar
Analysis request, it is a month of data accessed by the link wannianrili.bmcx.com/ajax/, access to the results of the data is in XML format
According to the analysis, date types are marked by CSS classes, namely wnrl_RIQI_BAN, wnrL_RIqi_MO, and wnrl_RIqi_XIU, representing work, weekend, and rest
So you just need to parse the XML you get
Further – because here I am again for a month, each request access point charge again, and it is in the booking, so I need a higher efficiency (ha ha, is actually want to dazzle technique), then made a small cache, every time see if there are any XML files for the month, if you have read directly, without access to, and stored
After the realization of the holiday judgment, add a judgment in the main booking program, if the day to make an appointment is a working day, then postpone one day, continue to judge, until a fee working day
Here is the code to determine the date type:
import requests
from lxml import etree
import datetime
import os
def getDaysInfo(ym):
cacheName = ym + ".html"
if os.path.exists(cacheName):
content = open(cacheName).read()
else:
content = requestsDayInfo(ym)
saveFile(cacheName, content)
return content
def requestsDayInfo(ym=None):
headers = {
'sec-ch-ua': '"Google Chrome"; v="89", "Chromium"; v="89", "; Not A Brand"; v="99"'.'Referer': 'https://wannianrili.bmcx.com/'.'sec-ch-ua-mobile': '? 0 '.'User-Agent': 'the Mozilla / 5.0 (Windows NT 10.0; Win64; X64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36',
}
params = (
('q', ym),
('v'.'20031912'),
)
response = requests.get('https://wannianrili.bmcx.com/ajax/', headers=headers, params=params)
return response.text
def saveFile(name, content):
print(name)
f = open(name,'w')
f.write(content)
f.close()
def parse(content, d):
html = etree.HTML(content)
dayclass = html.xpath('//*[@id="wnrl_riqi_id_'+str(int(d)- 1) +'"]) [0].attrib.get('class')
if dayclass is None or dayclass == 'wnrl_riqi_ban':
return 1
elif dayclass == 'wnrl_riqi_mo':
return 2
elif dayclass == 'wnrl_riqi_xiu':
return 3
else:
return 0
def getDayType(date):
str_date = date.strftime('%Y-%m-%d')
ymd = str_date.split("-")
ym = ymd[0] + The '-' + ymd[1]
d = ymd[2]
return parse(getDaysInfo(ym), d)
if __name__ == "__main__":
delta = 1Date = datetime.date.today() while(getDayType(date)< datetime.date.today())2):
delta += 1
date = datetime.date.today() + datetime.timedelta(days=delta)
Copy the code
conclusion
Ok, now you can be an elegant dad again. Haha, the best way to teach your kids is to grow up with them. Whatever it is, if you happen to like programming and know how to program, you can try doing something fun with your kids, like making a dice game. [7]
ink
The resources
[1]
Python lesson about: mp.weixin.qq.com/s/XqICwC9_c…
[2]
Android caught: www.jianshu.com/p/8385a13b0…
[3]
The illustration HTTP: book.douban.com/subject/258…
[4]
Android 7.0 installation certificate: bbs.huaweicloud.com/blogs/24501…
[5]
Curl to Python request: curl.trillworks.com/
[6]
This is the correct posture for using Python! : mp.weixin.qq.com/s/XqICwC9_c…
[7]
A dice game: mp.weixin.qq.com/s/czcGKk6RT…
PS: Reply “Python” within the public number to enter the Python novice learning exchange group, together with the 100-day plan!
Old rules, brothers still remember, the lower right corner of the “watching” click, if you feel the content of the article is good, remember to share moments to let more people know!
[Code access ****]
Identify the qr code at the end of the article, reply: 0506