一.接口概念
1.什么是接口(API)
接口:接口是为了提供一种服务
所有的接口统称为API,接口分为内部接口和外部接口外部接口:测试被测系统和外部系统之间的接口
测试内部接口:
1.内部接口提供内部系统使用:开发人员自己开发的对自身系统提供的接口)
2.内部接口提供外部系统使用:正例,各种异常场景,权限控制(只需要测试正例即可),开发系统调用外部的其他的接口
2.软件为什么需要接口
接口可以使外部来修改内部的数据
3.怎么做接口测试
一般项目的前后端进度不同,则需要提前将开发出的接口进行测试
基于安全考虑,前端的验证很容易绕过,直接请求接口,特别是:身份证信息,银行卡,金钱交易
接口的本质:就是测试接口是否能正常的交互,权限控制及异常场景
二.接口测试的流程
- 从开发那拿到Api接口(期望不要太大)/用Friider去抓包接口,熟悉接口业务,鉴权码
- 接口计划和方案思路: a.正例:输入正常的入参,查看接口是否返回成功 b.反例 I.鉴权返例: 鉴权为空,鉴权码错误,鉴权码已过期… II.参数反例: 参数为空,参数类型异常,参数长度异常 III.其他场景:错误码的覆盖,分页异常,接口调用次数限制3.使用接口测试工具postman编写用例和评审4.使用postman+Newman+jenkins实现持续集成,并且输出测试报告并且发送邮件
三.接口协议
1.webservice协议
接口地址:
http:// ....... ?wsdl
restful规则:get获取数据,post提交数据,put修改数据,delect删除数据
以前对数据的增删改查都是由四个地址进行操作.http://192.168.25.2:8080/adduser
http://192.168.25.2:8080/delectuser
http://192.168.25.2:8080/putuser
http://192.168.25.2:8080/postuser
而现在只用一个网址
http://192.168.25.2:8080/user
使用get,post,put,delect请求来进行增删改查
2.dubbo协议
接口地址
dubbo://
适用于少量数据的传输,大并发
3.http协议
超文本传输协议(HTTP):一种无状态的,以请求/应答方式运行的协议,它使用可拓展的语义和自描述消息格式.
http协议
: 接口地址
http:// 80
,端口是80,
https=http+ssl
安全传输协议,端口是443
响应:1XX响应的信息,2XX响应成功,3XX重定向,4XX客户端错误(不传值跳转网页),5XX服务器错误
须知
1丶 接口返回的数据格式
- json格式(主流)
Json是一种轻量级的数据交换格式。它基于JAVAScript的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。 在js语言中,一切都是对象,因此任何支持的类型都可以通过json来表示
json由**两种特殊类型(数组,对象)和四种基本类型(string.int,boolean、NULL值)**构成v
数组它也可以像对象那样使用键值对,但还是索引使用得多。值的类型可以是任意类型。举例:{“firstName”: “Brett”, “lastName”: “McLaughlin”}。
对象键名可以使用整数和字符串来表示。值的类型可以是任意类型。举例:people:[{“firstName”: “Brett”,“lastName”:“McLaughlin”},{“firstName”:“Jason”,“lastName”:“Hunter”}]
优点
- 简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。
- 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率
b. json由两种数据结构组成(可以相互嵌套),MAP对象,键值对,{key:value,key:value}和 数组:[value1,value2,value3]
c. 在线校验json结构的网站
http://www.bejson.com
格式: {error_code:0,msg:"提现成功",data:[]}
error_code(自定义名字):错误码,0代表成功
msg:对错误码的中文说明
data:真正返回的数据
2.html格式
<html>
<title></title>
<body>
<error_code>0</error_code>
</body>
</html>
3.xml格式
<?xml?version="1.0" encoding="utf-8">
<error_code>0</error_code>
...........
</xml>
2丶 头字段
HTTP头字段是
key-value
的形式,key和value之间用":"分隔,最后用
crlf
换行表示字段结束.
前后端分离则将传输数据类型为
Content-type: application/json
,这里的key就是
Content-kype
.value值就是
application/json
头字段规则
- 字段名不区分大小写,字段名里不允许出现空格,可以使用连字符
-
,但不能使用下划线_
(有的浏览器不能解析下划线) - 字段名后面紧跟
:
字段原则上不能重复.除非set-cookie
常用头字段
http协议中有很多头字段
请求字段:请求头中的头字段,如
Host,Referer
响应字段:响应头中的头字段,如
server,Date
通用字段:在请求头和响应头都可以出现,如
Content-type,connection
3丶请求报文
HTTP协议的请求报文由四大部分组成
- 请求行:描述请求或响应的基本信息
GET /index.html HTTP/1.1``````HTTP/1.1 200 ok
- 请求头:使用Key-value形式更详细的说明报文
Connection: keep-alive
- 空格
- 消息正文:实际传输的数据,它不一定是纯文本,可以是图片,视频,二进制数据
<html>语句</html>
请求头报文格式:method 空格 url version 换行 ``````method(请求方法):如`get/head/put/post`,表示对资源的操作URL(请求目标):通常是一个URl,标记了请求方法要操作的资源version(版本号):表示报文使用的HTTP协议版本
4丶响应报文
HTTP协议的响应报文由四大部分组成
- 响应行:描述请求或响应的基本信息
GET /index.html HTTP/1.1``````HTTP/1.1 200 ok
- 响应头:使用Key-value形式更详细的说明报文
Connection: keep-alive
- 空格
- 消息正文:实际传输的数据,它不一定是纯文本,可以是图片,视频,二进制数据
<html>语句</html>
响应行报文格式:version 空格 statuscode 空格 reason 换行``````version(版本号):表示报文使用的HTTP协议statuscode(版本状态码):三位数字,表示处理的结果
5丶HTTP的 Post编码格式
HTTP是以ASCll码来传输的,建立在TCP/IP协议上,HTTP请求/响应包括请求行,请求头,空格,消息正文
application/x-www-form-urlencoded; charset=UTF-8
而请求头的Content-Type属性告诉服务器,浏览器发送的消息正文是通过什么方式进行编码的,服务器就会得知用什么方式进行解析,而POST方法有四种编码格式
- application/x-www-form-urlencoded
post请求的编码格式若不指定,就是这个,只能传key=value值
- multipart/form-data
(键值对型数据):通常是用在客户端向服务端传送大文件数据,如:图片或者文件。也可以传key=value
- application/json
(Json 类型数据):用的超级多,也非常的方便。
- text/xml
(xml)
6丶注意
- JSON 格式支持比键值对复杂得多的结构化数据,而且还支持其他数据但是如果在这种格式下用到key—value形式,接收方就接收不到value,因为消息正文没有application/json形式的处理来源于
https://blog.csdn.net/do_finsh/article/details/72886000
7丶Tcp/IP 协议
一个HTTP请求流程
输入网址回车后,浏览器会将域名解析出来,浏览器会去查看你的浏览器是否有该域名对应的DNS缓存,有的话,可以拿到服务端的地址,没有的话,会去看你本地的host文件是否配置,没有配置则发起DNS请求来获取你对应的服务器iP地址
应用层会构造一个DNS请求报文,应用层会调用传输层的一个接口,调用UDP进行传输
网络层会将UDP请求报文添加一个IP的请求头,网络层会将其数据交给链路层
应用层:DNS,HTTP,SSH,SMTP,FTP
传输控制层:Tcp协议,UDP协议
网络层:ipv4,ipv6,arp,icmp
数据链路层:以太网,无线LAN
物理层:光纤,双绞线电缆.无线设备
TCP协议 是面向连接的****可靠的传输控制协议,TCP的三次握手和四次挥手
8,接口报文模版
将该接口链接的文档下载下来
请求部分
//请求行
POST https://event.csdn.net/logstores/csdn-pc-tracking-page-exposure/track HTTP/1.1
// 请求方式是post,请求地址是https://event.csdn.net/logstores/csdn-pc-tracking-page-exposure/track,协议HTTP/1.1
//请求头
*Host: event.csdn.net//请求的主机地址
*Connection: keep-alive(保持活跃) //连接方式
*User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.63 //客户端的用户类型
*Accept: */* //客户端接到的数据格式
*Content-Type: text/plain;charset=UTF-8// 请求内容的格式
*cookie: eyJfX3NvdXJjZV9fIjoiY3NkbiIsIl9fbG9nc19fIjpbeyJjaWQiOiIxMF8zNTUwNjExOTU2MC0xNjAyMjA2ODMyNjMwLTQyMDgyMiIsInNpZCI6IjEwXzE2NTQ5MzcwMjQ2OTIuNDEyNDY3IiwicGlkIjoicGFzc3BvcnQiLCJ1aWQiOiIiLCJkaWQiOiIxMF8zNTUwNjExOTU2MC0xNjAyMjA2ODMyNjMwLTQyMDgyMiIsImRjX3NpZCI6ImE1NDRmMzYxYmVkZmVlOGNkZWQ1MzIzY2U0NGQ1YzdkIiwicmVmIjoiaHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3oyNzY4NTU3NzkyP3R5cGU9YmxvZyIsImN1cmwiOiJodHRwczovL3Bhc3Nwb3J0LmNzZG4ubmV0L2xvZ2luP2NvZGU9YXBwbGV0cyIsImRlc3QiOiIiLCJ1dG0iOiIiLCJzcG0iOiIxMDMxLjIzNTIuMzAwMS43NzY1IiwidCI6IjE2NTQ5MzczOTciLCJlbGVUb3AiOiIiLCJjQ29va2llIjoiY19kbF91bT0tO2NfZGxfcHJpZD0xNjU0ODI2NDgwMzUxXzk3OTYxNDtjX2RsX3JpZD0xNjU0ODI3NDIxMTE1XzkwMzUwODtjX2RsX2ZyZWY9aHR0cHM6Ly9iYnMuY3Nkbi5uZXQvdG9waWNzLzYwNjg3ODg0ODtjX2RsX2ZwYWdlPS9kb3dubG9hZC9zaW5hdF80MDU3Mjg3NS84NTU5NTA3MjtjX2ZpcnN0X3JlZj1kZWZhdWx0O2NfZmlyc3RfcGFnZT1odHRwcyUzQS8vd3d3LmNzZG4ubmV0LztjX3NlZ21lbnQ9NjtjX3NpZD1hNTQ0ZjM2MWJlZGZlZThjZGVkNTMyM2NlNDRkNWM3ZDtjX3Nlc3Npb25faWQ9MTBfMTY1NDkzNzAyNDY5Mi40MTI0Njc7Y19kc2lkPTExXzE2NTQ5MzcwMjUwMTYuMDg1NzEzO2NfcGFnZV9pZD1kZWZhdWx0O2NfcHJlZj1odHRwcyUzQS8vYmxvZy5jc2RuLm5ldC9tMnNmZmcyJTNGdHlwZSUzMiUzRnNwbSUzRDEwMDAuMjExNS4zMDAxLjUzNDM7Y19yZWY9aHR0cHMlM0EvL2Jsb2cuY3Nkbi5uZXQvbjM0NWRzZmZnMiUzRnR5cGUlM0RibG9nO2NfdG9zPXJkYjF2ODsiLCJfX3RpbWVfXyI6MTY1NDkzNzM5N31dLCJfX3RhZ3NfXyI6eyJ1c2VyYWdlbnQiOiJNb3ppbGxhLzUuMCAoV2luZG93cyBOVCAxMC4wOyBXaW42NDsgeDY0KSBBcHBsZVdlYktpdC81MzcuMzYgKEtIVE1MLCBsaWtlIEdlY2tvKSBDaHJvbWUvMTAyLjAuNTAwNS42MyBTYWZhcmkvNTM3LjM2IiwicGxhdGZvcm0iOiJQQyIsImxvZ19pZCI6IjUyMTUifX0=
Referer: https://passport.csdn.net/login?code=applets //请求来源的地址
Content-Length: 1116 (发送给服务器内容的长度)
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="102", "Google Chrome";v="102"
x-log-apiversion: 0.6.0
sec-ch-ua-mobile: ?0`
user-Agent: //客户端的用户类型
Safari/537.36
x-log-bodyrawsize: 1234
sec-ch-ua-platform: "Windows"
Origin: https://passport.csdn.net
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Accept-Encoding: gzip, deflate, br(可接受的压缩方式)
Accept-Language: zh-CN,zh;q=0.9
//空格部分
//消息正文
响应部分
//响应行
HTTP/1.1 200 OK//协议 响应码 响应信息
//响应头
Server: Tengine //服务器的名称
Content-Type: application/octet-stream//响应内容的类型
Content-Length: 0
Connection: keep-alive(保持活跃)
Set-Cookie:Hm_lvt_866c9be12d4a814454792b1fd0fed295=1654732414,1654827627,1654910665,1655001979; Hm_lpvt_866c9be12d4a814454792b1fd0fed295=165502304(响应的cookie)
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: *
Date: Sat, 11 Jun 2022 08:49:57 GMT//响应的时间
x-log-time: 1654937397
x-log-requestid: 62A45735C290A28A675D2C95
Via: cache14.l2cm9-7[24,0], kunlun8.cn1497[53,0]
Timing-Allow-Origin: *
EagleId: 701ea2a616549373977903829e
//空格
//消息正文
五.postman工具
构建请求
- 请求方式
- url方式
- 请求头的确认
- 传参格式
- 发送请求
1.功能栏
请求标题栏
1. params:
请求的参数
2. Authorrization:鉴权方式
3. headers:请求头
4. 请求下的Body:入参格式
none:没有参数
form-data:文件/键值对(key- value)
x-www-form-urlencoded:键值对
raw:Json格式(Text,javascript,json,html.xxml)
binary:传二进制文件
5. pre-request-script:请求之前的脚本
6. tests:请求之后断言的代码
7. setting:设置
8. cookies:postman管理cookie信息
响应标题栏
1. Body:接口返回的数据
pretty:以json,html,xml..不同的格式查看返回的数据
Raw:以文本格式方式查看返回的数据
preview:以网页的方式查看返回的数据
2. cookie:响应的cookie信息
3. headers:响应头
4. TestResults:断言结果
5. status:状态码
6. time:响应的时间
7. szie:响应内容大小
2.问题
多种环境: 开发环境,测试环境,生成环境
接口关联: 需要手动关联
参数需要手动修改
3.postman环境/全局变量
1.概念
请求地址:https://{{ip}}/cgi-bin/token?grant_type=client_credential&appid=wx6b11b3efd1cdc290&secret=106a9c6157c4db5f6029918738f9529d
此时的ip是环境变量,已经在envirronments中设过了
而在请求地址上引用 环境变量 要用{{变量}}包起来
- 环境变量:环境变量就是全局变量
- 全局变量:全局变量是能够在任何接口都可以访问的变量
4.postman内置动态函数
postman内置动态函数,在功能pre-request Script下设置
{{$timestamp}}生成当前时间的时间戳
{{$randomint}}生成0-100之间的随机数
{{$guid}}生成速记GUID字符串
自定义动态参数
设置全局变量,在通过body引用变量传参
//手动获取时间戳
var times = Date.now();
//设置为全局变量
pm.globals.set("times", times);
使用时,{{times}}
5.解决接口关联问题
1.使用json提取器
若下一个接口需要上一个传参,在Tests断言选项输入以下代码
//使用json提取器提取access_token值//打印返回报文
console.log(responseBody);//因为JSON.parse()方法可以将字符串内容转换成对象形式,这样变量result就可以使用result.属性的方法了var result =JSON.parse(responseBody)
console.log(result.access_token);//打印var的access_token属性
pm.globals.set("access_token", result.access_token);//把access_token设置全局变量
2.使用正则表达式提取器
使用正则表达式提取器实现接口关联,match()方法用于匹配内容
在Tests断言选项输入以下代码
//返回报文主体 内容进行匹配字段是access_token, " .*? " 代替键值内容
var result = responseBody.match(new RegExp('"access_token":"(.*?)"'));//new RegExp(),新建一个正则表达式
console.log(result)//发现打印的内容有点杂
console.log(result[1]);//过滤后,发现打印的内容就是access_token值
pm.globals.set("access_token", result[1]);//再把access_token设置全局变量
6.postman的断言
断言(Tests功能)可以判断出接口是否返回成功
1.功能栏
- Get an environment variable 获得一个环境变量
- Get a golbal variable 获得一个全局变量
- get a variable 获得一个变量
- get a collection variable 获得一个集合变量
- set设置 , clear删除
- sent a request 发送一个请求
- status code : Code is 200 检查返回的状态码是否是200
- response body: Contains string 检查响应中包含指定字符串
- response body: JSON value check 检查响应中包含json的值
- response body: is equal to a string 检查响应中等于一个字符串 ,一般用于判断返回值少的字符串
- response header : Content- type header check 检查是否包含某个响应头,一般就查看有没有content_type
- response time is less than 200ms 检查请求耗时小于200ms
- status code : Successful Post request
- status code : code name has string
- response body: convert xml body to a Json 将XML的返回值转换成一个json对象
2.断言的流程及注意
断言分为 **状态断言 **和 业务断言
每一个接口测试时,都需要查看状态码和核心关键字,在功能Tests下输入相应代码块
可以通过Test Results功能查看
//状态码(一个)
pm.test("检查返回值状态码为200", function () {
pm.response.to.have.status(200);
});
//核心关键字(一般多个)
pm.test("检查响应中是否包含access_token", function () {
pm.expect(pm.response.text()).to.include("access_token");
});
pm.test("检查响应中是否包含日程", function () {
//若是动态参数断言,只能是自定义的能断言
1.pm.expect(pm.response.text()).to.include("date" +pm.globals.get("times"));
2. pm.expect(pm.response.text()).to.include("date" +globals["times"]);
3. 2. pm.expect(pm.response.text()).to.include("date" +globals.times);
});
注意: 若是动态参数断言,只能是自定义的能断言
在断言中获取自定义动态参数(全局变量)的方式:
pm.globals.get(“times”)
globals[“times”]
globals.times
3.设置全局断言
因为每个接口都需要状态码断言,可以设置一个全局的,这样每个接口断言就不要写状态码断言了[在Edit选项设置全局Tests]
Tests下输入
pm.test("判断状态码是不是200", function () {
pm.response.to.have.status(200);
});
7.执行开始
1.运行所有接口,查看信息
2. 自动判断接口的参数结果
除了使用csv文件来判断,还有json文件也可以判断,不过两者过程一样,只是文件类型不同
而这里只介绍csv文件上传的过程
a.第一步建立个csv文件,里面写入正例和反例及结果码的所有可能
grant_type,appid,secret,assert_value
client_credential,wx6b11b3efd1cdc290,106a9c6157c4db5f6029918738f9529d,access_token
,wx6b11b3efd1cdc290,106a9c6157c4db5f6029918738f9529d,40002
client_credential,,106a9c6157c4db5f6029918738f9529d,41002
client_credential,wx6b11b3efd1cdc290,,41004
b.第二步将请求的参数值都改称为其变量
c.第三步 更该断言功能Tests里面的代码
原断言代码
//因为JSON.parse()方法可以将字符串内容转换成对象形式,这样变量result就可以使用result.属性的方法
var result = JSON.parse(responseBody)
console.log(result.access_token);//打印var的access_token属性
pm.globals.set("access_token", result.access_token);//把access_token设置全局变量
pm.test("检查响应是否包含access_token值", function () {
pm.expect(pm.response.text()).to.include("access_token");
});
更改后:
//判断当返回结果中包含有access_token时,才通过json提取access_token值
if(responseBody.search("access_toke"!=-1)){ //search()查找是否包含某字段方法
//因为JSON.parse()方法可以将字符串内容转换成对象形式,这样变量result就可以使用result.属性的方法
var result = JSON.parse(responseBody)
console.log(result.access_token);//打印var的access_token属性
pm.globals.set("access_token", result.access_token);//把access_token设置全局变量
}
pm.test("检查响应是否包含access_token值", function () {
pm.expect(pm.response.text()).to.include(data.assert_value);
});
d.第四步点击
run collection
将
data.csv
上传至data功能处
点击
preview
查看数据演示
f.清空全选,选中单个接口运行
六.fiddler工具
1.获取请求链接所有的请求头 ,在postman上点击功能键BulkEdit,输入这些请求头
GET /s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=helloworld&fenlei=256&rsv_pq=9d1e79b700011649&rsv_t=7eb2SCx1PugFhQCxdR5%2FU%2BH9IL3fZIiTrcIKxN1E1pLkGfjWL5%2BgIIV2421J&rqlang=en&rsv_dl=tb&rsv_enter=1&rsv_sug3=5&rsv_sug1=4&rsv_sug7=101&rsv_sug2=0&rsv_btype=i&prefixsug=helloworld&rsp=4&inputT=6452&rsv_sug4=8213 HTTP/1.1
Host: www.baidu.com
Connection: keep-alive
Cache-Control: max-age=0
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="102", "Google Chrome";v="102"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://cn.bing.com/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: PSTM=1602206858; BIDUPSID=B2609704B49E4BB52A6234BE123C9114; __yjs_duid=1_7214023cf5165172180f7377d29c219e1621776676211; BDSFRCVID_BFESS=3tIOJexroG38rlbemRTmhjJ6QmKK0gOTDYrEOwXPsp3LGJLVgHGfEG0PtOVzGoFbI1odogKKWmOTH7kF_2uxOjjg8UtVJeC6EG0Ptf8g0M5; H_BDCLCKID_SF_BFESS=tJ-HoC0XtDD3H48k-4QEbbQH-UnLqMvAtgOZ04n-ah05b-o1-4oV0l30MM6ZtqoLW20j0h7m3UTKsq76Wh35K5tTQP6rLtb73Kc4KKJxbp74Jl3vQ45zDt4OhUJiBhbLBan7_bvIXKohJh7FM4tW3J0ZyxomtfQxtNRJ0DnjtpChbC_9D6LbejjLeU5eetjK2CntsJOOaCkBbqbOy4oWK441DN7H2Pj-aGrn-bn_WDQGDqvoD-Jc3M04K4o9-hvT-54e2p3FBUQJOh3IQft20b0g3l6x2M5aWR6y0n7jWhvRDq72y5JOQlRX5q79atTMfNTJ-qcH0KQpsIJM5-DWbT8IjHCHqTDDJbKHoCvX-5rVjJnv2tP_-P4DepKJ0URZ56bHWh0bfPoSHR5z0lOIM-IpjRQLBMPj52OnKUT-3Cov8qc25f7WDtD03xJ70-543bRTLp7CMq3osRoVDtnfhP-UynJLWh37JK3lMKoaMp78jR093JO4y4Ldj4oxJpOJ5JbMopCafD_WhCD6ejKaenFyqxc0aPR8a-o2WbCQbUcU8pcN2b5oQTJbKxvaK4rNQNO3BqFKLR6vOIJTXpOUWJDkD4RuBq3tWT-D3t5C5hnnel5jDh3MXpKhQUnl5fFDaKny0hvcQb6cShP6MUjrDRLbXU6BK5vPbNcZ0l8K3l02V-bIe-t2XjQhDGAHJ6-8tJCs3t88KJjEe-Kk-PnVeTt3ytnZKRvHa2keVPosKJ5VVxbzM-6kjl_DyP4jKMRn3N5HKl75yUJ5qKOsQU6d34-nQUj405OTbgOpXq3O3JozhJ7ghPJvyp-DXnO7t-nlXbrtXp7_2J0WStbKy4oTjxL1Db3JKjvMtgDtVJO-KKC5MK0x3q; BAIDUID=07164A9259B71EDAEF5DFF8E9C9EC64B:FG=1; BAIDUID_BFESS=F7D52997C3EB96F965A2395BE54A2EFD:FG=1; COOKIE_SESSION=9431174_0_6_6_20_10_0_1_6_4_0_3_2807994_0_0_0_1634822155_0_1650896722%7C9%230_1_1615950967%7C1; BD_UPN=12314753; ZFY=VvdyyF0oDsneCav3mPLD5ecs4M:AjqQxNgDXxxS0wETY:C; ab_sr=1.0.1_N2QxZWJmOWMzZTA3NmZlN2I4ZGZlZTY3NTAzMzA4NWE1YTBhNmMyYTVjNGM0NTQ3MTViYjZkMDM1NGQ3NGU2MWM5OWQzODlmMmY3NTQ2MDgxZmY1ODIwZGJiOWMxYTNhMzY2NTk2Y2IyMDYxNjY5NDg2MjkwNDMyNjc3MjY3ZTdhYzY3NWU0MTBkZTlhMWEyOTE1MjJmYWUyY2I0MDJkMw==; RT="z=1&dm=baidu.com&si=aymt3kf34vh&ss=l4qsj55r&sl=5&tt=9jt&bcn=https%3A%2F%2Ffclog.baidu.com%2Flog%2Fweirwood%3Ftype%3Dperf&ul=ln6&hd=lqc"; BD_HOME=1; H_PS_PSSID=36560_36625_36673_36455_31660_34813_36167_36569_36073_36267_26350_36469_22157; BA_HECTOR=008h8404a42h8l20ag1hb8fgj15; delPer=0; BD_CK_SAM=1; PSINO=3; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; channel=bing; H_PS_645EC=0255z1rq4m2iDrQCswLBaT8yeE6bJLmzQEBW9fZoXkRV5c11gyJHAY0cNrE; baikeVisitId=4dc53a4c-6f24-42de-be01-82b5b402263d
版权归原作者 .弗兰克 所有, 如有侵权,请联系我们删除。