Python3 微信支付(小程序支付)V3接口的实现

 更新时间:2023年01月17日 15:57:53   作者:宗乐平  
本文主要介绍了Python3 微信支付(小程序支付)V3接口的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

Python客栈送红包、纸质书

起因:

因公司项目需要网上充值功能,从而对接微信支付,目前也只对接了微信支付的小程序支付功能,在网上找到的都是对接微信支付V2版本接口,与我所对接的接口版本不一致,无法使用,特此记录下微信支付完成功能,使用Django完成后端功能,此文章用于记录使用,

以下代码仅供参考,如若直接商用出现任何后果请自行承担,本人概不负责。

功能:

调起微信支付,微信回调

代码:

1、准备工作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
mchid = "xxxxxx"                         # 商户号
pay_key = "xxxxxx"                       # 商户秘钥V3 使用V3接口必须使用V3秘钥
serial_num = "xxxxxx"                    # 证书序列号
  
# ======================前三个参数在微信支付中可找到===============================
# ============ 商户号(mchid ) 在账户中心——商户信息——微信支付商户号 (是纯数字) ==================
# ============= 商户秘钥(pay_key) 在账户中心——API安全——APIv3秘钥 (需手动设置) ===================
# ============= 证书序列号(serial_num) 在账户中心——API安全——API证书 (需手动申请,通过后会有串证书序列号),申请完成后需要把证书下载到项目中,便于使用 ===================
  
  
  
appid = "xxxxxx"                         # 微信小程序appid
wx_secret ="xxxxxx"                      # 微信小程序秘钥
# ============= 微信小程序appid 在产品中心——AppID账号管理——添加关联的AppID  ===================    
  
WX_Pay_URL = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi"
# ============= 微信支付调用地址,用于请求接收 预支付交易会话标识: prepay_id ===================
  
  
WX_Notify_URL = "https://127.0.0.1:8000" 
# ============= 接收微信支付回调地址,必须是https ===================

2、调起微信支付(后端只能请求微信支付接口向微信支付官方获取到预支付交易会话标识,并返回给前端,前端才能调起输入密码支付界面)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import json
import decimal
import traceback
  
import requests
from django.http import HttpResponse
  
  
def payment_view(request, *args, **kwargs):
    """
    微信支付(小程序)
    :param request:
    :param args:
    :param kwargs:
    :return:
    """
    try:
        reqdata = json.loads(request.body)
        # 前端参数
        jscode = reqdata["jscode"# 微信ID
        price = decimal.Decimal(reqdata["price"]).quantize(decimal.Decimal("0.00"))  # 充值金额,保留两位小数
        nickname = reqdata["nickname"# 微信昵称/支付宝名称 前端获取到返给后端做记录,可要可不要的字段
        paymode = reqdata["paymode"# 支付方式  1微信支付
        remark = reqdata["remark"# 支付内容描述
         
        # 根据jscode 获取openID
        rets = requests.get(url = "https://api.weixin.qq.com/sns/jscode2session?" \
              "appid=%s&secret=%s&js_code=%s" \
              "&grant_type=authorization_code" % (appid,wx_secret, js_code), timeout=3, verify=False)
        if not rets:
            return HttpResponse(general_error_msg(msg="未获取到微信信息"))
  
        # 0.获取支付的微信openid
        print(f"组织ID:{userinfo['orgid']}, jscode:{jscode}")
        wxuser = getappopenid(orgid, jscode)
        if wxuser:
            # session_key = wxuser["session_key"]
            openid = wxuser["openid"]
        else:
            return HttpResponse(general_error_msg(msg="未获取到微信用户信息"))
  
        # 1.以交易日期生成交易号
        orderno = order_num()
        # 2.生成新交易记录 paystatus 支付状态  1成功 0待支付 -1支付失败
        conorder.objects.create(orderno=orderno, openid=openid, openname=nickname,
                                paymode=paymode,goodstotalprice=price, paystatus=0,
                                remark=remark,createtime=get_now_time(1))
        # 3.生成统一下单的报文body
        url = WX_Pay_URL
        body = {
            "appid": appid,
            "mchid": mchid,
            "description": remark,
            "out_trade_no": orderno,
            "notify_url": WX_Notify_URL + "/pay/notify"# 后端接收回调通知的接口
            "amount": {"total": int(price * 100), "currency": "CNY"},  # 正式上线price要*100,微信金额单位为分(必须整型)。
            "payer": {"openid": openid},
        }
        data = json.dumps(body)
  
        headers, random_str, time_stamps = make_headers_v3(mchid, serial_num, data=data, method='POST')
  
        # 10.发送请求获得prepay_id
        try:
            response = requests.post(url, data=data, headers=headers)  # 获取预支付交易会话标识(prepay_id)
            print("预支付交易会话标识", response)
            if response.status_code == 200:
                wechatpay_serial, wechatpay_timestamp, wechatpay_nonce, wechatpay_signature, certificate, serial_no = check_wx_cert(
                    response, mchid, pay_key, serial_num)
                # 11.9签名验证
                if wechatpay_serial == serial_no:  # 应答签名中的序列号同证书序列号应相同
                    print('serial_no match')
                    try:
                        data3 = f"{wechatpay_timestamp}\n{wechatpay_nonce}\n{response.text}\n"
                        verify(data3, wechatpay_signature, certificate)
                        print('The signature is valid.')
                        # 12.生成调起支付API需要的参数并返回前端
                        res = {
                            'orderno': orderno,  # 订单号
                            'timeStamp': time_stamps,
                            'nonceStr': random_str,
                            'package': 'prepay_id=' + response.json()['prepay_id'],
                            'signType': "RSA",
                            'paySign': get_sign(f"{appid}\n{time_stamps}\n{random_str}\n{'prepay_id=' + response.json()['prepay_id']}\n"),
                        }
                        return HttpResponse(success_msg(msg="下单成功", total=0, data=res))
                    except Exception as e:
                        log.error(f"证书序列号验签失败{e}, {traceback.format_exc()}")
                        return HttpResponse(general_error_msg(msg="下单失败"))
                else:
                    log.error(f"证书序列号比对失败【请求头中证书序列号:{wechatpay_serial};本地存储证书序列号:{serial_no};】")
                    return HttpResponse(general_error_msg(msg="调起微信支付失败!"))
            else:
                log.error(f"获取预支付交易会话标识 接口报错【params:{data};headers:{headers};response:{response.text}】")
                return HttpResponse(general_error_msg(msg="调起微信支付失败!"))
        except Exception as e:
            log.error(f"调用微信支付接口超时【params:{data};headers:{headers};】:{e},{traceback.format_exc()}")
            return HttpResponse(general_error_msg(msg="微信支付超时!"))
    except Exception as e:
        log.error(f"微信支付接口报错:{e},{traceback.format_exc()}")
        return HttpResponse(general_error_msg(msg="微信支付接口报错!"))

3、相关方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
import base64
import random
import string
import time
import traceback
from datetime import datetime
  
import requests
from BaseMethods.log import log
from Crypto.PublicKey import RSA
from Crypto.Signature import pkcs1_15
from Cryptodome.Hash import SHA256
from sqlalchemy.util import b64encode
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
  
# 各包版本
# django-ratelimit==3.0.1
# SQLAlchemy~=1.4.44
# pycryptodome==3.16.0
# pycryptodomex==3.16.0
# cryptography~=38.0.4
# Django~=3.2.4
  
# 获取唯一标识
def get_uuid(utype=0):
    """
    唯一码
    :param utype:
    :return:
    """
    if utype == 0:
        return uuid.uuid1()
    elif utype == 1:
        return str(uuid.uuid1())
    elif utype == 2:
        return str(uuid.uuid1().hex)
    elif utype == 3:
        return str((uuid.uuid5(uuid.NAMESPACE_DNS, str(uuid.uuid1()) + str(random.random()))))
  
  
# 获取当前时间
def get_now_time(type=0):
    """
    :param type: 类型0-5
    :return: yyyy-mm-dd HH:MM:SS;y-m-d H:M:S.f;y-m-d;ymdHMS;y年m月d日h时M分S秒
    """
    if type == 0:
        return datetime.datetime.now()
    elif type == 1:
        return datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    elif type == 2:
        return datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")
    elif type == 3:
        return datetime.datetime.now().strftime("%Y-%m-%d")
    elif type == 4:
        return datetime.datetime.now().strftime("%Y%m%d%H%M%S")
    elif type == 5:
        locale.setlocale(locale.LC_CTYPE, 'chinese')
        timestr = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        t = time.strptime(timestr, "%Y-%m-%d %H:%M:%S")
        result = (time.strftime("%Y年%m月%d日%H时%M分%S秒", t))
        return result
    elif type == 6:
        return datetime.datetime.now().strftime("%Y%m%d")
  
  
# 重构系统jargon类,用于处理时间格式报错问题
class DateEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime.datetime):
            return obj.strftime('%Y-%m-%d %H:%M:%S')
        elif isinstance(obj, datetime.date):
            return obj.strftime("%Y-%m-%d")
        elif isinstance(obj, Decimal):
            return float(obj)
        elif isinstance(obj, bytes):
            return str(obj, encoding='utf-8')
        elif isinstance(obj, uuid.UUID):
            return str(obj)
        elif isinstance(obj, datetime.time):
            return obj.strftime('%H:%M')
        elif isinstance(obj, datetime.timedelta):
            return str(obj)
        else:
            return json.JSONEncoder.default(self, obj)
  
  
  
  
def decrypt(nonce, ciphertext, associated_data, pay_key):
    """
    AES解密
    :param nonce:
    :param ciphertext:
    :param associated_data:
    :param pay_key:
    :return:
    """
    key = pay_key
    key_bytes = str.encode(key)
    nonce_bytes = str.encode(nonce)
    ad_bytes = str.encode(associated_data)
    data = base64.b64decode(ciphertext)
    aesgcm = AESGCM(key_bytes)
    return aesgcm.decrypt(nonce_bytes, data, ad_bytes)
  
  
def order_num():
    """
    生成订单号
    :return:
    """
    # 下单时间的年月日毫秒12+随机数8位
    now_time = datetime.now()
    result = str(now_time.year) + str(now_time.month) + str(now_time.day) + str(now_time.microsecond) + str(
        random.randrange(10000000, 99999999))
    return result
  
  
def get_sign(sign_str):
    """
    定义生成签名的函数
    :param sign_str:
    :return:
    """
    try:
        with open(r'static/cret/apiclient_key.pem') as f:
            private_key = f.read()
        rsa_key = RSA.importKey(private_key)
        signer = pkcs1_15.new(rsa_key)
        digest = SHA256.new(sign_str.encode('utf-8'))
        # sign = b64encode(signer.sign(digest)).decode('utf-8')
        sign = b64encode(signer.sign(digest))
        return sign
    except Exception as e:
        log.error("生成签名的函数方法报错【func:get_sign;sign_str:%s】:%s ==> %s" % (sign_str, e, traceback.format_exc()))
  
  
def check_wx_cert(response, mchid, pay_key, serial_no):
    """
    微信平台证书
    :param response: 请求微信支付平台所对应的的接口返回的响应值
    :param mchid: 商户号
    :param pay_key: 商户号秘钥
    :param serial_no: 证书序列号
    :return:
    """
    wechatpay_serial, wechatpay_timestamp, wechatpay_nonce, wechatpay_signature, certificate = None, None, None, None, None
    try:
        # 11.应答签名验证
        wechatpay_serial = response.headers['Wechatpay-Serial'# 获取HTTP头部中包括回调报文的证书序列号
        wechatpay_signature = response.headers['Wechatpay-Signature'# 获取HTTP头部中包括回调报文的签名
        wechatpay_timestamp = response.headers['Wechatpay-Timestamp'# 获取HTTP头部中包括回调报文的时间戳
        wechatpay_nonce = response.headers['Wechatpay-Nonce'# 获取HTTP头部中包括回调报文的随机串
        # 11.1.获取微信平台证书 (等于又把前面的跑一遍,实际上应是获得一次证书就存起来,不用每次都重新获取一次)
        url2 = "https://api.mch.weixin.qq.com/v3/certificates"
        # 11.2.生成证书请求随机串
        random_str2 = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(32))
        # 11.3.生成证书请求时间戳
        time_stamps2 = str(int(time.time()))
        # 11.4.生成请求证书的签名串
        data2 = ""
        sign_str2 = f"GET\n{'/v3/certificates'}\n{time_stamps2}\n{random_str2}\n{data2}\n"
        # 11.5.生成签名
        sign2 = get_sign(sign_str2)
        # 11.6.生成HTTP请求头
        headers2 = {
            "Content-Type": "application/json",
            "Accept": "application/json",
            "Authorization": 'WECHATPAY2-SHA256-RSA2048 '
                             + f'mchid="{mchid}",nonce_str="{random_str2}",signature="{sign2}",timestamp="{time_stamps2}",serial_no="{serial_no}"'
        }
        # 11.7.发送请求获得证书
        response2 = requests.get(url2, headers=headers2)  # 只需要请求头
        cert = response2.json()
  
        # 11.8.证书解密
        nonce = cert["data"][0]['encrypt_certificate']['nonce']
        ciphertext = cert["data"][0]['encrypt_certificate']['ciphertext']
        associated_data = cert["data"][0]['encrypt_certificate']['associated_data']
        serial_no = cert["data"][0]['serial_no']
        certificate = decrypt(nonce, ciphertext, associated_data, pay_key)
    except Exception as e:
        log.error(f"微信平台证书验证报错:{e};{traceback.format_exc()}")
    return wechatpay_serial, wechatpay_timestamp, wechatpay_nonce, wechatpay_signature, certificate, serial_no
  
  
def verify(check_data, signature, certificate):
    """
    验签函数
    :param check_data:
    :param signature:
    :param certificate:
    :return:
    """
    key = RSA.importKey(certificate)  # 这里直接用了解密后的证书,但没有去导出公钥,似乎也是可以的。怎么导公钥还没搞懂。
    verifier = pkcs1_15.new(key)
    hash_obj = SHA256.new(check_data.encode('utf8'))
    return verifier.verify(hash_obj, base64.b64decode(signature))
  
  
def make_headers_v3(mchid, serial_num, data='', method='GET'):
    """
    定义微信支付请求接口中请求头认证
    :param mchid: 商户ID
    :param serial_num: 证书序列号
    :param data: 请求体内容
    :param method: 请求方法
    :return: headers(请求头)
    """
    # 4.定义生成签名的函数 get_sign(sign_str)
    # 5.生成请求随机串
    random_str = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(32))
    # 6.生成请求时间戳
    time_stamps = str(int(time.time()))
    # 7.生成签名串
    sign_str = f"{method}\n{'/v3/pay/transactions/jsapi'}\n{time_stamps}\n{random_str}\n{data}\n"
    # 8.生成签名
    sign = get_sign(sign_str)
    # 9.生成HTTP请求头
    headers = {
        'Content-Type': 'application/json',
        'Authorization': 'WECHATPAY2-SHA256-RSA2048 '
                         + f'mchid="{mchid}",nonce_str="{random_str}",signature="{sign}",timestamp="{time_stamps}",serial_no="{serial_num}"'
    }
    return headers, random_str, time_stamps

4、微信回调

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import decimal
import json
import traceback
  
from django.http import HttpResponse
  
  
def notify_view(request, *args, **kwargs):
    """
    支付完成之后的通知(微信官方返回的数据)
    :param request:
    :param args:
    :param kwargs:
    :return:
    """
    try:
        # 1.获得支付通知的参数
        body = request.body
        data = bytes.decode(body, 'utf-8')
        newdata = json.loads(data)
        # newdata = {
        #     "id": "9d40acfd-13cb-5175-a5aa-6c421f794952",
        #     "create_time": "2023-01-06T15:12:49+08:00",
        #     "resource_type": "encrypt-resource",
        #     "event_type": "TRANSACTION.SUCCESS",
        #     "summary": "\xe6\x94\xaf\xe4\xbb\x98\xe6\x88\x90\xe5\x8a\x9f",
        #     "resource": {
        #         "original_type":
        #         "transaction",
        #         "algorithm": "AEAD_AES_256_GCM",
        #         "ciphertext": "UF5gLXfe8qBv9qxQsf+/Mb6as+vbIhUS8Dm25qGIJIIdXTorUUjqZH1+"
        #                       "jMQxkxma/Gn9bOxeAoQWPEuIoJ2pB328Iv90jmHTrouoP3L60mjNgGJS8d3H8i1zAPBXCpP4mgvgRANWsw4pAWj1lFM5BZr4aP+"
        #                       "pNMc5TdwreGBG3rO9sbCLXsSRfW8pVZ7IfPnhPDTOWP3P1k5ikHedcRt4/HP69oDBEe5RSsD93wO/"
        #                       "lrIwycStVHyecBaliwpVMRnNnRCXqhlalNJ3NJ6jcgy32fP1J+L90ntwGyqMmZUS71P5TN1H0iH5rXNpRY9IF3pvN+"
        #                       "lei5IS86wEoVXkmEsPcJrHaabn7rghxuZoqwuauMIiMwBLllnEmgXfAbJA4FJy+"
        #                       "OLhZPrMWMkkiNCLcL069QlvhLXYi/0V9PQVTnvtA5RLarj26s4WSqTZ2I5VGHbTqSIZvZYK3F275KEbQsemYETl18xwZ+"
        #                       "WAuSrYaSKN/pKykK37vUGtT3FeIoJup2c6M8Ghull3OcVmqCOsgvU7/pNjl1rLKEJB6t/X9avcHv+feikwQBtBmd/b2qCeSrEpM7US",
        #         "associated_data": "transaction",
        #         "nonce": "cKEdw8eV9Bh0"
        #     }
        # }
        nonce = newdata['resource']['nonce']
        ciphertext = newdata['resource']['ciphertext']
        associated_data = newdata['resource']['associated_data']
  
        try:
           payment = decrypt(nonce, ciphertext, associated_data, pay_key)
           break
        except Exception as e:
           print(e)
        if not payment:
            return HttpResponse({"code": "FAIL", "message": "失败"}, status=400)
        payment = eval(payment.decode('utf-8'))
        # payment = {
        #     "mchid": "xxxx",
        #     "appid": "xxxx",
        #     "out_trade_no": "20231654836163523608",
        #     "transaction_id": "4200001646202301065425000524",
        #     "trade_type": "JSAPI",
        #     "trade_state": "SUCCESS",
        #     "trade_state_desc": "\xe6\x94\xaf\xe4\xbb\x98\xe6\x88\x90\xe5\x8a\x9f",
        #     "bank_type": "OTHERS",
        #     "attach": "",
        #     "success_time": "2023-01-06T15:12:49+08:00",
        #     "payer": {
        #         "openid": "xxxxx"
        #     },
        #     "amount": {
        #         "total": 1,
        #         "payer_total": 1,
        #         "currency": "CNY",
        #         "payer_currency": "CNY"
        #     }
        # }
        orderno = payment['out_trade_no']
        zf_status = True if payment["trade_type"] == "SUCCESS" else False
        if zf_status:
            money = decimal.Decimal(int(payment["amount"]["payer_total"]) / 100).quantize(decimal.Decimal("0.00"))
        else:
            money = decimal.Decimal(0.0).quantize(decimal.Decimal("0.00"))
        # 7.回调报文签名验证
        # 同第一篇签名验证的代码
        wechatpay_serial, wechatpay_timestamp, wechatpay_nonce, wechatpay_signature, certificate = check_wx_cert(request, mchid, pay_key, serial_num)
        if wechatpay_serial == serial_num:  # 应答签名中的序列号同证书序列号应相同
            # 8.获得回调报文中交易号后修改已支付订单状态
            res = conorder.objects.filter(orderno=orderno, paystatus=-1).first()
            if res:
                res.paystatus = 1
                res.save()
            else:
                res.paystatus = -1
                res.save()
            # 9.项目业务逻辑
            return HttpResponse({"code": "SUCCESS", "message": "成功"})
        else:
            log.error(f"证书序列号比对失败【请求头中证书序列号:{wechatpay_serial};本地存储证书序列号:{serial_num};】")
            return HttpResponse({"code": "FAIL", "message": "失败"}, status=400)
    except Exception as e:
        log.error(f"微信回调接口报错:{e},{traceback.format_exc()}")
        return HttpResponse({"code": "FAIL", "message": "失败"}, status=400)

5、参考文章:

在此非常感谢博主,文章链接如下:https://zhuanlan.zhihu.com/p/402449405

到此这篇关于Python3 微信支付(小程序支付)V3接口的实现的文章就介绍到这了,更多相关Python3 微信支付V3接口内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
蓄力AI

微信公众号搜索 “ 脚本之家 ” ,选择关注

程序猿的那些事、送书等活动等着你

原文链接:https://blog.csdn.net/qq_42142258/article/details/128653725

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 reterry123@163.com 进行投诉反馈,一经查实,立即处理!

相关文章

  • Python+Turtle绘制可爱的小蜜蜂详解

    Python+Turtle绘制可爱的小蜜蜂详解

    turtle库是一个点线面的简单图像库,在Python2.6之后被引入进来,能够完成一些比较简单的几何图像可视化。本文将利用turtle绘制一个可爱的小蜜蜂,感兴趣的可以试一试
    2022-05-05
  • 关于Python中两个不同shape的数组间运算规则

    关于Python中两个不同shape的数组间运算规则

    这篇文章主要介绍了关于Python中两个不同shape的数组间运算规则,众所周知,相同 shape 的两个数组间运算是指两个数组的对应元素相加,我们经常会碰到一些不同 shape 的数组间运算,需要的朋友可以参考下
    2023-08-08
  • Python 用Redis简单实现分布式爬虫的方法

    Python 用Redis简单实现分布式爬虫的方法

    本篇文章主要介绍了Python 用Redis简单实现分布式爬虫的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-11-11
  • python、PyTorch图像读取与numpy转换实例

    python、PyTorch图像读取与numpy转换实例

    今天小编就为大家分享一篇python、PyTorch图像读取与numpy转换实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-01-01
  • Python利用for循环打印星号三角形的案例

    Python利用for循环打印星号三角形的案例

    这篇文章主要介绍了Python利用for循环打印星号三角形的案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-04-04
  • Python实现遍历大量表格文件并筛选出数据缺失率低的文件

    Python实现遍历大量表格文件并筛选出数据缺失率低的文件

    这篇文章主要为大家详细介绍了如何利用Python实现遍历大量表格文件并筛选出表格内数据缺失率低的文件的功能,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-05-05
  • Python实现yaml与json文件批量互转

    Python实现yaml与json文件批量互转

    这篇文章主要为大家详细介绍了如何利用Python语言实现yaml与json文件的批量互转,文中的示例代码讲解详细,感兴趣的小伙伴可以动手尝试一下
    2022-07-07
  • 基于Python实现帕累托图的示例详解

    基于Python实现帕累托图的示例详解

    帕累托图是一种特殊的直方图, 在项目管理知识体系中属于质量管理的工具。本文为大家整理了Python实现帕累托图的方法,需要的可以参考一下
    2023-03-03
  • 详解Python单元测试的两种写法

    详解Python单元测试的两种写法

    python的两个单元测试包分别是 doctest 和 unittest,这两个包的使用起来各有长处,适用于不同的场景,这篇文章主要介绍了Python单元测试的两种写法,需要的朋友可以参考下
    2022-07-07
  • python 画三维图像 曲面图和散点图的示例

    python 画三维图像 曲面图和散点图的示例

    今天小编就为大家分享一篇python 画三维图像 曲面图和散点图的示例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-12-12

最新评论