1、在python中遍历字典的时候不能对字典本身做涉及键的操作
2、%和format的区别
c = (220,220)
s1 = "坐标为%s"%(c,)
s2 = "坐标为{}".format(c)
print(s1,s2)
输出结果:
坐标为(220, 220) 坐标为(220, 220)
python3.6版本format多了个f-strings
name = "李优秀"
age = "20"
s1 = "{}is{}".format(name,age)
s2 = f"{name}is{age}"
print(s1,s2)
# format通过对象属性
class Person():
def __init__(self,name,age):
self.name = name
self.age = age
def __str__(self):
return "{self.name}is{self.age}".format(self = self)
p = Person("李优秀",18)
print(p)
输出结果:
李优秀is18
3、可变对象不能做函数参数
def foo(arg,li = []):
li.append(arg)
return li
list1 = foo(21)
list2 = foo(21,[1,])
list3 = foo(28)
print(list1,list2,list3)
输出结果:
[21, 28] [1, 21] [21, 28]
4、打乱列表内容
import random
list1 = [1,2,3,4,5]
random.shuffle(list1)
print(list1)
5、装饰器
1、装饰函数带参数和返回值
def outer(f):
def inner(*arg,**karg):
print("xxxx")
ret = f(*arg,**karg)
print("xxxxx")
return ret
return inner
@outer
def foo(name):
print(name+":你好")
return 5
a = foo("long")
print(a)
2、带参数的装饰器
3、多个装饰器装饰同一个函数的时候执行顺序
4、带返回值的装饰器
5、装饰类的装饰器
https://q1mi.github.io/PythonBlog/post/advanced_decorator/
6、不成功剥皮函数
list1 = [11,[22,3],[4,],[55,66],8,[9,[7,[12,[34,[26]]]]]]
def f(x):
ret = []
for b in x:
if isinstance(b,list):
for a in f(b):
ret.append(a)
else:
ret.append(b)
return ret
ret1 = f(list1)
print(ret1)
7、时间间隔
import datetime
now_time = datetime.datetime.now()
day_7_later = datetime.timedelta(days=7)
ret = now_time+day_7_later
print(now_time,ret)
输出结果:
2019-03-01 20:33:35.350343 2019-03-08 20:33:35.350343
8、Django请求生命周期
1.浏览器发送请求
2.执行遵循wsgi协议的模块(本质是socket服务端)进行初次封装
3.然后将初次封装的数据交给Django进行再次封装(封装request),例如session,和csrf_token
4.经过中间件process_request
5.进行路由匹配
6.经过process_view中间件
7.到视图函数,可能会涉及到ORM访问数据库,与模板渲染
8.经过process_response中间件
9.到wsgi进行数据封装返回到浏览器
9、什么是WSGI(web服务网关接口)
web服务网关接口
实现该协议的模块:
- wsgiref
- werkzurg
- uwsgi
10、什么是接口:
一种就是:URL
一种就是做约束用(一般在c#和java中存在)
11、restful api规范:
1.根据method不同,进行不同操作(GET,POST,PUT,DELETE,PATCH)
2.面向资源编程:http://xxxxxxxx/api/v1/名词
3.体现是API:http://xxxxxxxx/api/.....
4.体现版本:http://xxxxxxxx/api/v1/.....
5.https:
6.在响应时添加状态码(200,300,400,500)
7.条件:https://xxxxxxxxxxxxxxxxxxxx?page = 1&size = 10
8.返回值
https://www.luffycity.com/api/v2/salary
GET: 所有列表
{
code: 10000,
data: [
{'id':1,'title':'高亮'},
{'id':1,'title':'龙泰'},
{'id':1,'title':'小东北'},
]
}
POST: 返回新增的数据
{'id':1,'title':'高亮'}
https://www.luffycity.com/api/v2/salary/1/
GET: 获取单条数据
{'id':1,'title':'高亮'}
PUT:更新
{'id':1,'title':'高亮'}
PATCH: 局部更新
{'id':1,'title':'高亮'}
DELETE:删除
9.返回错误信息{
code:1001,
erro:'xxxx错误'
}
10.Hyermedia API
ret = {
code:1000,
data:{
id:'',
name:'',
depart_id:'http://xxxxxxxx/api/v1/depart/8/' //返回路由查询路径
}
}
12、django rest framework
django rest framework的作用?
快速搭建基于restful规范的接口。
框架组件有哪些?(10)
- 版本
- 权限
- 写一个类并注册到权限类,在类的的has_permission方法中编写认证逻辑。
- True
- False
当用户登录时候获取当前用户所有权限并放入session,(获取带参数URL:request.get_full_path() 获取不带参数URL:request.path)
然后再次访问其他页面,获取当前url并在session中进行匹配。
如果没有匹配成功,则在中间件返回“无权访问”
- 认证
登录认证
- 写一个类并注册到认证类,在类的的authticate方法中编写认证逻辑。
- 认证成功(user,auth)
- raise AuthticateFaild(....)
- None
- 访问频率限制(列表insert方法)
- 写一个类并注册到频率类,在类的的 allow_request/wait 方法中编写认证逻辑。
allow_request
- True
- False 如果返回False,那么就要执行wait
匿名用户:以IP地址为键,以时间戳为值(无法控制,因为用户可以换代理IP)
登录用户:以用户名为键,以时间戳为值(登录用户:如果有很多账号,也无法限制)
默认将访问记录放在缓存中:redis/memcached
- 路由
- 可以通过as_view传参数,根据请求方式不同执行相应的方法
- 可以在url中设置一个结尾,类似于: .json
- 视图
- 帮助开发者提供了一些类,并在类中提供了多个方法以供我们使用。
面试题:你的写的类都继承过哪些类?
class View(object):
class APIView(View):
class GenericAPIView(views.APIView):
class GenericViewSet(ViewSetMixin, generics.GenericAPIView)
class ModelViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet):
- 序列化:(用到了类中__new__方法,单个对象和多个对象)
- 对queryset序列化以及对请求数据格式校验
ser =XX(queryset,many=True) # ListSerializer对象
ser =XX(obj, many=False) # XX对象
from rest_framework.serializers import Serializer
class XX(Serializer):
pass
ser =XX(queryset,many=True) # ListSerializer对象
ser =XX(obj, many=False) # XX对象
- 列表生成式
- 根据字符串的形式,自动导入模块并使用反射找到模块中的类【参考:s9day108】。
- 解析器
- 根据ContentType请求头,选择不同解析器对 请求体中的数据进行解析。
POST /index/ http1.1.\r\nhost:11.11.11.11\r\nContent-Type:url-formendo.... \r\n\r\nuser=alex&age=123
POST /index/ http1.1.\r\nhost:11.11.11.11\r\nContent-Type:application/json\r\n\r\n{....}
- 分页
- 对从数据库中获取到的数据进行分页处理: SQL -> limit offset
- 根据页码:http://www.luffycity.com/api/v1/student/?page=1&size=10
- 根据索引:http://www.luffycity.com/api/v1/student/?offset=60&limit=10
- 根据加密:http://www.luffycity.com/api/v1/student/?page=erd8
页码越大速度越慢,为什么以及如何解决?
原因:页码越大向后需要扫描的行数越多,因为每次都是从0开始扫描。
解决:
- 限制显示的页数
- 记录当前页数据ID最大值和最小值,再次分页时,根据ID现行筛选,然后再分页。
- 渲染器
- 根据URL中传入的后缀,决定在数据如何渲染到到页面上。
13、vue 发ajax请求时的this作用域
14、视图FBV和CBV
FBV和CBV本质是一样的
基于函数的视图叫做FBV,基于类的视图叫做CBV
在python中使用CBV的优点:
1.提高了代码的复用性,可以使用面向对象的技术,比如Mixin(多继承)
2.可以用不同的函数针对不同的HTTP方法处理,而不是通过很多if判断,提高代码可读性
15、跨域
- 为什么会有跨域?
因为浏览器的同源策略导致,只有相同IP之间才能进行数据交互(开放:src 禁止:ajax)
- 如何跨域?
- 绕过浏览器同源策略就可以跨域。
1. jsonp(只能发get请求,并且要求双方得规定好)
动态创建script标签
同源策略会阻止ajax请求;不阻止具有src属性的标签
<script src='xxxx'></script>
2. cors
设置响应头,
简单请求
和复杂请求
1.请求以 GET, HEAD 或者 POST 以外的方法发起请求。
或者,使用 POST,但请求数据为 application/x-www-form-urlencoded,
multipart/form-data 或者 text/plain 以外的数据类型。
比如说,用 POST 发送数据类型为 application/xml 或者 text/xml 的 XML 数据的请求。
2.使用自定义请求头(比如添加诸如 X-PINGOTHER)
options请求做预检,加content_type,
class CORSMiddleware(MiddlewareMixin):
def process_response(self,request,response):
# 允许所有域名来获取我的数据
response['Access-Control-Allow-Origin'] = "*"
if request.method == "OPTIONS":
# 允许你携带
response['Access-Control-Allow-Headers'] = "Content-Type"
# 允许你发送DELETE,PUT
response['Access-Control-Allow-Methods'] = "DELETE,PUT,POST"
return response
16、 你理解的Http协议?
1.
- 建立在tcp之上
- 一次请求一次响应然后断开连接(无状态、短连接)
- 请求和响应
发送:请求头\r\n\r\n请求体
host:www.luffy.com\r\ncontent-type:application/json\r\n\r\n请求体
响应:响应头\r\n\r\n响应体
2.
Http协议就是一个传输数据格式。
我原来学习django框架,从socket服务端开始学起。
自己创造了一个socket服务器来充当:网站。
浏览器当socket客户端。
更清楚的明白到底http协议是什么?
- 请求头 请求头
- 响应头 响应头
一次请求响应后,断开连接。
3.常见请求头:Accept-Encoding,User-Agent(浏览器的身份标识字符串),Referer(表示浏览器所访问的前一个页面),Content-Type( 请求体的MIME类型 (用于POST和PUT请求中)),Accept,Cookie,Host
4. 常见的请求体?
Form表单提交:
POST /index http1.1\r\nhost:www.luffycity.com...\r\n\r\nusername=alex&password=123&...
Ajax请求:
POST /index http1.1\r\nhost:www.luffycity.com...\r\n\r\nusername=alex&password=123&...
POST /index http1.1\r\nhost:www.luffycity.com...\r\n\r\n{“username”:"alex","password":123}
补充:django中获取请求体
- request.POST
- request.body
18、ORM方法
class Depart(models.Model): 5个部门
title = models.CharField(...)
class User(models.Model): 10个用户
name = models.CharField(...)
email = models.CharField(...)
dp = models.FK(Depart)
result = models.User.objects.all().only('id','name','email')
models.User.objects.all().values( 'id','name')
models.User.objects.all().values_list( 'id','name')
seleted_related,主动做连表查询(1次链表)result = User.objects.all().seleted_related('dp')
prefetch_related:
select * from user ;
通过python代码获取:dp_id = [1,2]
select * from depart where id in dp_id
2次单表查询result = User.objects.all().prefetch_related('dp')
数据量比较大,不会使用FK,允许出现数据冗余。
19、setting中根据字符串的形式,自动导入模块并使用
利用a,b = xxx.split('.',maxlenth = 1)或a,b = xxx.split('.',1)
import importlib
m = importlib.import_module(a)
cls = getattr(m,b)
obj = cls()
20、 django中间件是什么?
django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法。
在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件
中间件中一共有四个方法:
process_request
process_view
process_exception
process_response
21、 使用中间件做过什么?
- 内置
- csrf
- session
- 自定义
- 登录认证
- 权限
- cors
- 登录认证,不再需要在每个函数中添加装饰器
- 权限,当用户登录时候获取当前用户所有权限并放入session,然后再次访问其他页面,获取当前url并在session中进行匹配。如果没有匹配成功,则在中间件返回“无权访问”
- 跨域,
- jsonp,动态创建一个script标签。
- cors,设置响应头
应用:本地开始前后端分离的时使用。
22、 原生Ajax:XMLHttpRequest对象:
原生Ajax:XMLHttpRequest对象:
var xhr = new XMLHttpRequest()
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
// 已经接收到全部响应数据,执行以下操作
var data = xhr.responseText;
console.log(data);
}
};
xhr.open('POST', "/test/", true);
// 设置请求头
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');
// 发送请求
xhr.send('n1=1;n2=2;');
23、 如果代码出现bug,你们是如何解决?
创建一个bug分支,然后进行bug处理,处理完毕后,合并到master分支。
删除bug分支
回到dev分支继续开发。
24、 git rebase的作用?
保持提交记录的整洁。
25、 redis和mysql
mysql是一个软件,帮助开发者对一台机器的硬盘进行操作。
redis是一个软件,帮助开发者对一台机器的内存进行操作。
缓存,优先去redis中获取,如果没有就是数据库。
26 redis是什么?
用于操作内存的软件。
- 可以做持久化:
- AOF:
- RDB:
- 相当于是大字典
- 单进程单线程
27、 F和Q
F,更新数据库字段
Q, 构造复杂条件
28、 git协同开发
a. 怎么通过git做得协同开发?
b. 是否做代码review?
c. 开发过程中出现bug如何做?
d. git rebase作用?
e. 给别人开源代码贡献力量。
f. 使用的github、gitlab ?
PS:隐藏明感信息
29、Django和flask的区别
30、 Flask提供的功能
配置文件
app.config.from_object("类的路径")
app.config["xx"] = xxx
应用:
Django中间件
rest framework全局配置
31、 session的原理
1、当请求到来时从用户的cookie中把值取出(浏览器)
2、在视图中解密,反序列化,以字典的方式放到内存中,
3、请求结束把session序列化加密
32、 Flask中g的生命周期?
33、 g和session一样吗?
34、 g和全局变量一样吗?
35、 谈谈你对django和flask的认识?
36、 上下文管理
37、 什么是响应式布局?
38、给出m长的0或1,然后最多补n个0,求最长连续1后或前补完0。连续最长1
n = int(input(">>"))
m = int(input(">>"))
lis = [int(input(">>")) for i in range(n)]
lis.append(0)
cnt_list = []
flag = 0
start = 0
for i in range(len(lis)):
if lis[i] == 1:
if flag == 0:
flag = 1
start = i
else:
end = i
if flag == 1:
flag = 0
cnt_list.append([start, end])
start = end = 0
ever_max_len = []
for k in range(len(cnt_list)-1):
if k < len(cnt_list) - 1:
num = cnt_list[k+1][0]-cnt_list[k][1]
print(num)
if num <= m:
ever_max_len.append(cnt_list[k][1]-cnt_list[k][0]+cnt_list[k+1][1]-cnt_list[k+1][0]+num)
else:
ever_max_len.append(max(cnt_list[k][1]-cnt_list[k][0]+m, cnt_list[k+1][1]-cnt_list[k+1][0]+m))
print(max(ever_max_len))
39、threading.local
应用:
- Flask上下文管理中的Local类更高级
- DBUtils线程池的模式一:为每个线程创建一个连接。
- SQLAlchemy
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session
from models import Student,Course,Student2Course
engine = create_engine(
"mysql+pymysql://root:123456@127.0.0.1:3306/s9day120?charset=utf8",
max_overflow=0, # 超过连接池大小外最多创建的连接
pool_size=5, # 连接池大小
pool_timeout=30, # 池中没有线程最多等待的时间,否则报错
pool_recycle=-1 # 多久之后对线程池中的线程进行一次连接的回收(重置)
)
SessionFactory = sessionmaker(bind=engine)
# 为每个线程创建一个连接
session = scoped_session(SessionFactory)
def task():
ret = session.query(Student).all()
# 将连接交还给连接池
session.remove()
from threading import Thread
for i in range(20):
t = Thread(target=task)
t.start()
40、上下文管理
41、 为什么要创建两个Local?或两个LocalStack?
- 编写离线脚本时,需要配置文件,而配置文件存放在app中。
- 编写离线脚本时,不需要请求相关的数据。
所以,将app和请求相关的数据分开:
- 应用上下文(app,g)
- 请求上下文(request,session)
42、 Flask程序有几个Local和LocalStack?
请求LocalStack,帮助开发对stack对应列表操作
请求Local = {
1212:{
stack:[ctx,]
}
}
应用LocalStack,帮助开发对stack对应列表操作
应用Local = {
1212:{
stack:[app_ctx,]
}
}
43、web运行时多个app离线脚本(web runtime):
请求Local = {
1111:{
stack:[ctx1,]
},
1112:{
stack:[ctx2,]
},
1113:{
stack:[ctx3,]
}
}
应用Local = {
1111:{
stack:[app_ctx1,]
}
1112:{
stack:[app_ctx2,]
},
1113:{
stack:[app_ctx3,]
}
}
多app离线脚本:
from flask import current_app
app1 = create_app()
app_ctx1 = app1.app_context() # app_ctx = app/g
app2 = create_app()
app_ctx2 = app2.app_context() # app_ctx = app/g
with app_ctx1: # __enter__,通过LocalStack放入Local中
print(current_app) # app1
with app_ctx2:
print(current_app) # app2
print(current_app) # app1
44、如何对对象做约束
Java:
- 接口,约子类中必须包含某个方法(约束)。
Interface IMessage:
def func1(self):
pass
def func2(self):
pass
class Msg(IMessage):
def func1(self):
print('func1')
def func2(self):
print('func1')
- 抽象方法/抽象类,约子类中必须包含某个方法。(约束+继承)
class abstract IMessage:
def abstract func1(self):
pass
def abstract func2(self):
pass
def func3(self):
print('asdfasdf')
class Msg(IMessage):
def func1(self):
print('func1')
def func2(self):
print('func1')
Python:
- 接口(无)
- 抽象方法/抽象类(有,ABC)
- 类继承+异常
class IMessage(object):
def func1(self):
raise NotImplementedError('子类没有实现func1方法')
class Msg(IMessage):
def func1(self):
print('123')
obj = Msg()
obj.func1()
有什么用?用于告知其他人以后继承时,需要实现那个方法,如:
class BaseAuthentication(object):
"""
All authentication classes should extend BaseAuthentication.
"""
def authenticate(self, request):
"""
Authenticate the request and return a two-tuple of (user, token).
"""
raise NotImplementedError(".authenticate() must be overridden.")
def authenticate_header(self, request):
"""
Return a string to be used as the value of the `WWW-Authenticate`
header in a `401 Unauthenticated` response, or `None` if the
authentication scheme should return `403 Permission Denied` responses.
"""
pass
以后自己开发时,如何使用?
需求:
class BaseMessage(object):
def send(self):
raise NotImplementedError('必须实现send方法')
class Msg(BaseMessage):
def send(self):
print('发送短信')
class Wechat(BaseMessage):
def send(self):
print('发送微信')
class Email(BaseMessage):
def send(self):
print('发送邮件')
class DingDing(BaseMessage):
def send(self):
print('发送钉钉提醒')
45、 metaclass作用:指定类由那个type创建?(type泛指继承type的所有类)
46、 数据库如何加锁?
终端1:
begin;
select * from tb for update;
commit;
终端2:
begin;
select * from tb for update;
commit;
47、什么时候需要加锁?
- 计数
- 应用场景:
- 商品数量
48、视图、触发器、函数、存储过程是什么?
49、 执行计划
explain select * from tb;
id
查询顺序标识
如:mysql> explain select * from (select nid,name from tb1 where nid < 10) as B;
+----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 9 | NULL |
| 2 | DERIVED | tb1 | range | PRIMARY | PRIMARY | 8 | NULL | 9 | Using where |
+----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
特别的:如果使用union连接气值可能为null
select_type
查询类型
SIMPLE 简单查询
PRIMARY 最外层查询
SUBQUERY 映射为子查询
DERIVED 子查询
UNION 联合
UNION RESULT 使用联合的结果
...
table
正在访问的表名
type
查询时的访问方式,性能:all < index < range < index_merge < ref_or_null < ref < eq_ref < system/const
ALL 全表扫描,对于数据表从头到尾找一遍
select * from tb1;
特别的:如果有limit限制,则找到之后就不在继续向下扫描
select * from tb1 where email = 'seven@live.com'
select * from tb1 where email = 'seven@live.com' limit 1;
虽然上述两个语句都会进行全表扫描,第二句使用了limit,则找到一个后就不再继续扫描。
INDEX 全索引扫描,对索引从头到尾找一遍
select nid from tb1;
RANGE 对索引列进行范围查找
select * from tb1 where name < 'alex';
PS:
between and
in
> >= < <= 操作
注意:!= 和 > 符号
INDEX_MERGE 合并索引,使用多个单列索引搜索
select * from tb1 where name = 'alex' or nid in (11,22,33);
REF 根据索引查找一个或多个值
select * from tb1 where name = 'seven';
EQ_REF 连接时使用primary key 或 unique类型
select tb2.nid,tb1.name from tb2 left join tb1 on tb2.nid = tb1.nid;
CONST 常量
表最多有一个匹配行,因为仅有一行,在这行的列值可被优化器剩余部分认为是常数,const表很快,因为它们只读取一次。
select nid from tb1 where nid = 2 ;
SYSTEM 系统
表仅有一行(=系统表)。这是const联接类型的一个特例。
select * from (select nid from tb1 where nid = 1) as A;
possible_keys
可能使用的索引
key
真实使用的
key_len
MySQL中使用索引字节长度
rows
mysql估计为了找到所需的行而要读取的行数 ------ 只是预估值
extra
该列包含MySQL解决查询的详细信息
“Using index”
此值表示mysql将使用覆盖索引,以避免访问表。不要把覆盖索引和index访问类型弄混了。
“Using where”
这意味着mysql服务器将在存储引擎检索行后再进行过滤,许多where条件里涉及索引中的列,当(并且如果)它读取索引时,就能被存储引擎检验,因此不是所有带where子句的查询都会显示“Using where”。有时“Using where”的出现就是一个暗示:查询可受益于不同的索引。
“Using temporary”
这意味着mysql在对查询结果排序时会使用一个临时表。
“Using filesort”
这意味着mysql会对结果使用一个外部索引排序,而不是按索引次序从表里读取行。mysql有两种文件排序算法,这两种排序方式都可以在内存或者磁盘上完成,explain不会告诉你mysql将使用哪一种文件排序,也不会告诉你排序会在内存里还是磁盘上完成。
“Range checked for each record(index map: N)”
这个意味着没有好用的索引,新的索引将在联接的每一行上重新估算,N是显示在possible_keys列中索引的位图,并且是冗余的。
50、慢日志?
- 查询时间久
- 未命中索引
修改配置:
slow_query_log = ON 是否开启慢日志记录
long_query_time = 2 时间限制,超过此时间,则记录
slow_query_log_file = /usr/slow.log 日志文件
log_queries_not_using_indexes = ON 为使用索引的搜索是否记录
51、无法命中的情况?
52、数据库优化方案:
- 不使用select *
- 短索引
- 使用链表代替子查询
- 固定长度在前面
- 分库分表
- 组合索引 > 索引合并
- 内存代替链表
- choices
- limit
- 读写分离(主从)
- 分页
- 缓存
53、谈谈你对面向对象的认识。
54、Local的作用?
类似于threading.local的作用,但是是他的升级版(greentlet.get_current())
__storage__ = {
1231: {},
1231: {}
}
55、LocalStack作用?
将Local中__storage__的值维护成一下结构:
__storage__ = {
1231: {stack:[],},
1231: {stack:[],}
}
56、web知识
- 请求和响应:
- 请求:
"GET /index http1.1\r\nhost:c1.com\r\nContent-type:asdf\r\nUser-Agent:aa\r\nreferer:www.xx.com;cookie:k1=v1;k2=v2;\r\n\r\n"
- 响应:
"HTTP/1.1 200 \r\nSet-Cookies:k1=v1;k2=v2,Connection:Keep-Alive\r\nContent-Encoding:gzip\r\n\r\n<html>asdfasdfasdfasdfdf</html>"
- 携带常见请求头
- user-agent
- referer
- host
- content-type
- cookie
- csrf
- 原因1:
- 需要浏览器+爬虫先访问登录页面,获取token,然后再携带token去访问。
- 原因2:
- 两个tab打开的同事,其中一个tab诱导你对另外一个tab提交非法数据。
57、 OSI 7层模型
58、 三次握手、四次挥手?
59、 TCP和UDP区别?
60、 路由器和交换机的区别?
61、 ARP协议?
62、 DNS解析?
63、 Http和Https?
64、 进程、线程、协程区别?
65、 GIL锁
66、 进程如何进程共享?
67、twisted是什么以及和requests的区别?
requests是一个Python实现的可以伪造浏览器发送Http请求的模块。
- 封装socket发送请求
twisted是基于事件循环的异步非阻塞网络框架。
- 封装socket发送请求
- 单线程完成并发请求
PS: 三个相关词
- 非阻塞:不等待
- 异步:回调
- 事件循环:一直循环去检查状态。
面试题
最新推荐文章于 2024-01-20 20:06:43 发布