软件测试——python实现接口自动化

基础模块

requests模块

requests 是Python一个常用的 HTTP 请求库,可以方便地向网站发送 HTTP 请求,并获取响应结果。

***导入模块***
import requests





***发送请求***
'''
发送GET请求:requests.get(url, params=None, **kwargs)
发送POST请求:requests.post(url, data=None, json=None, **kwargs)
发送PUT请求:requests.put(url, data=None, **kwargs)
发送DELETE请求:requests.delete(url, **kwargs)
发送任意请求(常用):requests.request(method, url, **kwargs)

注意:
1.发送get请求时,请注意传入的params会自动解析拼接在url后面。所以其实也可以不传params,传url时直接带上这部分参数也行
2.发送post请求时,请注意该接口的请求头里约定的是“application/x-www-formurlencoded”还是“application/json”,前者的话传data,后者的话传json
3.通过上面的方法返回的是一个Response对象,该对象有一些常用的属性和方法:
cookies:返回一个 CookieJar 对象,包含了从服务器发回的 cookie
status_code:状态码
text:返回字符串方式的响应体,会自动根据响应头部的字符编码进行解码
json():返回内容进行json转换
'''

# 发送get请求(通过params传参)
url_get1 = 'http://127.0.0.1:8787/coupApply/cms/goodsList'
header_get1 = {'Content-Type': 'application/x-www-formurlencoded;charset=UTF-8'}
params_get1 = {
    "msgType": "getHandsetListOfCust",
    "page": 1,
    "size": 20
}

res_get1 = requests.get(url=url_get1, params=params_get1, headers=header_get1)



# 发送get请求(通过url传参)
url_get2 = 'http://127.0.0.1:8787/coupApply/cms/goodsList?msgType=getHandsetListOfCust&page=1&size=20'
header_get2 = {'Content-Type': 'application/x-www-formurlencoded;charset=UTF-8'}

res_get2 = requests.get(url=url_get2, headers=header_get2)



# 发送post请求(x-www-formurlencoded)
url_post1 = 'http://127.0.0.1:8787/dar/user/login'
header_post1 = {'Content-Type': 'application/x-www-formurlencoded;charset=UTF-8'}
data_post1 = {
    "user_name": "test01",
    "passwd": "admin123"
}

res_post1 = requests.post(url=url_post1, data=data_post1)
# 获取登录接口响应的cookie
print(res_post1.cookies) # <RequestsCookieJar[<Cookie access_token_cookie=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmcmVzaCI6ZmFsc2UsImlhdCI6MTc0MTQyOTQ4MSwianRpIjoiYWVhM2FkN2QtYjFkNy00N2I2LTk0MGUtMzUzMmUzMGRiZTcyIiwidHlwZSI6ImFjY2VzcyIsInN1YiI6ImV4YW1wbGVfdXNlciIsIm5iZiI6MTc0MTQyOTQ4MSwiZXhwIjoxNzQxNDMwMzgxfQ.qejKoJE_4HejFLYMM7O_PRDUU3mecmo8s3IA07P9HSc for 127.0.0.1/>]>
cookie = requests.utils.dict_from_cookiejar(res_post1.cookies)
print(cookie) # {'access_token_cookie': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmcmVzaCI6ZmFsc2UsImlhdCI6MTc0MTQyOTQ4MSwianRpIjoiYWVhM2FkN2QtYjFkNy00N2I2LTk0MGUtMzUzMmUzMGRiZTcyIiwidHlwZSI6ImFjY2VzcyIsInN1YiI6ImV4YW1wbGVfdXNlciIsIm5iZiI6MTc0MTQyOTQ4MSwiZXhwIjoxNzQxNDMwMzgxfQ.qejKoJE_4HejFLYMM7O_PRDUU3mecmo8s3IA07P9HSc'}



# 发送post请求(json)
url_post2 = 'http://127.0.0.1:8787/coupApply/cms/productDetail'
header_post2 = {'Content-Type': 'application/json;charset=UTF-8'}
json_post2 = {
    "pro_id": "33809635011",
    "page": 1,
    "size": 20
}

res_post2 = requests.post(url=url_post2, json=json_post2, headers=header_post2)



# 使用request方法发送上一个post请求
method_request = 'post'

res_request = requests.request(method = method_request, url=url_post2, json=json_post2, headers=header_post2)
# 获取接口响应的状态码
print(res_request.status_code) # 200
# 获取接口响应内容(文本)
print(res_request.text) # {"api_info":"today:21 max:10000 all[90=21+33+36];expires:2030-12-31","api_type":"pinduoduo","cache":0,"call_args":{"num_iid":"1620002566"},"client_ip":"106.6.39.223","error":"","error_code":"0000","execution_time":"0.437","goodsId":"56996760797","item":{"AmountOnSale":3188,"CategoryId":8484,"Coupon":null,"Delivery":{"From":null,"Info":null,"MarkInfo":null,"Postage":"快递 免运费","To":null,"extras":null},"DescUrl":null,"Detail":"<img src=\"https://img.pddpic.com/mms-material-img/2022-09-18/3f89d470-1af8-4dee-b529-6d62aa2ea3b7.png\" style=\"width:100%;\"/><img src=\"https://t00img.yangkeduo.com/goods/images/2019-02-15/ddf6fe7b-b536-4183-932d-69a1189a3f59.png\" style=\"width:100%;\"/><img src=\"https://t00img.yangkeduo.com/goods/images/2018-09-02/20f659b04d3e7e5851c27ff9931c96fc.jpeg\" style=\"width:100%;\"/><img src=\"https://t00img.yangkeduo.com/goods/images/2019-11-14/4420a8c3-49ed-46d8-ab55-15e7a638ca31.jpg\" style=\"width:100%;\"/><img src=\"https://t00img.yangkeduo.com/goods/images/2018-09-02/26c3e9d5cfbaf4e8f13b2bdd38f48d71.jpeg\" style=\"width:100%;\"/><img src=\"https://t00img.yangkeduo.com/goods/images/2018-09-02/0aa872fa74599dad7b6aefe6b6c035c0.jpeg\" style=\"width:100%;\"/><img src=\"https://t00img.yangkeduo.com/goods/images/2018-09-02/6bc959e32a30424c7a5284a37676999c.jpeg\" style=\"width:100%;\"/><img src=\"https://t00img.yangkeduo.com/goods/images/2018-09-02/1fa9861a8c99c5e9e8119fd2239fef5a.jpeg\" style=\"width:100%;\"/><img src=\"https://t00img.yangkeduo.com/goods/images/2018-09-02/b62cabf1d2320c5761e3f4c15203fb20.jpeg\" style=\"width:100%;\"/><img src=\"https://t00img.yangkeduo.com/goods/images/2018-09-02/6f6e54376a66cbc78e16700d4c424fe1.jpeg\" style=\"width:100%;\"/><img src=\"https://t00img.yangkeduo.com/goods/images/2018-09-02/2f60753dfc875a6876adc35833a69d31.jpeg\" style=\"width:100%;\"/><img src=\"https://t00img.yangkeduo.com/goods/images/2018-09-02/ae0116e589d8de712f8dafd0c356cefe.jpeg\" style=\"width:100%;\"/><img src=\"https://t00img.yangkeduo.com/goods/images/2018-09-02/da910c98fcc8de1b4d2d1498cd7899fd.jpeg\" style=\"width:100%;\"/><img src=\"https://t00img.yangkeduo.com/goods/images/2018-09-02/140349649d8b7d08c8e88bfbbaa2f900.jpeg\" style=\"width:100%;\"/><img src=\"https://t00img.yangkeduo.com/goods/images/2018-09-02/a953bae2eeb7364ef3ef2976a97d07eb.jpeg\" style=\"width:100%;\"/><img src=\"https://t00img.yangkeduo.com/goods/images/2018-09-02/4da59828136c3b1308aad0aa990778a7.jpeg\" style=\"width:100%;\"/><img src=\"https://t00img.yangkeduo.com/goods/images/2018-09-02/4a365b61a80e47288c8609ccd5982396.jpeg\" style=\"width:100%;\"/><img src=\"https://t00img.yangkeduo.com/goods/images/2018-11-17/cd0a8a96b783a51236812ce24c59a329.jpeg\" style=\"width:100%;\"/><img src=\"https://t00img.yangkeduo.com/goods/images/2018-11-17/16008ac19768d05e7dee16406ff958a1.jpeg\" style=\"width:100%;\"/><img src=\"https://t00img.yangkeduo.com/goods/images/2018-11-17/ef1d17b69ebf9449a8bb52459b168c26.jpeg\" style=\"width:100%;\"/>","FansCount":null,"ImageUrls":["https://omsproductionimg.yangkeduo.com/images/2017-12-12/bcf848aa71c6389607ae7a84b70f1543.jpeg","https://omsproductionimg.yangkeduo.com/images/2017-12-12/176019babfdecffa1d9f98f40b7e99b4.jpeg","https://omsproductionimg.yangkeduo.com/images/2017-12-12/efb5db42397550bffd3211ca6f197498.jpeg","https://omsproductionimg.yangkeduo.com/images/2017-12-12/d209ef7bcc9183c3bb8ca1dfdb108d49.jpeg","https://omsproductionimg.yangkeduo.com/images/2017-12-12/74257ab65f3f00da7a90fde9042fe640.jpeg","https://t00img.yangkeduo.com/goods/images/2019-08-17/e8fbd9cb-cc74-4caa-9380-84c46d27b008.jpg","https://t00img.yangkeduo.com/goods/images/2019-08-17/d76f515b-e375-4060-b94e-cf64f6b0964e.jpg","https://t00img.yangkeduo.com/goods/images/2019-08-17/f2f279b5-6000-4fbe-b99b-7c1cbd7884ea.jpg"],"MainImageVideo":null,"OfferId":1620002566,"OriginalPriceRangeInfos":[{"ConvertPrice":0,"Price":115,"Range":"3"}],"PriceRangeInfos":[{"ConvertPrice":0,"Price":95.4,"Range":"3"}],"ProductFeatureTuples":[{"Item1":"面料材质","Item2":"仿皮草"},{"Item1":"成分含量","Item2":"71%(含)—80%(含)"},{"Item1":"版型","Item2":"修身"},{"Item1":"领型","Item2":"圆领"},{"Item1":"衣长","Item2":"短款"},{"Item1":"是否带毛领","Item2":"不带毛领"},{"Item1":"主风格","Item2":"气质名媛"}],"ProductFeatures":{"主风格":"气质名媛","成分含量":"71%(含)—80%(含)","是否带毛领":"不带毛领","版型":"修身","衣长":"短款","面料材质":"仿皮草","领型":"圆领"},"RateCount":null,"RetryCount":0,"SellCount":"已拼4.2万件","SellerId":null,"SellerNick":null,"ShopId":"461742","ShopInfo":null,"ShopName":"果果家气质女装","ShopUrl":"http://yangkeduo.com/mall_page.html?mall_id=461742","SkuMaps":[{"AmountOnSale":73,"ImageUrl":"http://t00img.yangkeduo.com/goods/images/2018-08-28/062d42b525a7c786920cbb83ac772af7.jpeg","Key":"1215:1115500378;1226:119128","OriginalPrice":115,"Price":95.4,"SkuId":"57114357891","SpecAttributes":{"尺码":"S(90斤以下)","颜色":"粉色两件套(外套+裙子)"}},{"AmountOnSale":65,"ImageUrl":"http://t00img.yangkeduo.com/goods/images/2018-08-28/062d42b525a7c786920cbb83ac772af7.jpeg","Key":"1215:1115500378;1226:96784","OriginalPrice":115,"Price":95.4,"SkuId":"57114357892","SpecAttributes":{"尺码":"M(90-100斤)","颜色":"粉色两件套(外套+裙子)"}},{"AmountOnSale":82,"ImageUrl":"http://t00img.yangkeduo.com/goods/images/2018-08-28/062d42b525a7c786920cbb83ac772af7.jpeg","Key":"1215:1115500378;1226:33651","OriginalPrice":115,"Price":95.4,"SkuId":"57114357893","SpecAttributes":{"尺码":"L(100-110斤)","颜色":"粉色两件套(外套+裙子)"}},{"AmountOnSale":89,"ImageUrl":"http://t00img.yangkeduo.com/goods/images/2018-08-28/062d42b525a7c786920cbb83ac772af7.jpeg","Key":"1215:1115500378;1226:33652","OriginalPrice":115,"Price":95.4,"SkuId":"57114357894","SpecAttributes":{"尺码":"XL(110-120斤)","颜色":"粉色两件套(外套+裙子)"}},{"AmountOnSale":94,"ImageUrl":"http://t00img.yangkeduo.com/goods/images/2018-08-28/062d42b525a7c786920cbb83ac772af7.jpeg","Key":"1215:1115500378;1226:33653","OriginalPrice":115,"Price":95.4,"SkuId":"57114357895","SpecAttributes":{"尺码":"2XL(120-130斤)","颜色":"粉色两件套(外套+裙子)"}},{"AmountOnSale":105,"ImageUrl":"http://t00img.yangkeduo.com/goods/images/2018-08-28/062d42b525a7c786920cbb83ac772af7.jpeg","Key":"1215:1115500378;1226:33656","OriginalPrice":115,"Price":95.4,"SkuId":"57114357896","SpecAttributes":{"尺码":"3XL(130-140斤)","颜色":"粉色两件套(外套+裙子)"}},{"AmountOnSale":1051,"ImageUrl":"http://t00img.yangkeduo.com/goods/images/2018-08-28/415bed99d5a925123d7b7c39547205de.jpeg","Key":"1215:1115501666;1226:119128","OriginalPrice":115,"Price":95.4,"SkuId":"57114357897","SpecAttributes":{"尺码":"S(90斤以下)","颜色":"米色两件套(外套+裙子)"}},{"AmountOnSale":88,"ImageUrl":"http://t00img.yangkeduo.com/goods/images/2018-08-28/415bed99d5a925123d7b7c39547205de.jpeg","Key":"1215:1115501666;1226:96784","OriginalPrice":115,"Price":95.4,"SkuId":"57114357898","SpecAttributes":{"尺码":"M(90-100斤)","颜色":"米色两件套(外套+裙子)"}},{"AmountOnSale":80,"ImageUrl":"http://t00img.yangkeduo.com/goods/images/2018-08-28/415bed99d5a925123d7b7c39547205de.jpeg","Key":"1215:1115501666;1226:33651","OriginalPrice":115,"Price":95.4,"SkuId":"57114357899","SpecAttributes":{"尺码":"L(100-110斤)","颜色":"米色两件套(外套+裙子)"}},{"AmountOnSale":660,"ImageUrl":"http://t00img.yangkeduo.com/goods/images/2018-08-28/415bed99d5a925123d7b7c39547205de.jpeg","Key":"1215:1115501666;1226:33652","OriginalPrice":115,"Price":95.4,"SkuId":"57114357900","SpecAttributes":{"尺码":"XL(110-120斤)","颜色":"米色两件套(外套+裙子)"}},{"AmountOnSale":126,"ImageUrl":"http://t00img.yangkeduo.com/goods/images/2018-08-28/415bed99d5a925123d7b7c39547205de.jpeg","Key":"1215:1115501666;1226:33653","OriginalPrice":115,"Price":95.4,"SkuId":"57114357901","SpecAttributes":{"尺码":"2XL(120-130斤)","颜色":"米色两件套(外套+裙子)"}},{"AmountOnSale":89,"ImageUrl":"http://t00img.yangkeduo.com/goods/images/2018-08-28/415bed99d5a925123d7b7c39547205de.jpeg","Key":"1215:1115501666;1226:33656","OriginalPrice":115,"Price":95.4,"SkuId":"57114357902","SpecAttributes":{"尺码":"3XL(130-140斤)","颜色":"米色两件套(外套+裙子)"}},{"AmountOnSale":98,"ImageUrl":"http://t00img.yangkeduo.com/goods/images/2018-11-17/48b30664f0f7e526ab1b956e813f25cf.jpeg","Key":"1215:105309781;1226:119128","OriginalPrice":115,"Price":95.4,"SkuId":"103851107855","SpecAttributes":{"尺码":"S(90斤以下)","颜色":"蓝色两件套(外套+裙子)"}},{"AmountOnSale":95,"ImageUrl":"http://t00img.yangkeduo.com/goods/images/2018-11-17/3660b7893ca5cda1ffcea745d10b2506.jpeg","Key":"1215:105309781;1226:96784","OriginalPrice":115,"Price":95.4,"SkuId":"103851107856","SpecAttributes":{"尺码":"M(90-100斤)","颜色":"蓝色两件套(外套+裙子)"}},{"AmountOnSale":97,"ImageUrl":"http://t00img.yangkeduo.com/goods/images/2018-11-17/a4a5a671afbb2d8e1f4c21c0ced3bea8.jpeg","Key":"1215:105309781;1226:33651","OriginalPrice":115,"Price":95.4,"SkuId":"103851107857","SpecAttributes":{"尺码":"L(100-110斤)","颜色":"蓝色两件套(外套+裙子)"}},{"AmountOnSale":97,"ImageUrl":"http://t00img.yangkeduo.com/goods/images/2018-11-17/f0551176629bf81f25757c160198dba1.jpeg","Key":"1215:105309781;1226:33652","OriginalPrice":115,"Price":95.4,"SkuId":"103851107858","SpecAttributes":{"尺码":"XL(110-120斤)","颜色":"蓝色两件套(外套+裙子)"}},{"AmountOnSale":99,"ImageUrl":"http://t00img.yangkeduo.com/goods/images/2018-11-17/801a2e23140bfe76229f02aab0a8a5fe.jpeg","Key":"1215:105309781;1226:33653","OriginalPrice":115,"Price":95.4,"SkuId":"103851107853","SpecAttributes":{"尺码":"2XL(120-130斤)","颜色":"蓝色两件套(外套+裙子)"}},{"AmountOnSale":100,"ImageUrl":"http://t00img.yangkeduo.com/goods/images/2018-11-17/2f202934f16f0eee41257b77bf489262.jpeg","Key":"1215:105309781;1226:33656","OriginalPrice":115,"Price":95.4,"SkuId":"103851107854","SpecAttributes":{"尺码":"3XL(130-140斤)","颜色":"蓝色两件套(外套+裙子)"}}],"SkuProps":[{"IsImg":true,"Prop":"颜色","Value":[{"imageUrl":"http://t00img.yangkeduo.com/goods/images/2018-08-28/062d42b525a7c786920cbb83ac772af7.jpeg","name":"粉色两件套(外套+裙子)","value":"1215:1115500378"},{"imageUrl":"http://t00img.yangkeduo.com/goods/images/2018-08-28/415bed99d5a925123d7b7c39547205de.jpeg","name":"米色两件套(外套+裙子)","value":"1215:1115501666"},{"imageUrl":"http://t00img.yangkeduo.com/goods/images/2018-11-17/48b30664f0f7e526ab1b956e813f25cf.jpeg","name":"蓝色两件套(外套+裙子)","value":"1215:105309781"}]},{"IsImg":false,"Prop":"尺码","Value":[{"name":"S(90斤以下)","value":"1226:119128"},{"name":"M(90-100斤)","value":"1226:96784"},{"name":"L(100-110斤)","value":"1226:33651"},{"name":"XL(110-120斤)","value":"1226:33652"},{"name":"2XL(120-130斤)","value":"1226:33653"},{"name":"3XL(130-140斤)","value":"1226:33656"}]}],"SourceType":6,"Subject":"【2件套】套装秋冬新款仿獭兔毛钉珠皮草毛毛短外套加厚大衣女装","Tag":null,"Unit":null,"UserId":"461742","_ddf":"app","format_check":"ok"},"reason":"","request_id":"gw-4.63510267214bd","secache":"c98b29872e8a4b28859db207944ba817","secache_date":"2025-03-01 23:01:59","secache_time":1666253415,"server_memory":"0.84MB","server_time":"Beijing/2023-10-20 16:10:15","translate_engine":"baidu","translate_language":"zh-CN"}
# 获取接口响应内容(json格式)
print(res_request.json()) # {'api_info': 'today:21 max:10000 all[90=21+33+36];expires:2030-12-31', 'api_type': 'pinduoduo', 'cache': 0, 'call_args': {'num_iid': '1620002566'}, 'client_ip': '106.6.39.223', 'error': '', 'error_code': '0000', 'execution_time': '0.437', 'goodsId': '56996760797', 'item': {'AmountOnSale': 3188, 'CategoryId': 8484, 'Coupon': None, 'Delivery': {'From': None, 'Info': None, 'MarkInfo': None, 'Postage': '快递 免运费', 'To': None, 'extras': None}, 'DescUrl': None, 'Detail': '<img src="https://img.pddpic.com/mms-material-img/2022-09-18/3f89d470-1af8-4dee-b529-6d62aa2ea3b7.png" style="width:100%;"/><img src="https://t00img.yangkeduo.com/goods/images/2019-02-15/ddf6fe7b-b536-4183-932d-69a1189a3f59.png" style="width:100%;"/><img src="https://t00img.yangkeduo.com/goods/images/2018-09-02/20f659b04d3e7e5851c27ff9931c96fc.jpeg" style="width:100%;"/><img src="https://t00img.yangkeduo.com/goods/images/2019-11-14/4420a8c3-49ed-46d8-ab55-15e7a638ca31.jpg" style="width:100%;"/><img src="https://t00img.yangkeduo.com/goods/images/2018-09-02/26c3e9d5cfbaf4e8f13b2bdd38f48d71.jpeg" style="width:100%;"/><img src="https://t00img.yangkeduo.com/goods/images/2018-09-02/0aa872fa74599dad7b6aefe6b6c035c0.jpeg" style="width:100%;"/><img src="https://t00img.yangkeduo.com/goods/images/2018-09-02/6bc959e32a30424c7a5284a37676999c.jpeg" style="width:100%;"/><img src="https://t00img.yangkeduo.com/goods/images/2018-09-02/1fa9861a8c99c5e9e8119fd2239fef5a.jpeg" style="width:100%;"/><img src="https://t00img.yangkeduo.com/goods/images/2018-09-02/b62cabf1d2320c5761e3f4c15203fb20.jpeg" style="width:100%;"/><img src="https://t00img.yangkeduo.com/goods/images/2018-09-02/6f6e54376a66cbc78e16700d4c424fe1.jpeg" style="width:100%;"/><img src="https://t00img.yangkeduo.com/goods/images/2018-09-02/2f60753dfc875a6876adc35833a69d31.jpeg" style="width:100%;"/><img src="https://t00img.yangkeduo.com/goods/images/2018-09-02/ae0116e589d8de712f8dafd0c356cefe.jpeg" style="width:100%;"/><img src="https://t00img.yangkeduo.com/goods/images/2018-09-02/da910c98fcc8de1b4d2d1498cd7899fd.jpeg" style="width:100%;"/><img src="https://t00img.yangkeduo.com/goods/images/2018-09-02/140349649d8b7d08c8e88bfbbaa2f900.jpeg" style="width:100%;"/><img src="https://t00img.yangkeduo.com/goods/images/2018-09-02/a953bae2eeb7364ef3ef2976a97d07eb.jpeg" style="width:100%;"/><img src="https://t00img.yangkeduo.com/goods/images/2018-09-02/4da59828136c3b1308aad0aa990778a7.jpeg" style="width:100%;"/><img src="https://t00img.yangkeduo.com/goods/images/2018-09-02/4a365b61a80e47288c8609ccd5982396.jpeg" style="width:100%;"/><img src="https://t00img.yangkeduo.com/goods/images/2018-11-17/cd0a8a96b783a51236812ce24c59a329.jpeg" style="width:100%;"/><img src="https://t00img.yangkeduo.com/goods/images/2018-11-17/16008ac19768d05e7dee16406ff958a1.jpeg" style="width:100%;"/><img src="https://t00img.yangkeduo.com/goods/images/2018-11-17/ef1d17b69ebf9449a8bb52459b168c26.jpeg" style="width:100%;"/>', 'FansCount': None, 'ImageUrls': ['https://omsproductionimg.yangkeduo.com/images/2017-12-12/bcf848aa71c6389607ae7a84b70f1543.jpeg', 'https://omsproductionimg.yangkeduo.com/images/2017-12-12/176019babfdecffa1d9f98f40b7e99b4.jpeg', 'https://omsproductionimg.yangkeduo.com/images/2017-12-12/efb5db42397550bffd3211ca6f197498.jpeg', 'https://omsproductionimg.yangkeduo.com/images/2017-12-12/d209ef7bcc9183c3bb8ca1dfdb108d49.jpeg', 'https://omsproductionimg.yangkeduo.com/images/2017-12-12/74257ab65f3f00da7a90fde9042fe640.jpeg', 'https://t00img.yangkeduo.com/goods/images/2019-08-17/e8fbd9cb-cc74-4caa-9380-84c46d27b008.jpg', 'https://t00img.yangkeduo.com/goods/images/2019-08-17/d76f515b-e375-4060-b94e-cf64f6b0964e.jpg', 'https://t00img.yangkeduo.com/goods/images/2019-08-17/f2f279b5-6000-4fbe-b99b-7c1cbd7884ea.jpg'], 'MainImageVideo': None, 'OfferId': 1620002566, 'OriginalPriceRangeInfos': [{'ConvertPrice': 0, 'Price': 115, 'Range': '3'}], 'PriceRangeInfos': [{'ConvertPrice': 0, 'Price': 95.4, 'Range': '3'}], 'ProductFeatureTuples': [{'Item1': '面料材质', 'Item2': '仿皮草'}, {'Item1': '成分含量', 'Item2': '71%(含)—80%(含)'}, {'Item1': '版型', 'Item2': '修身'}, {'Item1': '领型', 'Item2': '圆领'}, {'Item1': '衣长', 'Item2': '短款'}, {'Item1': '是否带毛领', 'Item2': '不带毛领'}, {'Item1': '主风格', 'Item2': '气质名媛'}], 'ProductFeatures': {'主风格': '气质名媛', '成分含量': '71%(含)—80%(含)', '是否带毛领': '不带毛领', '版型': '修身', '衣长': '短款', '面料材质': '仿皮草', '领型': '圆领'}, 'RateCount': None, 'RetryCount': 0, 'SellCount': '已拼4.2万件', 'SellerId': None, 'SellerNick': None, 'ShopId': '461742', 'ShopInfo': None, 'ShopName': '果果家气质女装', 'ShopUrl': 'http://yangkeduo.com/mall_page.html?mall_id=461742', 'SkuMaps': [{'AmountOnSale': 73, 'ImageUrl': 'http://t00img.yangkeduo.com/goods/images/2018-08-28/062d42b525a7c786920cbb83ac772af7.jpeg', 'Key': '1215:1115500378;1226:119128', 'OriginalPrice': 115, 'Price': 95.4, 'SkuId': '57114357891', 'SpecAttributes': {'尺码': 'S(90斤以下)', '颜色': '粉色两件套(外套+裙子)'}}, {'AmountOnSale': 65, 'ImageUrl': 'http://t00img.yangkeduo.com/goods/images/2018-08-28/062d42b525a7c786920cbb83ac772af7.jpeg', 'Key': '1215:1115500378;1226:96784', 'OriginalPrice': 115, 'Price': 95.4, 'SkuId': '57114357892', 'SpecAttributes': {'尺码': 'M(90-100斤)', '颜色': '粉色两件套(外套+裙子)'}}, {'AmountOnSale': 82, 'ImageUrl': 'http://t00img.yangkeduo.com/goods/images/2018-08-28/062d42b525a7c786920cbb83ac772af7.jpeg', 'Key': '1215:1115500378;1226:33651', 'OriginalPrice': 115, 'Price': 95.4, 'SkuId': '57114357893', 'SpecAttributes': {'尺码': 'L(100-110斤)', '颜色': '粉色两件套(外套+裙子)'}}, {'AmountOnSale': 89, 'ImageUrl': 'http://t00img.yangkeduo.com/goods/images/2018-08-28/062d42b525a7c786920cbb83ac772af7.jpeg', 'Key': '1215:1115500378;1226:33652', 'OriginalPrice': 115, 'Price': 95.4, 'SkuId': '57114357894', 'SpecAttributes': {'尺码': 'XL(110-120斤)', '颜色': '粉色两件套(外套+裙子)'}}, {'AmountOnSale': 94, 'ImageUrl': 'http://t00img.yangkeduo.com/goods/images/2018-08-28/062d42b525a7c786920cbb83ac772af7.jpeg', 'Key': '1215:1115500378;1226:33653', 'OriginalPrice': 115, 'Price': 95.4, 'SkuId': '57114357895', 'SpecAttributes': {'尺码': '2XL(120-130斤)', '颜色': '粉色两件套(外套+裙子)'}}, {'AmountOnSale': 105, 'ImageUrl': 'http://t00img.yangkeduo.com/goods/images/2018-08-28/062d42b525a7c786920cbb83ac772af7.jpeg', 'Key': '1215:1115500378;1226:33656', 'OriginalPrice': 115, 'Price': 95.4, 'SkuId': '57114357896', 'SpecAttributes': {'尺码': '3XL(130-140斤)', '颜色': '粉色两件套(外套+裙子)'}}, {'AmountOnSale': 1051, 'ImageUrl': 'http://t00img.yangkeduo.com/goods/images/2018-08-28/415bed99d5a925123d7b7c39547205de.jpeg', 'Key': '1215:1115501666;1226:119128', 'OriginalPrice': 115, 'Price': 95.4, 'SkuId': '57114357897', 'SpecAttributes': {'尺码': 'S(90斤以下)', '颜色': '米色两件套(外套+裙子)'}}, {'AmountOnSale': 88, 'ImageUrl': 'http://t00img.yangkeduo.com/goods/images/2018-08-28/415bed99d5a925123d7b7c39547205de.jpeg', 'Key': '1215:1115501666;1226:96784', 'OriginalPrice': 115, 'Price': 95.4, 'SkuId': '57114357898', 'SpecAttributes': {'尺码': 'M(90-100斤)', '颜色': '米色两件套(外套+裙子)'}}, {'AmountOnSale': 80, 'ImageUrl': 'http://t00img.yangkeduo.com/goods/images/2018-08-28/415bed99d5a925123d7b7c39547205de.jpeg', 'Key': '1215:1115501666;1226:33651', 'OriginalPrice': 115, 'Price': 95.4, 'SkuId': '57114357899', 'SpecAttributes': {'尺码': 'L(100-110斤)', '颜色': '米色两件套(外套+裙子)'}}, {'AmountOnSale': 660, 'ImageUrl': 'http://t00img.yangkeduo.com/goods/images/2018-08-28/415bed99d5a925123d7b7c39547205de.jpeg', 'Key': '1215:1115501666;1226:33652', 'OriginalPrice': 115, 'Price': 95.4, 'SkuId': '57114357900', 'SpecAttributes': {'尺码': 'XL(110-120斤)', '颜色': '米色两件套(外套+裙子)'}}, {'AmountOnSale': 126, 'ImageUrl': 'http://t00img.yangkeduo.com/goods/images/2018-08-28/415bed99d5a925123d7b7c39547205de.jpeg', 'Key': '1215:1115501666;1226:33653', 'OriginalPrice': 115, 'Price': 95.4, 'SkuId': '57114357901', 'SpecAttributes': {'尺码': '2XL(120-130斤)', '颜色': '米色两件套(外套+裙子)'}}, {'AmountOnSale': 89, 'ImageUrl': 'http://t00img.yangkeduo.com/goods/images/2018-08-28/415bed99d5a925123d7b7c39547205de.jpeg', 'Key': '1215:1115501666;1226:33656', 'OriginalPrice': 115, 'Price': 95.4, 'SkuId': '57114357902', 'SpecAttributes': {'尺码': '3XL(130-140斤)', '颜色': '米色两件套(外套+裙子)'}}, {'AmountOnSale': 98, 'ImageUrl': 'http://t00img.yangkeduo.com/goods/images/2018-11-17/48b30664f0f7e526ab1b956e813f25cf.jpeg', 'Key': '1215:105309781;1226:119128', 'OriginalPrice': 115, 'Price': 95.4, 'SkuId': '103851107855', 'SpecAttributes': {'尺码': 'S(90斤以下)', '颜色': '蓝色两件套(外套+裙子)'}}, {'AmountOnSale': 95, 'ImageUrl': 'http://t00img.yangkeduo.com/goods/images/2018-11-17/3660b7893ca5cda1ffcea745d10b2506.jpeg', 'Key': '1215:105309781;1226:96784', 'OriginalPrice': 115, 'Price': 95.4, 'SkuId': '103851107856', 'SpecAttributes': {'尺码': 'M(90-100斤)', '颜色': '蓝色两件套(外套+裙子)'}}, {'AmountOnSale': 97, 'ImageUrl': 'http://t00img.yangkeduo.com/goods/images/2018-11-17/a4a5a671afbb2d8e1f4c21c0ced3bea8.jpeg', 'Key': '1215:105309781;1226:33651', 'OriginalPrice': 115, 'Price': 95.4, 'SkuId': '103851107857', 'SpecAttributes': {'尺码': 'L(100-110斤)', '颜色': '蓝色两件套(外套+裙子)'}}, {'AmountOnSale': 97, 'ImageUrl': 'http://t00img.yangkeduo.com/goods/images/2018-11-17/f0551176629bf81f25757c160198dba1.jpeg', 'Key': '1215:105309781;1226:33652', 'OriginalPrice': 115, 'Price': 95.4, 'SkuId': '103851107858', 'SpecAttributes': {'尺码': 'XL(110-120斤)', '颜色': '蓝色两件套(外套+裙子)'}}, {'AmountOnSale': 99, 'ImageUrl': 'http://t00img.yangkeduo.com/goods/images/2018-11-17/801a2e23140bfe76229f02aab0a8a5fe.jpeg', 'Key': '1215:105309781;1226:33653', 'OriginalPrice': 115, 'Price': 95.4, 'SkuId': '103851107853', 'SpecAttributes': {'尺码': '2XL(120-130斤)', '颜色': '蓝色两件套(外套+裙子)'}}, {'AmountOnSale': 100, 'ImageUrl': 'http://t00img.yangkeduo.com/goods/images/2018-11-17/2f202934f16f0eee41257b77bf489262.jpeg', 'Key': '1215:105309781;1226:33656', 'OriginalPrice': 115, 'Price': 95.4, 'SkuId': '103851107854', 'SpecAttributes': {'尺码': '3XL(130-140斤)', '颜色': '蓝色两件套(外套+裙子)'}}], 'SkuProps': [{'IsImg': True, 'Prop': '颜色', 'Value': [{'imageUrl': 'http://t00img.yangkeduo.com/goods/images/2018-08-28/062d42b525a7c786920cbb83ac772af7.jpeg', 'name': '粉色两件套(外套+裙子)', 'value': '1215:1115500378'}, {'imageUrl': 'http://t00img.yangkeduo.com/goods/images/2018-08-28/415bed99d5a925123d7b7c39547205de.jpeg', 'name': '米色两件套(外套+裙子)', 'value': '1215:1115501666'}, {'imageUrl': 'http://t00img.yangkeduo.com/goods/images/2018-11-17/48b30664f0f7e526ab1b956e813f25cf.jpeg', 'name': '蓝色两件套(外套+裙子)', 'value': '1215:105309781'}]}, {'IsImg': False, 'Prop': '尺码', 'Value': [{'name': 'S(90斤以下)', 'value': '1226:119128'}, {'name': 'M(90-100斤)', 'value': '1226:96784'}, {'name': 'L(100-110斤)', 'value': '1226:33651'}, {'name': 'XL(110-120斤)', 'value': '1226:33652'}, {'name': '2XL(120-130斤)', 'value': '1226:33653'}, {'name': '3XL(130-140斤)', 'value': '1226:33656'}]}], 'SourceType': 6, 'Subject': '【2件套】套装秋冬新款仿獭兔毛钉珠皮草毛毛短外套加厚大衣女装', 'Tag': None, 'Unit': None, 'UserId': '461742', '_ddf': 'app', 'format_check': 'ok'}, 'reason': '', 'request_id': 'gw-4.63510267214bd', 'secache': 'c98b29872e8a4b28859db207944ba817', 'secache_date': '2025-03-01 23:01:59', 'secache_time': 1666253415, 'server_memory': '0.84MB', 'server_time': 'Beijing/2023-10-20 16:10:15', 'translate_engine': 'baidu', 'translate_language': 'zh-CN'}

yaml模块

yaml模块是python中用来操作yaml文件的第三方库。

yaml介绍:
yaml是一种简洁的非标记语言,通常用来写配置文件。yaml文件的后缀为.yaml或.yml

语法特点:
  1、大小写敏感
  2、使用缩进表示层级关系
  3、缩进时不允许使用Tab键,只允许使用空格(缩进的空格数目不重要,只要相同层级的元素左侧对其即可,通常是两格)
  4、key值前面带-表示这组数据是一个列表类型,如果两组数据的-属于同级关系的话,数据存在在一个列表里面
  5、: 号后面要加空格
  6、# 表示注释
举例:(可在https://www.bejson.com/validators/yaml_editor/该网站验证yaml格式是否正确)
在这里插入图片描述

***导入模块***
import yaml





***解析yaml文件***
'''
yaml.safe_load(stream)

注意:
1.该此函数能将 YAML 文档解析成 Python 字典对象以便进一步操作
'''

with open('data.yaml','r',encoding='utf-8') as f:
    data = yaml.safe_load(f)
    print(data) # {'name': 'XiaoLi', 'age': 25, 'spouse': {'name': 'HuaHua', 'age': 23}, 'children': [{'name': 'Joy', 'age': 6}, {'name': 'Alix', 'age': 3}]}





***生成yaml文件***
'''
yaml.safe_dump(data, stream=None, **kwds)
'''

data = {'name': 'XiaoLi', 'age': 25, 'spouse': {'name': 'HuaHua', 'age': 23}, 'children': [{'name': 'Joy', 'age': 6}, {'name': 'Alix', 'age': 3}]}
with open('data.yaml','w',encoding='utf-8') as f:
    yaml.safe_dump(data, f)

os模块

os模块主要用于与操作系统进行交互,包括文件和目录的操作、路径处理、进程管理等。

***导入模块***
import os





***路径处理***
'''
获取当前文件所在目录:os.getcwd()
获取指定目录下的所有文件和文件夹,返回一个列表:os.listdir(path=None)
路径拼接:os.path.join(path, *paths)
判断指定的路径是否存在,返回布尔值:os.path.exists(path)
获取指定路径的目录部分:os.path.dirname(file_path)

注意:
Python有一个特殊变量“__file__”,它的值是一个字符串,包含了脚本的完整路径(包括文件名)。例如os.path.dirname(__file__)即代表获取当前脚本路径的目录部分
'''

# 获取当前文件所在目录
path1 = os.getcwd()
print(path1) # E:\ltt_PythonProject1



# 获取指定目录下的所有文件和文件夹
path2 = os.listdir(path='E:\ltt_PythonProject1')
print(path2) # ['.idea', '.venv', 'data.yaml', 'test1.py', 'test2.py', 'tmp.py']



# 路径拼接
path_middle = 'data'
path_end = 'report.pdf'

path_full = os.path.join(path1, path_middle, path_end)
print(path_full) # E:\ltt_PythonProject1\data\report.pdf



# 判断指定路径'E:\ltt_PythonProject1'是否存在
is_exist = os.path.exists('E:\ltt_PythonProject1')
print(is_exist,type(is_exist)) # True <class 'bool'>



# 获取当前脚本路径的目录部分
path3 = os.path.dirname(__file__)
print(path3) # E:\ltt_PythonProject1





***在终端执行命令***
'''
os.system(command)
'''

# 执行命令查看python版本
os.system("python --version") # Python 3.7.0

configparser模块

configparser模块主要用于操作配置文件(ini文件)

ini文件介绍:
ini 文件是一种常用配置文件,后缀通常为.ini

语法特点:
1.由节(section)、键(key)、值(value)组成
2.节用方括号 [] 表示,键和值之间用等号 = 或冒号 : 分隔
3.一个ini文件中可以有多个 section,每个 section 名字不能相同;每个 section 下可以有多个键值对,每个 section 下的键不能相同
4.#代表注释
举例:
在这里插入图片描述

***导入模块***
import configparser





***操作ini文件***
'''
创建ConfigParser对象:config = configparser.ConfigParser()
读取配置文件:config.read(filenames)
获取指定section下指定key的值:config.get(section, option)
'''

# 创建ConfigParser对象
config = configparser.ConfigParser()

# 读取配置文件
config.read('config.ini')

# 获取指定section(MySQL)下指定key(database)的值
database = config.get('MySQL', 'database')
print(database) # ecshop

time模块

time模块主要用于处理时间

***导入模块***
import time





***获取时间***
'''
获取当前时间戳:time.time()
'''

now_time = time.time()
print(now_time) # 1750059436.261765

datetime模块

datetime模块主要用于处理日期和时间。有以下几个常用类

date
time
datetime
timedelta

***导入datetime模块的date类***
from datetime import date





***获取当前日期***
'''
date.today()
'''

d = date.today()
print(d) # 2025-06-16
***导入datetime模块的time类***
from datetime import time





***创建特定时间***
'''
创建特定时间:time(hour, minute, second)
'''

t = time(14, 30, 0)
print(t)  # 14:30:00
***导入datetime模块的datetime类***
from datetime import datetime





***获取当前日期时间***
'''
datetime.now()
'''

dt = datetime.now()
print(dt)  # 2025-06-16 16:16:40.386623
***导入datetime模块的timedelta类***
from datetime import timedelta





***创建时间差对象***
'''
timedelta(days, seconds, minutes, hours)
'''

now = datetime.now()
future1 = now + timedelta(days=10)
future2 = now + timedelta(seconds=10)
future3 = now + timedelta(minutes=10)
future4 = now + timedelta(hours=10)
print(now)  # 2025-06-16 16:28:03.451147
print(future1)  # 2025-06-26 16:28:03.451147
print(future2)  # 2025-06-16 16:28:13.451147
print(future3)  # 2025-06-16 16:38:03.451147
print(future4)  # 2025-06-17 02:28:03.451147

re模块

re模块主要用于处理正则表达式。正则表达式是一种强大的文本匹配工具。

核心语法

1、普通字符
直接匹配自身。
2、元字符
.:匹配除换行符外的任意单个字符。
^:匹配字符串的起始位置。
$:匹配字符串的结束位置。
*:匹配前一个字符的零个或多个重复。
+:匹配前一个字符的一个或多个重复。
?:匹配前一个字符的零个或一个重复。
[]:匹配括号内的任意一个字符。
|:匹配两个模式中的任意一个。
():创建一个捕获组,用于提取匹配的部分。
\:转义字符,用于匹配特殊字符本身。
3、重复限定符
{n}:匹配前一个字符恰好 n 次。
{n,}:匹配前一个字符至少 n 次。
{n,m}:匹配前一个字符 n 到 m 次。
4、字符类
[abc]:匹配a、b或c中的任意一个字符。
[a-z]:匹配任意一个小写字母。
[A-Z]:匹配任意一个大写字母。
[0-9]:匹配任意一个数字字符。
5、预定义字符类
\d:匹配任意一个数字字符。
\D:匹配任意一个非数字字符。
\w:匹配任意一个字母、数字或下划线字符。
\W:匹配任意一个非字母、数字或下划线字符。
\s:匹配任意一个空白字符,包括空格、制表符、换行符等。
\S:匹配任意一个非空白字符。
6、非贪婪匹配
在量词后加 ?。如 *?、+?、??、{n,m}?,表示尽可能少地匹配。

***导入模块***
import re





***编译正则表达式***
'''
将正则表达式模式编译为正则表达式对象,提高重复使用的效率:re.compile(pattern, flags=0)

注:
1、flags表示标志,用于修改正则表达式的匹配方式。可以不填。常用re.S,表示匹配包括换行符在内的所有字符
'''

pattern = re.compile(r'\d+') # 表示匹配一个或多个数字





***匹配字符串***
'''
从字符串开头开始匹配:re.match(pattern, string, flags=0)
整个字符串完全匹配:re.fullmatch(pattern, string, flags=0)

注:
1、如果不匹配则返回 None;匹配则返回 Match 对象。group() 是 Match 对象的一个方法,用于返回匹配的子串
'''

result1 = re.match(r'\d+', '123abc')
print(result1.group())  # 123

result2 = re.fullmatch(r'\d+', '123')
print(result2.group())  # 123





***搜索字符串***
'''
扫描整个字符串,返回第一个匹配的子串:re.search(pattern, string, flags=0)
'''

result = re.search(r'\d+', 'abc123def') 
print(result.group())  # 123





***查找所有匹配***
'''
返回字符串中所有匹配子串的列表:re.findall(pattern, string, flags=0)
'''

result = re.findall(r'\d+', 'abc123def456')  
print(result)  # ['123', '456']





***替换字符串***
'''
用 repl 替换字符串中所有匹配的子串:re.sub(pattern, repl, string, count=0, flags=0)
'''

result = re.sub(r'\d+', 'X', 'abc123def456')  # 输出: 'abcXdefX'
print(result) # abcXdefX





***分割字符串***
'''
re.split(pattern, string, maxsplit=0, flags=0)
'''

result = re.split(r'\d+', 'abc123def456')
# 第一次匹配 '123',将字符串分割为 'abc' 和 'def456'。
# 第二次匹配 '456',将 'def456' 分割为 'def' 和 ''(因为 '456' 是字符串的末尾)
print(result) # ['abc', 'def', '']





***转义字符串中的特殊字符***
'''
re.escape(string)
'''

text = "hello.world?123*[]{}"
escaped_text = re.escape(text)
print(escaped_text) # hello\.world\?123\*\[\]\{\}

random模块

random 模块主要用于生成随机数

***导入模块***
import random





***choice()***
'''
从非空序列 seq 返回一个随机元素:choice(seq)
'''

list = [1, 2, 3, 4, 5]
random_num = random.choice(list)
print(random_num)

operator模块

该模块提供了一系列与 Python 内置运算符对应的高效函数,这些函数可以替代一些基本的运算符操作

***导入模块***
import operator





***比较运算符***
'''
等于:operator.eq(a,b)
不等于:operator.ne(a,b)
'''

is_eq = operator.eq(2,2) # True
is_ne = operator.ne(2,2) # False
print(is_eq, is_ne)

jsonpath模块

jsonpath 模块主要用于从 JSON 中提取特定信息

JSONPath教程见:(非官方,挂了就关键字搜索其他的)https://blog.youkuaiyun.com/zhouruifu2015/article/details/130056895
https://blog.youkuaiyun.com/fanfangyu/article/details/133988514
查看JSONPath提取值的网站:https://jsonpath.com/

***导入模块***
import jsonpath





***从json中提取指定信息***
import jsonpath
'''
jsonpath.jsonpath(json_data, jsonpath_expression)

注:
1、json_data 是要查询的 JSON 数据
2、jsonpath_expression 是 JSONPath 表达式,用于指定要提取的数据
'''

json_data = {
    "store": {
        "book": [
            {"category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95},
            {"category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99},
            {"category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99},
            {"category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99}
        ],
        "bicycle": {
            "color": "red",
            "price": 19.95
        }
    },
    "expensive": 10
}

# 查所有书籍的价格
prices = jsonpath.jsonpath(json_data, "$.store.book[*].price")
print(prices)  # [8.95, 12.99, 8.99, 22.99]

pymysql模块

pymysql 模块主要用于连接MySQL数据库进行增删改查

***导入模块***
import pymysql




***增删改查***
# 建立数据库连接
connection = pymysql.connect(
    host='192***33',      # 数据库主机地址
    port =3**6,   # 端口
    user='r**t',  # 数据库用户名
    password='S***%^&*',  # 数据库密码
    database='so***ev',  # 数据库名称
    charset='utf8mb4',     # 字符编码
    cursorclass=pymysql.cursors.DictCursor  # 返回字典形式的结果
)


# 使用连接对象创建操作游标
cursor = connection.cursor()


# 查询
# 查询多条数据
select_sql1 = "SELECT * FROM sys_position"
cursor.execute(select_sql1)
results = cursor.fetchall()
for row in results:
    print(row)
# 查询单条数据
select_sql2 = "SELECT * FROM sys_position WHERE remark = '测试'"
cursor.execute(select_sql2)
result = cursor.fetchone()
print(result)


# 删除
delete_sql = "DELETE FROM sys_position WHERE remark = 'test'"
cursor.execute(delete_sql)
connection.commit()


# 更新
update_sql = "UPDATE sys_position SET remark = '更新' WHERE name = '销售经理'"
cursor.execute(update_sql)
connection.commit()


# 插入
insert_sql = "INSERT INTO `sone_v324_240903_dev`.`sys_position` (`id`, `name`, `remark`, `create_time`, `update_time`, `create_by`, `update_by`, `org_id`, `reference_cnt`, `element_id`, `type`, `state`, `unique_code`, `is_enabled`, `audit_state`, `audit_by`, `audit_time`, `tenant_id`, `staff_size`, `qualification`, `responsibility`, `position_level_count`, `emp_count`) VALUES ('1962423700152467456', 'test0901', 'test', '2025-09-01 15:54:04', '2025-09-01 15:54:05', '1924282009449488384', '1924282009449488384', '1111ok5499d5403f924249dbf035b188', 0, NULL, 'a414069be2980d16f16970f18a9a569a', '1939896487765331968', '000089', 1, 0, NULL, NULL, NULL, 1, '', '', 0, 0)"
cursor.execute(insert_sql)
connection.commit()


# 关闭数据库连接
connection.close()

logging模块

logging是python中用于记录日志的模块。

日志有以下级别(从低到高。默认级别是WARNING,默认只会输出 WARNING 及以上的日志) :

DEBUG:详细信息,一般只在调试问题时使用。
INFO:证明事情按预期工作。
WARNING:某些没有预料到的事件的提示,或者在将来可能会出现的问题提示。例如:磁盘空间不足。但是软件还是会照常运行。
ERROR:由于更严重的问题,软件已不能执行一些功能了。
CRITICAL:严重错误,表明软件已不能继续运行了。

***导入模块***
import logging





***在控制台和文件中同时输出日志***

# 创建Logger( Logger是程序员直接交互的对象。通常使用模块的名字(如__name__)作为logger的名字,这样可以方便地追踪日志来自哪个模块。也可以自定义名字)
logger = logging.getLogger(__name__)

# 设置logger的捕获级别(这里设置为DEBUG,意味着logger会捕获DEBUG及以上级别的日志)
logger.setLevel(logging.DEBUG)



# 创建Handler(Handler决定日志的输出目的地是哪里,StreamHandler是控制台,FileHandler是文件)
console_handler = logging.StreamHandler()   # 日志输出到控制台
console_handler.setLevel(logging.INFO)  # 控制台只输出INFO及以上级别的日志

file_handler = logging.FileHandler('app.log', encoding='utf-8') # 日志输出到文件
file_handler.setLevel(logging.DEBUG) # 文件记录DEBUG及以上级别的日志

# 创建Formatter并绑定到Handler(Formatter决定日志的输出格式)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
console_handler.setFormatter(formatter)
file_handler.setFormatter(formatter)



# 将Handler添加到Logger
logger.addHandler(console_handler)
logger.addHandler(file_handler)



# 记录日志
logger.debug("This is a debug message")
logger.info("This is an info message")
logger.error("This is an error message")

效果:
在这里插入图片描述

Pytest框架

pytest安装

pip install pytest

pytest编写规则

1、测试文件以test_开头(或者以_test结尾也行)
2、测试类以Test开头(注意类里面不能带有__init__初始化构造函数)
3、测试函数以test_开头
在这里插入图片描述

pytest运行方式

!pytest中有很多的参数可用于控制测试的运行方式、输出格式等。如:

-s :输出调试信息,包括print信息
-v :显示更加详细的信息
-vs :把上面这两个参数一起使用
-k :指定运行的测试用例文件、目录等
-n :设置多线程并发执行测试用例文件
–reruns :设置测试用例失败重跑次数
-m :运行被特定标记的测试用例

一、命令行运行(一般用于调试)

1、查找并运行当前目录及其子目录中的所有以test_开头的文件

pytest

2、查找并运行指定目录及其子目录中的所有以test_开头的文件

pytest testcase/login  # testcase/login为指定目录

3、运行指定文件

pytest testcase/login/test_login.py  # testcase/login/test_login.py为指定文件

4、使用-k参数,匹配指定名称的目录、文件、函数并运行
1)匹配目录

pytest -k login # login为目录名

2)匹配文件

pytest -k test_login # test_login为文件名

3)匹配函数

pytest -k test_login_module # test_login_module为函数名

二、主函数运行(常用)

不指定参数和匹配项:

if __name__ == '__main__':
    pytest.main()

指定参数和匹配项:

if __name__ == '__main__':
    pytest.main(['-vs', '-k', 'test_add_user_01']) # -vs、-k是参数;test_add_user_01是想要匹配的名称

注!pytest运行时会自动读取配置文件:pytest.ini

pytest.ini是Pytest测试框架的配置文件,会在pytest运行时读取文件并应用其中的配置。一般放在项目的根目录下,文件名是固定写法,不可更改。

配置文件参数说明

addopts:用于在运行测试时传递额外的命令行选项(比如之前提的-v、-s等)
testpaths:用于指定pytest在哪些目录中查找测试文件
python_files:用于指定测试文件的命名匹配模式
python_classes:用于指定测试类的命名匹配模式
python_functions:用于指定测试函数的命名匹配模式
markers:用于注册自定义标记

例子

[pytest]
addopts = -s -v -n 3 --reruns 3

testpaths = ./testcase

python_files = test_*.py

python_classes = Test*

python_functions = test_*

markers =
    P1
    P3

断言

相等断言:assert a == b
不等断言:assert a != b
真假断言:assert bool_value
成员断言:assert item in container
非成员断言:assert item not in container
在这里插入图片描述

import pytest

class TestAssertResult:

    # 相等断言,判断两个值是否相等
    def test_assert_eq(self):
        exp = {"msg": "登录成功"}
        response = {"msg": "登录成功"}
        assert exp == response, '断言失败,它们不相等' #PASSED

    # 不相等断言,判断两个值是否不等
    def test_assert_nq(self):
        exp = {"msg": "登录成功"}
        response = {"msg": "登录成功"}
        assert exp != response, '断言失败,它们相等' #FAILED

    # 真值断言
    def test_assert_bool1(self):
        assert True is True, '真值断言失败' #PASSED 

    # 假值断言
    def test_assert_bool2(self):
        assert True is False, '假值断言失败' #FAILED 

    # 成员断言,检查 item 是否在容器中
    def test_assert_contains1(self):
        contains = "pytest"
        contains_lst = ['pytest', 'unittest', 'python']
        assert contains in contains_lst, '断言失败,contains没在contains_lst里' #PASSED 

    # 非成员断言,检查 item 是否不在容器中
    def test_assert_contains2(self):
        contains = "pytest"
        contains_lst = ['pytest', 'unittest', 'python']
        assert contains not in contains_lst, '断言失败,contains在contains_lst里' #FAILED

if __name__ == '__main__':
    pytest.main()

pytest丰富的插件系统

一、pytest_xdist插件实现并发执行

安装插件:

pip install pytest-xdist

代码实现:
pytest.ini文件增加配置:
在这里插入图片描述
测试文件:

import pytest
from time import sleep

class TestLogin:

    def test_login_success(self):
        sleep(1)
        print('登录成功场景')

    def test_login_failed(self):
        sleep(1)
        print('登录失败场景')

    def test_login_error(self):
        sleep(1)
        print('登录错误场景')

if __name__ == '__main__':
    pytest.main()   # 效果:原本的3s的执行时间被缩短到了1s

二、pytest-rerunfailures插件实现失败测试用例重跑

安装插件:

pip install pytest-rerunfailures

代码实现:
pytest.ini文件增加配置:
在这里插入图片描述
测试文件:

import pytest

class TestLogin:

    def test_login_success(self):
        import random
        assert random.choice([True, False]), '测试失败'

if __name__ == '__main__':
    pytest.main() # 效果:若测试失败会重复执行,超过3次还没成功就不再执行了

三、pytest-ordering插件实现自定义测试用例的执行顺序

安装插件:

pip install pytest-ordering

代码实现:
使用@pytest.mark.run(order=N)

import pytest

class TestAddUser:

    @pytest.mark.run(order=3)
    def test_add_user_01(self):
        print("新增用户01")

    @pytest.mark.run(order=2)
    def test_add_user_02(self):
        print("新增用户02")

    @pytest.mark.run(order=1)
    def test_add_user_03(self):
        print("新增用户03")

if __name__ == '__main__':
    pytest.main() # 效果:执行顺序为新增用户03、新增用户02、新增用户01

pytest分组执行

步骤一:在pytest.ini文件中注册自定义标记
在这里插入图片描述
步骤二:代码中使用@pytest.mark.标记用例
在这里插入图片描述
步骤三:在pytest.ini文件使用-m执行标记的那组测试用例
执行单组测试用例(下图表示只执行标记为P1的)
在这里插入图片描述
执行多组测试用例(下图表示只执行标记为P1或P3的)
在这里插入图片描述

pytest跳过执行

在这里插入图片描述

import pytest

class TestLogin:

    @pytest.mark.skip
    def test_login_failed(self):
        print('登录失败场景') # SKIPPED

    num = 5
    @pytest.mark.skipif(num == 5, reason="符合表达式条件,所以此用例跳过")
    def test_login_error(self):
        print('登录错误场景') # SKIPPED

    @pytest.mark.xfail
    def test_login_except(self):
        assert 1 == 2 # XFAIL

if __name__ == '__main__':
    pytest.main()

参数化

pytest使用@pytest.mark.parametrize装饰器实现参数化

语法
@pytest.mark.parametrize("params1,params2.....", iterable)
参数
"params1,params2....."用于指定测试函数的参数名称
iterable是可迭代的对象,如:列表、元组、字典
测试函数接收的参数名必须要与 "params1,params2....."保持一致,参数个数也要保持一致

import pytest

class TestParameter:

    # 可迭代对象为列表(传递多个参数)
    @pytest.mark.parametrize('username,password',
                             [('test01', 'password01'), ('test02', 'password02'), ('test03', 'password03')])
    def test_login01(self, username, password):
        print(username, password) # 函数执行了3次,传参分别为:test01 password01、test02 password02、test03 password03

    # 可迭代对象为列表(传递一个参数)
    @pytest.mark.parametrize('username', ['test01', 'test02', 'test03'])
    def test_login02(self, username):
        print(username) # 函数执行了3次,传参分别为:test01、test02、test03



    # 可迭代对象为元组
    @pytest.mark.parametrize('username', ('test01', 'test02', 'test03'))
    def test_login_03(self, username):
        print(username) # 函数执行了3次,传参分别为:test01、test02、test03



    # 可迭代对象为字典
    @pytest.mark.parametrize("test_data", [
        {"username": "test01", "password": "pwd01"},
        {"username": "test02", "password": "pwd02"},
    ])
    def test_login(self,test_data):
        print(test_data["username"],test_data["password"]) # 函数执行了2次,传参分别为:{"username": "test01", "password": "pwd01"}、{"username": "test02", "password": "pwd02"}



if __name__ == '__main__':
    pytest.main()

前后置处理

一、setup_method、teardown_method、setup_class、teardown_class

setup_method、teardown_method用于函数级别的前后置处理:

import pytest

class TestSetup:

    def setup_method(self):
        print('所有测试函数执行前先执行这个操作')

    def test_case_01(self):
        print('这个是第一个测试函数')

    def test_case_02(self):
        print('这个是第二个测试函数')

    def test_case_03(self):
        print('这个是第三个测试函数')

    def teardown_method(self):
        print('所有测试函数执行结束后先执行这个操作')

if __name__ == '__main__':
    pytest.main() # 效果是每个测试函数开始和结束时都会执行一次前后置。共执行了3次。

setup_class、teardown_class用于级别的前后置处理:

import pytest

class TestSetup:

    def setup_class(self):
        print('在测试类执行前先执行此方法')

    def test_case_01(self):
        print('这个是第一个测试函数')

    def test_case_02(self):
        print('这个是第二个测试函数')

    def test_case_03(self):
        print('这个是第三个测试函数')

    def teardown_class(self):
        print('在测试类执行结束后先执行此方法')

if __name__ == '__main__':
    pytest.main()  # 效果是每个测试类开始和结束时都会执行一次前后置。共执行了1次。

二、@pytest.fixture(常用)

可用@pytest.fixture装饰器定义fixture函数,以便在测试函数执行前后进行一些初始化和清理操作,以及共享状态和资源等
语法:

@pytest.fixture(scope="", autouse="", params="", ids="", name="")
def 函数名():
    前置操作
    yield
    后置操作

注意:

scope、autouse、params、ids、name为fixture函数可以携带的参数,可以没有。
scope:控制fixture的作用范围。可选值有:function、class、session、module,默认function
function:每个测试函数运行前后各执行一次
class:每个测试类运行前后各执行一次
module:每个 .py文件运行前后各执行一次
session:整个测试会话(所有文件)运行前后各执行一次
autouse:用于指定是否自动应用fixture而无需在测试函数中显示调用。默认为False
params:允许为fixture定义多个参数值,以便在测试函数中使用不同的参数组合进行测试
ids:为参数化的fixture提供自定义的标识,用于在测试报告中更加清晰显示参数,需要跟params参数结合起来使用
name:自定义fixture的名称

示例:

import pytest

# 定义不带参数的fixture
@pytest.fixture()
def set_and_teardown01():
    print('前置操作')
    yield
    print('后置操作')

# 定义带参数的fixture
@pytest.fixture(scope="function", autouse=False, params=['北京', '成都', '重庆'], ids=['BJ', 'CD', 'CQ'], name='setValue')
def set_and_teardown02(request):
    return request.param



class TestFixture:

    
    def test_case_01(self, set_and_teardown01):
        print('这个是第一个测试函数')


    def test_case_02(self, setValue):
        print('这个是第二个测试函数')
        print(f'获取到的值为:{setValue}')


    def test_case_03(self):
        print('这个是第三个测试函数')


if __name__ == '__main__':
    pytest.main()

在这里插入图片描述

三、@pytest.fixture、conftest.py结合(常用)

可将@pytest.fixture和conftest.py结合来实现全局的前后置应用

1、conftest.py是一个单独存放的夹具配置文件,名称是固定写法不能更改
2、可以在项目中的不同目录创建多个conftest.py,每个conftest.py文件都会对其所在的目录及其子目录下的.py文件生效

示例:
在这里插入图片描述

钩子函数

钩子函数是 Pytest 框架中的回调机制,允许用户在测试执行的特定时刻插入自定义代码。这些函数通常在 conftest.py 文件中定义,Pytest 会在特定时刻自动调用它们。

pytest_configure(config)

测试配置初始化后、收集测试项之前被调用。这个钩子函数提供了在测试运行前进行全局配置和初始化的机会。
在这里插入图片描述

pytest_collection_modifyitems(config, items)

收集测试项之后、测试执行前被调用。可用于修改、排序收集到的测试用例。
在这里插入图片描述

pytest_runtest_protocol(item, nextitem)

每个测试项执行前后调用。

pytest_fixture_setup(fixturedef, request)

每个fixture之前调用。

pytest_fixture_post_finalizer(fixturedef, request)

每个fixture的最终清理阶段调用

pytest_runtest_makereport(item, call, report)

每个测试用例运行结束后调用。常用来自定义测试报告,比如在用例失败时截图或者打印日志。

pytest_terminal_summary(terminalreporter, exitstatus, config)

所有测试执行完毕后调用。用于自定义终端输出的摘要信息。

Allure

Allure是一个轻量级、灵活、支持多语言的测试报告生成工具

使用Allure生成测试报告

步骤一:生成测试报告原始数据
在Pytest的配置文件pytest.ini中加参数选项: --alluredir=原始数据存放路径--clean-alluredir在这里插入图片描述
这样运行pytest的时候就会自动生成原始数据↓
在这里插入图片描述

步骤二:基于原始数据生成测试报告
命令行运行:allure generate 原始数据存放路径 -o 测试报告存放路径 --clean
在这里插入图片描述

步骤三:查看报告
方式一:命令行运行allure open 测试报告存放路径
在这里插入图片描述
方式二:找到测试报告存放位置,手工打开
在这里插入图片描述

效果:
在这里插入图片描述

使用Allure常用功能使报告内容更丰富

一、使用注解

@allure.feature

用来定义测试用例所属的功能特性,可以在类方法上面使用,指明模块
@allure.feature('系统管理')

@allure.story

用来定义测试用例所属的用户故事,可以在测试函数方法上使用,指明功能点
@allure.story('新增用户')

@allure.title

用来定义测试用例标题
@allure.title('新增用户(用户名和密码输入正确)')

@allure.description

用来定义测试用例的描述
@allure.description('这是系统管理模块里面的新增用户功能,输入正确的用户和密码,验证能否成功新建')

在测试报告中的对应位置如下:
在这里插入图片描述

二、使用API函数(常用)

allure.attach(body,name,attachment_type)

用来在报告中附加额外的信息,如文本、图片或文件

body:附件内容 。
name:附件标题。
attachment_type:附件类型。常用TEXT、JSON、PNG等

例:allure.attach("url、传参、token等信息", name="请求信息", attachment_type=allure.attachment_type.TEXT

在测试报告中的对应位置如下:
在这里插入图片描述

allure.dynamic.title

用来动态生成测试用例标题,通过从yaml文件获取接口名称而不需要通过@allure.title方式写死标题
在这里插入图片描述
在这里插入图片描述

配置Allure测试报告总览的环境信息

Allure主要通过读取测试报告原始数据文件夹下的名为environment.xml 的配置文件来展示环境信息。
但由于每次执行前都会清空原始数据,所以建议先在根目录下创建该文件,然后在生成测试报告原始数据后,通过代码,复制该文件到原始数据存放目录下。

environment.xml文件常见内容:

<environment>
    <parameter>
        <key>操作系统</key>
        <value>window 10</value>
    </parameter>
    <parameter>
        <key>Python version</key>
        <value>python3.10.2</value>
    </parameter>
    <parameter>
        <key>allure version</key>
        <value>3.18.0</value>
    </parameter>
    <parameter>
        <key>项目名</key>
        <value>XXX自动化测试</value>
    </parameter>
    <parameter>
        <key>作者</key>
        <value>XXX</value>
    </parameter>
</environment>

在生成原始数据后,生成测试报告前,加代码逻辑
shutil.copy('./environment.xml', '原始数据存放路径')
在这里插入图片描述
效果:
在这里插入图片描述

`Lists.partition` 是 Guava 库中提供的一种便捷方法,用于将一个大的 `List` 集合按照指定的大小划分为多个子集合。每个子集合包含原始集合中连续的一部分元素,这种划分方式并不创建新的独立集合,而是基于原始集合的视图[^1]。 ### 功能实现 该方法接受两个参数: - `List<E> list`:需要被拆分的原始列表。 - `int size`:每个子列表的最大大小。 返回值是一个 `List<List<E>>` 类型,表示由多个子列表组成的列表。每个子列表的大小最多为 `size`,最后一个子列表可能小于或等于 `size`,取决于原始列表的元素总数是否能被 `size` 整除。 ### 使用方法 以下是一个典型的使用示例: ```java import com.google.common.collect.Lists; import java.util.List; public class PartitionExample { public static void main(String[] args) { List<String> list = Lists.newArrayList("快", "敲", "代", "码", "去"); List<List<String>> partition = Lists.partition(list, 2); System.out.println(partition); // 输出:[[快, 敲], [代, 码], [去]] } } ``` 在上述代码中,原始列表 `list` 被划分为了三个子列表,每个子列表最多包含两个元素。最终输出的结果是一个包含这些子列表的列表[^1]。 ### 注意事项 - **视图特性**:通过 `Lists.partition` 得到的子列表是原始列表的一个视图。这意味着对子列表的操作会直接影响到原始列表,反之亦然。例如,如果清空了原始列表,那么所有通过 `partition` 得到的子列表也会变为空[^3]。 - **线程安全**:`Lists.partition` 并不是线程安全的。如果在多线程环境中使用,需要额外的同步措施来保证线程安全。 - **异常处理**:如果传入的 `size` 小于等于 0,`Lists.partition` 会抛出 `IllegalArgumentException` 异常。 ### 依赖引入 要使用 `Lists.partition` 方法,需要在项目中引入 Guava 库,可以通过以下 Maven 依赖进行引入: ```xml <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>31.1-jre</version> </dependency> ``` ### 示例代码 下面是一个更复杂的示例,展示了如何遍历 `Lists.partition` 生成的子列表: ```java import com.google.common.collect.Lists; import java.util.List; public class ComplexPartitionExample { public static void main(String[] args) { List<Integer> list = Lists.newArrayList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14); List<List<Integer>> partition = Lists.partition(list, 4); partition.forEach(subList -> { System.out.println("子列表:" + subList); }); } } ``` 在这个例子中,原始列表 `list` 被划分为了多个大小为 4 的子列表,并且每个子列表都被打印出来。 ### 总结 `Lists.partition` 是一种非常实用的方法,特别适合在处理大数据量时将其分割成更小的块来处理。然而,需要注意其视图特性和潜在的并发问题,以避免在操作过程中出现意外的行为[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值