日常问题笔记


json.dump()和json.dumps()的区别

json.dumps(date,ensure_ascii=False)是把python对象转换成json对象的一个过程,生成的是字符串。
json.dump()是把python对象转换成json对象生成一个fp的文件流,和文件相关

与json.loads()和json.load()相反

生成器yield

生成器函数是一种特殊的函数,它可以在运行中暂停并返回一个中间结果,然后在下一次调用时继续执行,并从上一次暂停的位置开始。
,类似于return语句,但不同之处在于,它可以多次返回一个中间结果,并保留函数的状态,以便下一次调用时继续执行。一般来说,使用yield的程序可以看成是一个迭代器

除了使用next()函数迭代生成器外,还可以使用for循环对生成器进行迭代

import time
def produce():
    for i in range(100):
        yield "生产了%s个包子"%i
    pass

def main():
    p = produce()
    num = 0
    for i in p:
        print(i)
        num +=1
        if num==12:
            break
    pass
def main1():
    p = produce()
    num = 0
    for i in range(12):
        print(p.__next__()) #与效果一样 print(next(p))
    pass
if __name__=='__main__':
    main()

logging用法解析

初始化 logger = logging.getLogger(“endlesscode”),getLogger()方法后面最好加上所要日志记录的模块名字,后面的日志格式中的%(name)s 对应的是这里的模块名字
设置级别 logger.setLevel(logging.DEBUG),Logging中有NOTSET < DEBUG < INFO < WARNING < ERROR < CRITICAL这几种级别,日志会记录设置级别以上的日志
Handler,常用的是StreamHandler和FileHandler,windows下你可以简单理解为一个是console和文件日志,一个打印在CMD窗口上,一个记录在一个文件上
formatter,定义了最终log信息的顺序,结构和内容,我喜欢用这样的格式 ‘[%(asctime)s] [%(levelname)s] %(message)s’, ‘%Y-%m-%d %H:%M:%S’,
%(name)s Logger的名字
%(levelname)s 文本形式的日志级别
%(message)s 用户输出的消息
%(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
%(levelno)s 数字形式的日志级别
%(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
%(filename)s 调用日志输出函数的模块的文件名
%(module)s 调用日志输出函数的模块名
%(funcName)s 调用日志输出函数的函数名
%(lineno)d 调用日志输出函数的语句所在的代码行
%(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
%(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
%(thread)d 线程ID。可能没有
%(threadName)s 线程名。可能没有
%(process)d 进程ID。可能没有

import logging
logger = logging.getLogger("simple_example")
logger.setLevel(logging.DEBUG)
# 建立一个filehandler来把日志记录在文件里,级别为debug以上
fh = logging.FileHandler("spam.log")
fh.setLevel(logging.DEBUG)
# 建立一个streamhandler来把日志打在CMD窗口上,级别为error以上
ch = logging.StreamHandler()
ch.setLevel(logging.ERROR)
# 设置日志格式
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
ch.setFormatter(formatter)
fh.setFormatter(formatter)
#将相应的handler添加在logger对象中
logger.addHandler(ch)
logger.addHandler(fh)
# 开始打日志
logger.debug("debug message")
logger.info("info message")
logger.warn("warn message")
logger.error("error message")
logger.critical("critical message")

eval()

eval()是python中功能非常强大的一个函数

  • 将字符串当成有效的表达式来求值,并返回计算结果
  • 所谓表达式就是:eval这个函数会把里面的字符串参数的引号去掉,把中间的内容当成Python的代码,eval函数会执行这段代码并且返回执行结果

用一个超简单的案例来运用一下eval函数 —— 计算器

要求:

\1. 提示用户输入一个加减乘除混合运算

\2. 返回计算结果

代码:

input_number = input("请输入一个加减乘除运算公式:")
print(eval(input_number))

在开发时千万不要使用eval直接转换input的结果

因为如果用户直接通过os这个模块来调用system方法可以执行任何的终端命令,这样细想很恐怖,家底都给暴露出来了

等价代码:

__import__('os').system('ls')

# 等价代码(上面代码等价于下面代码)

import os
os.system('终端命令')
  • __import__是python中的一个内置方法,通过这个方法导入一个os模块, import(‘os’)等价于import os
  • system方法可以接收一个字符串参数,在字符串中可以指定终端下能够执行的密令,比如上面的代码中传入的是ls,就可以查看当前目录下的情况

例如:

\1. 当前目录下所有文件都显示出来

input_number = input("请输入:")
print(eval(input_number))

上面代码执行后输入:import(‘os’).system(‘ls) ,按回车执行

面试问题:

测试用例的设计思路?

从功能角度,用户体验角度,兼容性角度,安全性角度,性能角度方面逐一展开讲述就行

session和token检验的区别

session机制:后端验证通过,代表登录成功,由服务器产生,需要返回 cookie携带sessionid返回给客户端保存,服务器也保存一份sessionid数据,第二次客户端访问时携带与服务器的对比校验

token机制:后端验证通过,代表登录成功,生成令牌(特殊的字符串),响应给客户端,不要求服务器一定保存,没有要求一定要使用Cookie携带,一般是json形式传递,token通常由客户端开发自行编码保存,第二次客户端访问时携带与服务器的对比校验

小程序,app:没有操作cookie的机制,物联网浏览器才有。主要使用token技术

谈谈你对tcp三次握手机制的理解

http请求发起之前,已经进行多次网络操作,发送业务 ,底层的传输层协议是tcp 协议。创建”虚拟“连接—三次握手即三次网络数据交互,检查网络的可靠性

synchronization同步

acknowledgement确认

三次握手:

例子:打电话场景

我:喂,听得到吗

姐:听得到,你能听到吗

我:可以听得到

…. 开始正式聊天

四次挥手:

我:我要回家吃饭了

姐:等下,饭快做好了

​ 饭好了,快回来

我:马上开飞机回来

CDN(内容分发网络)

CDN加速器

负载均衡

任播

DNS域名解析

根域名服务器

.root 常简写成.

顶级域名服务器(Top Level Domain)TLD

.com .cn .net .gov

权威域名服务器(Authoritative)

blibli qq baidu

SSH协议握手核心

对称加密,双方拥有同一把钥匙,进行加密解密

非对称加密,我方有私钥和公钥,对方只有公钥,对方使用公钥加密后发送给我,只能使用我的私钥进行解密卡查看

DH(Diffie Hellman)密钥交换

我:秘密放箱子加锁,只有我的钥匙能打开,发送给姐

姐:拿到箱子加锁,只有姐的钥匙能打开,发送给我

我:拿到箱子解锁,发送给姐

姐:拿到箱子解锁,获取秘密

CS(Client-Server)和BS(Browser-Server)

CS(Client/Server):客户端—-服务器结构。app端

BS(Browser/Server):浏览器—-服务器结构。web端

C/S 用户固定,一般只应用于局域网中,要求拥有相同的操作系统,如果对于不同操作系统还要相应开发不同的版本,并且对于计算机电脑配置要求也较高。
B/S 要求有操作系统和浏览器就行,与操作系统平台无关(可以实现跨平台),对客户端的计算机电脑配置要求较低。

CS响应速度快,安全性强,一般应用于局域网中,但是开发维护成本高;BS可以实现跨平台,客户端零维护,但是个性化能力低,响应速度较慢。所以有些单位日常办公应用BS,在实际生产中使用CS结构

def f(): pass

print(type(f()))以上代码输出结果为?

<class’NoneType’>

faker自定义数据集

from faker import Faker

faker=Faker(locale=‘zh_CN’)

faker.add_provider(CustomPrvider) #自定义数据

faker.random_element((‘男’,’女‘)) #在提供范围中选择
faker.random_int(18,40) #在指定数字中随机数字

自定义数据集造数据

from faker.providers import DynamicProvider
class MyProvider:
    def __init__(self):
        self.roomType = DynamicProvider(
            provider_name="room_type",
            elements=["豪华套房", "商务套房", "总统套房", "时尚主题房", "豪华观景房", "烂漫都市情侣房", "梦回大唐书阁"]
        )
        self.paymentStatus = DynamicProvider(
            provider_name="payment_status",
            elements=["已支付", "待支付"]
        )
        self.orderStatus = DynamicProvider(
            provider_name="order_status",
            elements=["已预约", "已入住", "已退房"]
        )

使用自定义数据集,并存入数据库中

import pymysql
from faker import Faker

from demo.MyProvider import MyProvider
def generate_data():
    myp = MyProvider()
    fake = Faker(locale='zh_CN')
    fake.add_provider(myp.paymentStatus)
    fake.add_provider(myp.roomType)
    fake.add_provider(myp.orderStatus)

    datas = [
        [
            fake.ean(prefixes=('23',), length=8),
            fake.unique.random_int(min=1000, max=5000),
            fake.room_type(),
            fake.name(),
            fake.phone_number(),
            fake.ssn(),
            fake.date(),
            fake.date(),
            fake.random_digit_not_null(),
            fake.numerify(),
            fake.payment_status(),
            fake.order_status()
        ]
        for x in range(10)
    ]
    return datas

def mysql_transmit_data(datas):
    db = pymysql.connect(
        host="127.0.0.1",
        port=3306,
        user='root',
        password="645123ab",
        db="hotel_management_system",
        charset="utf8",
        autocommit=True
    )

    cursor = db.cursor()

    for data in datas:
        sql = "insert into orders (order_id, room_number, room_title, customer_name, telephone, identification, check_in, check_out, stay_days, total_price, payment, status, create_time)" \
              "value ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%d', '%d', '%s', '%s', '%s')" % (
              data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], int(data[8]), int(data[9]),
              data[10], data[11], data[6])
        cursor.execute(sql)
        db.commit()

if __name__ == '__main__':
    order_datas = generate_data()
    print(order_datas)

案例:如果造的数据是存量数据,不是新增数据,例如,生成订单中需要商品id,商品id选自数据库中的某一条数据

from faker.providers import BaseProvider
class CustomProvider(BaseProvider):
    def goods_id(self):
        db = pymysql.connect(host="localhost",user= "root",passwd= "root", database="finance",charset='utf8')#使用cursor()方法获取操作游标
        cursor = db.cursor()
        result=cursor.execute('''
    select id from users
    ''')
        ids=cursor.fetchall()
        return ids
#------------------------------    
from faker import Faker
faker=Faker(locale=‘zh_CN’)
faker.add_provider(CustomPrvider)    #自定义数据

使用ai,造web后端接口

问:用flask框架写一个接口,用于mock返回数据,使用Python3.0
接口路径 /login
参数 用户名,密码
请求方式 get
返回数据 {“tocken”:”a”}
a代表一串8位的随机数字加字母的格式

元组,列表和字典变量前加*的作用

在列表前加*号,会将列表拆分成一个一个的独立元素,不光是列表、元组、字典,二维列表,由numpy生成的向量也可以拆分;

函数中*args和**kwargs的人应该知道,这两个形参都接收若干个参数,通常我们将其称为参数组;

  • *args:接收若干个位置参数,转换成元组tuple形式
  • **kwargs:接收若干个关键字参数,转换成字典dict形式

ps:需要注意的是位置,参数*args一定要在关键字参数**kwargs前

def add(*args):
    print(type(args))
    for item in args:
        print(item)
_list=[1,2,4,5]
add(_list)
add(*_list)

返回结果:<class ‘tuple’>

[1,2,4,5]

<class ‘tuple’>

1

2

4

5

add(_list),如果不加*,add函数将整个列表当做一个元素使用,也就是add(([1,2,4,5],))。

而add(_list),带有号的参数,此时相当于add((1, 2, 4, 5));

zip()压缩可迭代对象,*号解压可迭代对象;

最后需要注意的是:

  • 可迭代对象才可以使用*号拆分;
  • 带*号变量严格来说并不是一个变量,而更应该称为参数,它是不能赋值给其他变量的,但可以作为参数传递;

python可变长参数

可变长参数:方式有两种,一种是位置实参,另一种是关键字实参,因此形参也必须得有两种解决方法,依次来分别接收溢出的位置实参与关键字实参*

一、可变长参数之*
形参中的会将溢出的位置实参全部接收,然后存储为元组的形式,再然后把元组赋值给后的参数。需要注意的是:*后的参数名约定俗成为args。

def sum_self(*args):
    res = 0
    for num in args:
        res += num
    return res
res = sum_self(1, 2, 3, 4)
print(res)

输出

10
1
二、可变长实参之*
实参中的会将后参数的值循环取出,打散成位置实参。以后但凡碰到实参中带的,它就是位置实参,应该马上打散成位置实参去看。

def func(x, y, z, *args):
    print(x, y, z, args)

func(1, *(1, 2), 3, 4)

输出

1 1 2 (3, 4)
1
三、可变长形参之**
形参中的会将溢出的关键字实参全部接收,然后存储字典的形式,然后把字典赋值给后的参数。需要注意的是:**后的参数名约定俗成为kwargs。

def func(**kwargw):
    print(kwargw)
func(a=5)

输出

{‘a’: 5}
1
四、可变长实参之**
实参中的会将后参数的值循环取出,打散成关键字实参。以后但凡碰到实参中带的,它就是关键字实参,应该马上打散成关键字实参去看。

def func(x, y, z, **kwargs):
    print(x, y, z, kwargs)

func(1, 3, 4, **{'a': 1, 'b': 2})

输出

1 3 4 {‘a’: 1, ‘b’: 2}

python调试工具pdb的用法

一、pdb 有2种用法

pdb:python debugger

1、非侵入式方法 (不用额外修改源代码,在命令行下直接运行就能调试)

python3 -m pdb filename.py

2、侵入式方法 (需要在被调试的代码中添加以下代码然后再正常运行代码)

import pdb pdb.set_trace()

当你在命令行看到下面这个提示符时,说明已经正确打开了pdb

(Pdb)

二、pdb 基本命令

命令 解释
break 或 b 设置断点,b x 在第x行设置断点;clear x 删除断
continue 或 c 继续执行程序
list 或 l 查看当前行的代码段
step 或 s 进入函数(进入 for 循环用 next 而不是用 step)
return 或 r 执行代码直到从当前函数返回,停在return之前
next 或 n 执行下一行
up 或 u 返回到上个调用点(不是上一行)
p x 打印变量x的值
exit 或 q 中止调试,退出程序
help 帮助
retval 获取值
until x 运行直到行数大于等于x,停在x行前

在实际使用中发现,用shell脚本运行python文件时,可能无法用pdb调试,会退出。此时只能直接运行py文件来调试。

数据库导入sql文件

mysql -u username -p database_name < path_to_sql_file.sql

update方法:

详细介绍字典和集合的更新操作

使用update方法添加新的键值对

可以使用update方法来向字典中添加新的键值对,将新的键和相应的值作为参数传递给update方法即可。如果键已经存在,对应的值会被替换为新的值。

使用update方法合并字典

如果有两个字典需要合并为一个,可以使用update方法将两个字典合并。合并时,如果有相同的键存在,调用update方法的字典中对应键的值会被后面的字典中的值替代。

使用update方法删除键值对

可以使用update方法删除指定键的键值对,通过传递一个包含需要删除的键的列表来实现。

使用update方法添加新的元素

可以使用update方法向集合中添加新的元素,通过将新的元素作为参数传递给update方法。如果元素已经存在,将不会被重复添加。

使用update方法合并集合

如果有两个集合需要合并为一个,可以使用update方法将两个集合合并。合并时,会自动去除重复的元素。

使用update方法删除元素

可以使用update方法删除集合中的元素,通过传递一个包含需要删除的元素的集合来实现。

dict = {‘Name’: ‘Zara’, ‘Age’: 7}

dict2 = {‘Sex’: ‘female’ }

dict.update(dict2)

print(dict)

以上实例输出结果为:Value : {‘Age’: 7, ‘Name’: ‘Zara’, ‘Sex’: ‘female’}

os.sep.join( )和os.path.join()的用法和区别

os.sep是为了解决不同平台上文件路径分隔符差异问题,例如在windows平台上,路径分隔符为:‘\’;Linux平台上为:‘/’;MAC上是‘:’。

os.sep.join([‘hello’, ‘world’])
输出为
hello\world

os.path.join()
该函数传入的参数是多个字符串型变量,例如:

os.path.join(‘hello’, ‘world’)
输出为
hello\world

总结
os.sep.join( )和os.path.join()两个函数传入的参数类型不同,前者是列表(列表中的元素也必须是字符串型的),后者是多个字符串型变量;两个函数实现的功能基本相同

@staticmethod(静态方法)和@classmethod(类方法)使用, property(特性)

一般来说,要使用某个类的方法,需要先实例化一个对象再调用方法。
而使用@staticmethod或@classmethod,就可以不需要实例化,直接通过类名就可以实现调用
使用直接类名.方法名()来调用。

@staticmethod不需要表示自身对象的self和自身类的cls参数(这两个参数都不需要添加),就跟使用函数一样。
使用:直接类名.属性名或方法名。 # 也可以直接类名( ).属性名或方法名
@classmethod也不需要self参数,但第一个参数需要是表示自身类的cls参数。
使用:直接类名.属性名或方法名。 # 也可以直接类名( ).属性名或方法名
注:两者定义的装饰器调用方法一样,但是@classmethod装饰器定义的类方法需要传入类参数cls

小结:

定义一个类的静态方法,不需要self参数
定义一个类方法,需要cls参数

小结:在Python中类和实例都是对象,都占用了内存空间,合理的使用@staticmethod @classmethod方法,就可以不用实例化就直接使用类的方法啦

property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值

通俗的理解就是:用访问类属性的方式,直接调用类方法

设置属性值:

@property 装饰的方法是获取属性值的方法,被装饰方法的名字会被用做属性名。
@属性名.setter 装饰的方法是设置属性值的方法。
@属性名.deleter 装饰的方法是删除属性值的方法。

面向对象的封装有三种方式:
【public】
这种其实就是不封装,是对外公开的
【protected】
这种封装方式对外不公开,但对朋友(friend)或者子类(形象的说法是“儿子”,但我不知道为什么大家 不说“女儿”,就像“parent”本来是“父母”的意思,但中文都是叫“父类”)公开
【private】
这种封装对谁都不公开

python并没有在语法上把它们三个内建到自己的class机制中,在C++里一般会将所有的数据都设置为私有的,然后提供set和get方法(接口)去设置和获取,在python中通过property方法可以实现

class Foo:
    def __init__(self,val):
        self.__NAME=val #将所有的数据属性都隐藏起来

    @property
    def name(self):
        return self.__NAME #obj.name访问的是self.__NAME(这也是真实值的存放位置)

    @name.setter
    def name(self,value):
        if not isinstance(value,str):  #在设定值之前进行类型检查
            raise TypeError('%s must be str' %value)
        self.__NAME=value #通过类型检查后,将值value存放到真实的位置self.__NAME

    @name.deleter
    def name(self):
        raise TypeError('Can not delete')

f=Foo('egon')
print(f.name)
# f.name=10 #抛出异常'TypeError: 10 must be str'
del f.name #抛出异常'TypeError: Can not delete'

因为它会把类方法当作类属性进行调用,因此一般我们需要获取返回值,而且会在调用属性(方法)中做一定的处理:

比如,我们获取路径文件的名的后缀

JSONPath是一种信息抽取类库,是从JSON文档中抽取指定信息的工具,提供多种语言实现版本

from jsonpath import jsonpath
XAPTH JSONPATH 描述
/ $ 根节点
. @ 现行节点
/ or[] 取子节点
.. n/a 取父节点,jsonpath不支持
// .. 不管位詈,选择所有符合条件的节点
* * 匹配所有元素节点
@ n/a 根据属性访问,JSON不支持,因为JSON是个key-value递归结构,不需要属性访问
[] [] 迭代器标示(可以在里面做简单的迭代操作,如数组下标、根据内容选值
| [,] 支持迭代器中做多选
[] ?() 支持过滤操作
n/a () 分组,JSONPath支持

re.compile()的使用

用于编译正则表达式,生成一个 Pattern 对象,它的一般使用形式如下:

re.compile(pattern[, flag])

其中,pattern 是一个字符串形式的正则表达式,flag 是一个可选参数,表示匹配模式,比如忽略大小写,多行模式等

从compile()函数的定义中,可以看出返回的是一个匹配对象,它单独使用就没有任何意义,需要和findall(), search(), match()搭配使用。
compile()与findall()一起使用,返回一个列表

compile()与match()一起使用,可返回一个class、str、tuple。但是一定需要注意match(),从位置0开始匹配,匹配不到会返回None,返回None的时候就没有span/group属性了。匹配到就,返回一个匹配就会结束。

compile()与search()搭配使用, 返回的类型与match()差不多, 但是不同的是search(), 可以不从位置0开始匹配。但是匹配一个单词之后,匹配和match()一样,匹配就会结束。

#替换Headers变量
#1、验证请求中是否${}$,返回${}$中的内容
str1='{"Authorization":"JWT ${token}$"}'
if "${' in str1:
    print(str1)
import re
pattern =re.compile('\${(.*)}\$')
re_res = pattern.findall(str1)
print(re_res[0])  #输出:token
#2、根据内容token,查询 前置条件测试用例返回结果token =值
token ="123"
#3、根据变量结果内容,替换
res = re.sub(pattern,token,str1)
print(res) #输出:{"Authorization":"JWT 123"}

re.sub()方法中含有5个参数,下面进行一一说明(加粗的为必须参数):
(1)pattern:该参数表示正则中的模式字符串;
(2)repl:该参数表示要替换的字符串(即匹配到pattern后替换为repl),也可以是个函数;
(3)string:该参数表示要被处理(查找替换)的原始字符串;
(4)count:可选参数,表示是要替换的最大次数,而且必须是非负整数,该参数默认为0,即所有的匹配都会被替换;
(5)flags:可选参数,表示编译时用的匹配模式(如忽略大小写、多行模式等),数字形式,默认为0

re.sub(r’[^0-9A-Za-z]’, ‘‘, s) 这句话则表示匹配单个非数字和非字母,并将单个非数字和非字母替换为一个星号 。
上面 re.sub(r’[^0-9A-Za-z]+’, ‘
‘, s) 这句话则表示匹配多个连续的非数字和非字母,并将多个连续的非数字和非字母替换为一个星号

删除并重置主键id

DELETE FROM bankcard WHERE id>10;
ALTER TABLE bankcard AUTO_INCREMENT=1;

字节到字符串

在 Python 3.x 中,字节字符串和字符串是不同的数据类型,如果不进行编码或解码,则无法互换使用。

decode()是可用于将字节转换为字符串的方法。在处理以特定字符编码(如 UTF-8 或 ASCII)编码的文本数据时,通常使用它。它的工作原理只是将编码的字节字符串作为输入并返回解码的字符串。str() bytes()

decoded_string = byte_string.decode(encoding)

encode()反之亦然

嘀嘀、小米、联想-JIRA,百度-coffee、字节一Meego飞书项目

nginx启动关闭

进入该路径:cd /usr/local/nginx/sbin

3 启动nginx 命令: ./nginx 出现下面启动成功

Linux怎么启动及关闭nginx命令

4 查看nginx 的状态 ps -ef | grep nginx 出现master 则启动成功

Linux怎么启动及关闭nginx命令

5 关闭nginx 命令 kill -9 8725(进程号 上面的) 则关闭nginx

\6. 停止 nginx 命令: ./nginx -s stop

7.重启nginx命令:./nginx -s reload

多参数数据驱动

@ddt
class BasicTestCase(unittest.TestCase):
@data(read_dict()) # 加表示逐个读取列表元素,Python中可变参数,*表示逐个读取列表元素,列表为[[‘张三’, ‘18’], [‘李四’, ‘19’], [‘王五’, ‘20’]]
@unpack # 通过unpack解包,逐个传参,缺少这句会将[‘张三’, ‘18’]传给name,从而导致age为空
def test(self, name, age): # 设置两个接收参数的形参
print(‘姓名为:’, name, ‘年龄为:’, age)

isinstance()与type()的区别

type()不会认为子类是一种父类类型,不考虑继承关系

isinstance()会认为子类是一种父类类型,考虑继承关系

如果要判断两个类型是否相同推荐使用isinstance()

class A:
pass

class B(A):
pass

isinstance(A(),A) # True
type(A()) == A # True
isinstance(B(),A) # True
type(B()) == A # False

urlencode和urldecode

urllib.parse.unquote()函数
urllib.parse.unquote() 函数属于urllib库中的parse模块,该模块提供了处理URL的方法。unquote()函数的作用是将URL中的特殊字符解码为原始字符
该函数的定义如下:
urllib.parse.unquote(string,encoding=’utf-8’,errors=’replace’)
string :要解码的URL字符串
encoding : 解码时使用的字符编码,默认为UTF-8
errors: 解码时遇到错误的处理方式,默认为替换错误字符

from urllib.parse import unquote
#要解码的URL
url ='' 
# 解码URL
decoded_ur1 = unquote(ur1)
#打印解码后的URL
print(decoded_ur1)
#获取参数字典
params = parse_qs(decoded ur1)
#打印参数值
print(params[q][0]) 
# 输出:中文
print(params[category][0]) 
# 输出: python

在这个示例中,我们首先使用 unquote() 函数对URL进行解码,然后使用 parse_gs() 函数将解码后的URL转换为参数字典,最后可以通过参数名来获取对应的值。

from urllib.parse import unquote
#要解码的文件名
filename ="%E4%B8%AD%E6%96%87%20file.txt
#解码文件名
decoded_filename = unquote(filename)
#打印解码后的文件名
# 输出:中文 file.txt
print(decoded_filename)

urlencode()
传入参数类型:字典
功能:将存入的字典参数编码为URL查询字符串,即转换成以key1=value1&key2=value2的形式
导入:from urllib.parse import urlencode
Ps:url单个字符串编码用quote()函数
例子1:url标准符号,数字字母

from urllib.parse import urlencode
base_url = "https://m.weibo.cn/api/container/getIndex?"
params1 = {"value": "english", "page": 1}
url1 = base_url + urlencode(params1)
print(url1)

结果:

https://m.weibo.cn/api/container/getIndex?value=english&page=1
例子2:汉字,/,&,=,URL编码转化为%xx的形式

from urllib.parse import urlencode
params2 = {
    'name': "王二",
    'extra': "/",
    'special': '&',
    'equal': '='}
base_url = "https://m.weibo.cn/api/container/getIndex?"
url2 = base_url + urlencode(params2,encodeing-'utf-8')
print(urlencode(params2))
print(url2)

运行结果

name=%E7%8E%8B%E4%BA%8C&extra=%2F&special=%26&equal=%3D

https://m.weibo.cn/api/container/getIndex?name=name=%E7%8E%8B%E4%BA%8C&extra=%2F&special=%26&equal=%3D
quote()
传入参数类型:字符串
功能:将单个字符串编码转化为 %xx 的形式
导入:from urllib.parse import quote
Ps:url多个字符串编码用urlenocde()函数
例子:特殊符号:汉字、&、=等特殊符号编码为%xx
from urllib.parse import quote
“””特殊符号:汉字、&、=等特殊符号编码为%xx “””
KEYWORD = ‘苹果’
url = ‘https://s.taobao.com/search?q=' + quote(KEYWORD)
print(url)

运行结果:https://s.taobao.com/search?q=%E8%8B%B9%E6%9E%9C

KEYWORD = ‘=’
url = ‘https://s.taobao.com/search?q=' + quote(KEYWORD)
print(url)

运行结果:https://s.taobao.com/search?q=%3D
例子3:以上两例子默认utf8编码,如果用gb2312编码,则需指定
from urllib.parse import quote
text = quote(“药品互联网信息服务”, encoding=”gb2312”)
print(text)

运行结果:%D2%A9%C6%B7%BB%A5%C1%AA%CD%F8%D0%C5%CF%A2%B7%FE%CE%F1


文章作者: 读序
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 读序 !
  目录