背景
本文为转载170道题目。用做复习记录,如有错误,请大家指点。
原文以及答案:
引言
最近在刷面试题,所以需要看大量的 Python 相关的面试题,从大量的题目中总结了很多的知识,同时也对一些题目进行拓展了,但是在看了网上的大部分面试题不是很满意,一个是有些部分还是 Python2 的代码,另一个就是回答的很简单,有些关键的题目,也没有点出为什么,最重要的是还有一些复制粘贴根本就跑不通,这种相信大家深有体会吧,这样就导致我们可能需要去找其他人发的类似的教程。难受啊,所以我决定针对市面上大多的 Python 题目做一个分析,同时也希望大家尽可能的做到举一反三,而不是局限于题目本身。大概就这样吧,有你看过的题目也有你没看到过的。
通过本场 Chat,你将获得如下知识点:
- 掌握 Python 的基础语法
- 语法常见的 Python 应用场景
- 掌握 Python 闭包的使用以及装饰器的使用
- 生成器和迭代器的使用
- 常见的设计模式的使用
- 深浅拷贝的区别
- 线程、进程、协程的使用
- 了解 Python 中的元编程和反射
- 常考的数据结构和算法
- 爬虫相关知识,网络编程基本知识等
所有题目
语言特性
1.谈谈对 Python 和其他语言的区别
Python 是一门语法简洁优美,功能强大无比,应用领域非常广泛,具有强大完备的第三方库,他是一门强类型的可移植、可扩展,可嵌入的解释型编程语言,属于动态语言。
语言特点:简洁、优雅,省略了各种大括号和分号,还有一些关键字,类型说明;
语言类型:解释型语言,运行的时候是一行一行的解释,并运行,所以调试代码很方便,开发效率很高;
第三方库:python是开源的,并且python的定位时任由其发展,应用领域很多比如Web,运维,自动化测试,爬虫,数据分析,人工智能。Python具有非常完备的第三方库;
Python和Java相比:
Python比Java要简单.Python是弱类型语言,而Java是强类型语言。
Python和C相比:
对于使用:Python的类库齐全并且使用简洁,很少代码实现的功能用C可能要很复杂。
对于速度:Python的运行速度相较于C,绝对是很慢了.Python和CPython解释器都是C语言编写。
强/弱类型是指类型检查的严格程度的。语言有无类型,弱类型和强类型三种。无类型的不检查,甚至不区分指令和数据。弱类型的检查很弱,仅能严格的区分指令和数据。强类型的则严格的在编译期进行检查。
2.简述解释型和编译型编程语言
解释型:就是边解释边执行;
编译性:编译后再执行
类型 | 原理 | 优点 | 缺点 |
编译型语言 | 通过专门的编译器,将所有源代码一次性转换成特定平台(Windows、Linux 等)执行的机器码(以可执行文件的形式存在)。 | 编译一次后,脱离了编译器也可以运行,并且运行效率高。 | 可移植性差,不够灵活。 |
解释型语言 | 由专门的解释器,根据需要将部分源代码临时转换成特定平台的机器码。 | 跨平台性好,通过不同的解释器,将相同的源代码解释成不同平台下的机器码。 | 一边执行一边转换,效率很低。 |
转载自http://c.biancheng.net/view/4136.html
3.Python 的解释器种类以及相关特点?
Python解释器主要有以下几个:
1、CPython
官方版本的解释器:CPython。这个解释器是用C语言开发的,所以叫CPython。在命令行下运行python就是启动CPython解释器。CPython是使用最广且被的Python解释器。
2、IPython
IPython是基于CPython之上的一个交互式解释器,也就是说,IPython只是在交互方式上有所增强,但是执行Python代码的功能和CPython是完全一样的。CPython用>>>作为提示符,而IPython用In [序号]:作为提示符。
3、PyPy
PyPy是另一个Python解释器,它的目标是执行速度。PyPy采用JIT技术,对Python代码进行动态编译(注意不是解释),所以可以显著提高Python代码的执行速度。
4、Jython
Jython是运行在Java平台上的Python解释器,可以直接把Python代码编译成Java字节码执行。
5、IronPython
IronPython和Jython类似,只不过IronPython是运行在微软.Net平台上的Python解释器,可以直接把Python代码编译成.Net的字节码。
4.说说你知道的Python3 和 Python2 之间的区别?
python2的默认编码是ASCII,python3的默认编码是Unicode
python2中range返回的是列表,xrange返回的是可迭代对象,而Python3中range返回的是可迭代对象
python2中整数分为int 和 lang,python3中统一归为int
python2不等于可以用!= 或者<>表示,在python3中只能用!=
python2 使用print语句,python3中使用print()函数
python2 输入用row_input() ,python3用input()
详情见
5.Python3 和 Python2 中 int 和 long 区别?
6.xrange 和 range 的区别?
python2中,range返回的是列表,xrange返回的是可迭代对象
>>>xrange(8)
xrange(8)
>>> list(xrange(8))
[0, 1, 2, 3, 4, 5, 6, 7]
>>> range(8) # range 使用
[0, 1, 2, 3, 4, 5, 6, 7]
python3中
>>> range(8) # range 使用
range(0, 8)
>>> list(range(0,8))
[0, 1, 2, 3, 4, 5, 6, 7]
总结,python3弃用了xrange,但python3的range功能和python2的xrange一样,都是一个生成器。
编码规范
7.什么是 PEP8?
pep8 通常会听别人提到,但是具体的指什么内容呢,简单介绍下。
《Python Enhancement Proposal #8》 (8号python增强提案)又叫PEP8,他针对的python代码格式而编订的风格指南。
空白
- 使用space来表示缩进,而不要用tab
- 和语法相关的每一层缩进用4个空格来表示
- 每行的字符数不应超过79
- 文件中函数与类之间应该用两个空行隔开
- 在同一个类中,各方法之间应用一个空行隔开
- 在使用下表来获取列表元素、调用函数或给关键字参数赋值的时候,不要在两旁添加空格
- 为变量赋值的时候,赋值符号的左侧和右侧应该各自写上一个空格,而且只要一个就好
命名
- 函数、变量及属性应该用小写字母来拼写,各单词之间以下划线相连
- 类与异常,应该以每个单词首字母均大写的格式来命名
- 类中的实例方法,应该把首个参数命名为self,以表示该对象的自身
- 类方法的首个参数,应该命名为cls,以表示该类自身
表达式和语句
- 采用内联式的否定词,而不要把否定词放在整个表达式的前面,例如,应该写if a is not b 而不是if not a is b
- 不要通过检测长度的办法(如 if len(somelist) == 0)来判断somelist是否为空值,而是应该采用 if not somelist 这种写法来判断,他会假定:空值将自动评估为False
- 不要编写单行的if语句,for循环,while循环及except复合语句,而是应该把这些语句分成多行来书写,以示清晰
- import语句应在总放在文件开头
- 文件中的哪些import语句应该按照顺序划分为三个部分,分别表示标准库模块,第三方模块以及自用模块
要点
- 当编写Python代码时,总应该遵循PEP8风格指南
- 与广大Python开发者采用同一套代码风格,可以使项目更利于多人协作
- 采用一直的风格来编写代码,可以领后续的修改工作变得更为容易
以上是摘自PEP8的部分,有兴趣可以查看http://www.python.org/dev/peps/pep-0008
原文转自:
8.了解 Python 之禅么?
- 在编辑器中查看。新建 .py 文件,文件名随便取,键入 import this,并运行代码,会有控制台输出 “Python之禅”的内容。
- 在解释器或命令窗口中查看。直接输入 import this并回车,需要注意的是命令窗口中得先输入python并回车,待看到 >>> 提示符时,才可输入 import this。回车后,下方会直接输出 “Python之禅”的内容。
9.了解 dosctring 么?
10.了解类型注解么?
11.例举你知道 Python 对象的命名规范,例如方法或者类等
12.Python 中的注释有几种?
答:总体来说分为两种,单行注释和多行注释。
- 单行注释在行首是
#
。 - 多行注释可以使用三个单引号或三个双引号,包括要注释的内容。
13.如何优雅的给一个函数加注释?
14.如何给变量加注释?
15.Python 代码缩进中是否支持 Tab 键和空格混用。
答:不允许 tab 键和空格键混用,一般推荐使用 4 个空格替代 tab 键。
16.是否可以在一句 import 中导入多个库?
答:可以是可以,但是不推荐。因为一次导入多个模块可读性不是很好,所以一行导入一个模块会比较好。同样的尽量少用 from modulename import *,因为判断某个函数或者属性的来源有些困难,不方便调试,可读性也降低了。
17.在给 Py 文件命名的时候需要注意什么?
答:给文件命名的时候不要和标准库库的一些模块重复,比如 abc。 另外要名字要有意义,不建议数字开头或者中文命名
18.例举几个规范 Python 代码风格的工具
数据类型
字符串
19.列举 Python 中的基本数据类型?
python中6个常用数据类型:整型,字符串,元组,集合,列表,字典
20.如何区别可变数据类型和不可变数据类型
不可变:整型、字符串、元组
可变:集合、列表、字典
字典的键值必须是不可变类型。
从对象内存地址方向来说
- 可变数据类型:在内存地址不变的情况下,值可改变(列表和字典是可变类型,但是字典中的 key 值必须是不可变类型)
- 不可变数据类型:内存改变,值也跟着改变。(数字,字符串,布尔类型,都是不可变类型)可以通过 id() 方法进行内存地址的检测。
21.将"hello world"转换为首字母大写"Hello World"
str = "hello world"
str.title()
string.title()将每个单词首字母大写。
22.如何检测字符串中只含有数字?
Python isalnum() 方法检测字符串是否由字母和数字组成。
Python isdigit() 方法检测字符串是否只由数字组成。
Python isalpha() 方法检测字符串是否只由字母或文字组成。
23.将字符串"ilovechina"进行反转
给定一个字符串,然后将其翻转,逆序输出。
实例 1:使用字符串切片
str='Runoob'
print(str[::-1])
执行以上代码输出结果为:
boonuR
知识点:
利用索引进行切片操作时,可包含三个参数:
如对列表来说即:list[start_index: stop_index: step]。
- 起始位置 : start_index (空时默认为 0)。
- 终点位置: stop_index (空时默认为列表长度) 需要注意起点与终点索引的位置关系。
- 步长: step (空时默认为 1,不能为 0)。
实例 2:使用 reversed()
str='Runoob'
print(''.join(reversed(str)))
执行以上代码输出结果为:
boonuR
join的返回通过指定字符连接序列中元素后生成的新字符串。
#!/usr/bin/python3
s1 = "-"
s2 = ""
seq = ("r", "u", "n", "o", "o", "b") # 字符串序列
print (s1.join( seq ))
print (s2.join( seq ))
输出结果:
r-u-n-o-o-b
runoob
24.Python 中的字符串格式化方式你知道哪些?
1.使用"%"操作符
>>> print("我叫%s,今年%d岁了" % ("小李", 20))
我叫小李,今年20岁了
2.使用字符串对象的format()方法
1、正常使用
>>> print("我叫{},今年{}岁了".format("小李", 20))
我叫小李,今年20岁了
2、还可以通过在括号里填写数字,修改格式化的顺序
>>> print("我叫{1},今年{0}岁了".format("小李", 20))
我叫20,今年小李岁了
转载自
25.有一个字符串开头和末尾都有空格,比如“ adabdw ”,要求写一个函数把这个字符串的前后空格都去掉。
str = " adabdw "
方法1:str.replace(' ','')
方法2:str.strip()
知识点:
1、Python replace() 方法把字符串中的 old(旧字符串) 替换成 new(新字符串),如果指定第三个参数max,则替换不超过 max 次。关于 string 的 replace 方法,需要注意 replace 不会改变原 string 的内容。
str.replace(old, new[, max])
参数:
- old -- 将被替换的子字符串。
- new -- 新字符串,用于替换old子字符串。
- max -- 可选字符串, 替换不超过 max 次
2、
Python strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。
注意:该方法只能删除开头或是结尾的字符,不能删除中间部分的字符。需要注意 strip会改变原 string 的内容。
26.获取字符串”123456“最后的两个字符。
str = '123456'
str[-2::]
27.一个编码为 GBK 的字符串 S,要将其转成 UTF-8 编码的字符串,应如何操作?
S.decode('gbk').encode('utf8')
需要先进行解码,然后再进行编码
encode和decode分别指编码和解码
encode()方法为str对象的方法,用于将字符串转换成二进制数据(即bytes),也称编码。encode()不会修改原字符串。
decode()方法为byte对象的方法,用于将二进制数据转换为字符串,即将使用encode()方法转换的结果再转换成字符串,也称为解码。
28.s="info:xiaoZhang 33 shandong",用正则切分字符串输出['info', 'xiaoZhang', '33', 'shandong']
import re
re.split(r'[ :| ]',s)
知识点:
正则表达式的() [] {}有不同的意思。
() 是为了提取匹配的字符串。表达式中有几个()就有几个相应的匹配字符串。
(\s*)表示连续空格的字符串。
[]是定义匹配的字符范围。比如 [a-zA-Z0-9] 表示相应位置的字符要匹配英文字符和数字。[\s*]表示空格或者*号。
{}一般用来表示匹配的长度,比如 \s{3} 表示匹配三个空格,\s[1,3]表示匹配一到三个空格。
(0-9) 匹配 '0-9′ 本身。 [0-9]* 匹配数字(注意后面有 *,可以为空)[0-9]+ 匹配数字(注意后面有 +,不可以为空){1-9} 写法错误。
[0-9]{0,9} 表示长度为 0 到 9 的数字字符串。
正则表达式在线生成工具:
http://tools.jb51.net/regex/create_reg
27.怎样将字符串转换为小写?
string.lower()
28.单引号、双引号、三引号的区别?
当你用单引号' '定义字符串的时候,它就会认为你字符串里面的双引号" "是普通字符,从而不需要转义。反之当你用双引号定义字符串的时候,就会认为你字符串里面的单引号是普通字符无需转义。
python三引号允许一个字符串跨多行,字符串中可以包含换行符、制表符以及其他特殊字符;三引号可以表示为注释。
转载自
29.a = "你好 中国 ",去除多余空格只留一个空格。
s = "你好 中国 " print(" ".join(s.split()))
列表
30.已知 AList = [1,2,3,1,2],对 AList 列表元素去重,写出具体过程。
list(set(AList))
31.如何实现 "1,2,3" 变成 ["1","2","3"]
str = "1,2,3"
str.split(',')
32.给定两个 list,A 和 B,找出相同元素和不同元素
a = list(range(4))
b = list(range(5))
c = set(a)&set(b)
d = set(a)^set(b)
集合最常用的操作就是交集、并集、差集、对称差集运算。进行交集运算时使用‘&’符号,进行并集时使用‘|’符号,进行差集时使用‘-’符号,进行对称差集运算时使用‘^’符号。
图中分别为:并集、交集、差集、对称差集。
33.[[1,2],[3,4],[5,6]]一行代码展开该列表,得出[1,2,3,4,5,6]
a = [[1,2],[3,4],[5,6]]
final = [y for x in a for y in x]
print(final)
34.合并列表[1,5,7,9]和[2,2,6,8]
a = [1,5,7,9]
b = [2,2,6,8]
方法1:c = a+b
方法2:a.extend(b)
list.extend()该方法没有返回值,但会在已存在的列表中添加新的列表内容。
35.如何打乱一个列表的元素?
import random
a = [1,5,7,9]
random.shuffle(a)
shuffle() 方法将序列的所有元素随机排序
字典
36.字典操作中 del 和 pop 有什么区别
答:
del 可以根据索引(元素所在位置)来删除的,没有返回值。 pop 可以根据索引弹出一个值,然后可以接收它的返回值。
a = {'a':1,'b':2,'c':3,'d':4}
a.pop('b') #代表从a中删除key='b'的元素,返回值是与key对应的value;Python 字典 pop() 方法删除字典给定键 key 及对应的值,返回值为被删除的值。key 值必须给出。 否则,返回 default 值。
a.clear() #代表清空a中的所有元素,原字典变成空字典
del a #代表删除字典a这个变量,删除整个字典
a.popitem() # popitem() 方法返回并删除字典中的最后一对键和值。
37.按照字典的内的年龄排序
d1 = [
{'name':'alice', 'age':38},
{'name':'bob', 'age':18},
{'name':'Carl', 'age':28},
]
答:
d1.sort(key = lambda x: x['age'],reverse = False)
参考:在Python中,字典按值排序
38.请合并下面两个字典 a = {"A":1,"B":2},b = {"C":3,"D":4}
答:
# 需求 3: 把字典的 key 和 value 值调换;
d = {'a':'1', 'b':'2'}
print({v:k for k,v in d.items()})
39.如何使用生成式的方式生成一个字典,写一段功能代码。
40.如何把元组("a","b")和元组(1,2),变为字典{"a":1,"b":2}
答:
a = ("a","b")
b = (1,2)
dict(zip(a,b))
知识点:zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
综合
41.Python 常用的数据结构的类型及其特性?
A:{1:0,2:0,3:0}
B:{"a":0, "b":0, "c":0}
C: {(1,2):0, (2,3):0}
D: {[1,2]:0, [2,3]:0}
42.如何将元组("A","B")和元组(1,2),合并成字典{"A":1,"B":2}
a = ("A","B")
b = (1,2)
dict(zip(a,b))
43.Python 里面如何实现 tuple 和 list 的转换?
Python 中的类型转换,一般通过类型强转即可完成 tuple 转 list 是 list() 方法 list 转 tuple 使用 tuple() 方法
44.我们知道对于列表可以使用切片操作进行部分元素的选择,那么如何对生成器类型的对象实现相同的功能呢?
45.请将[i for i in range(3)]改成生成器
46.a="hello"和 b="你好"编码成 bytes 类型
47.下面的代码输出结果是什么?
a = (1,2,3,[4,5,6,7],8)
a[2] = 2
48.下面的代码输出的结果是什么?
a = (1,2,3,[4,5,6,7],8)
a[5] = 2
操作类题目
49.Python 交换两个变量的值
50.在读文件操作的时候会使用 read、readline 或者 readlines,简述它们各自的左右
51.json 序列化时,可以处理的数据类型有哪些?如何定制支持 datetime 类型?
52.json 序列化时,默认遇到中文会转换成 unicode,如果想要保留中文怎么办?
53.有两个磁盘文件 A 和 B,各存放一行字母,要求把这两个文件中的信息合并(按字母顺序排列),输出到一个新文件 C 中。
54.如果当前的日期为 20190530,要求写一个函数输出 N 天后的日期,(比如 N 为 2,则输出 20190601)。
55.写一个函数,接收整数参数 n,返回一个函数,函数的功能是把函数的参数和 n 相乘并把结果返回。
56.下面代码会存在什么问题,如何改进?
def strappend(num):
str='first'
for i in range(num):
str+=str(i)
return str
57.一行代码输出 1-100 之间的所有偶数。
答:list(range(2,101,2))
58.with 语句的作用,写一段代码?
59.python 字典和 json 字符串相互转化方法
60.请写一个 Python 逻辑,计算一个文件中的大写字母数量
高级特效
70.函数装饰器有什么作用?请列举说明?
71.Python 垃圾回收机制?
72.魔法函数 __call__怎么使用?
73.如何判断一个对象是函数还是方法?
74.@classmethod 和@staticmethod 用法和区别
75.Python 中的接口如何实现?
76.Python 中的反射了解么?
77.metaclass 作用?以及应用场景?
78.hasattr() getattr() setattr()的用法
79.请列举你知道的 Python 的魔法方法及用途。
80.如何知道一个 Python 对象的类型?
81.Python 的传参是传值还是传址?
82.Python 中的元类(metaclass)使用举例
83.简述 any()和 all()方法
84.filter 方法求出列表所有奇数并构造新列表,a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
85.什么是猴子补丁?
86.在 Python 中是如何管理内存的?
87.当退出 Python 时是否释放所有内存分配?
正则表达式
88.使用正则表达式匹配出<html><h1>www.baidu.com</html>中的地址
a="张明 98 分",用 re.sub,将 98 替换为 100
答:
pattern = 'h1>(.*?)<'
str = '<html><h1>www.baidu.com</html>
results = re.search(pattern,str)
results.group(1)
pattern = '([0-9]{2})'
re.sub(pattern,'100',a)
89.正则表达式匹配中(.*)和(.*?)匹配区别?
(.*)表示贪心算法,表示尽可能多的配对
(.*?)表示非贪心算法,表示要精确的配对
.*具有贪婪的性质,首先匹配到不能匹配为止,根据后面的正则表达式,会进行回溯。.*?则相反,一个匹配以后,就往下进行,所以不会进行回溯,具有最小匹配的性质。
表达式 .* 就是单个字符匹配任意次,即贪婪匹配。
表达式 .*? 是满足条件的情况只匹配一次,即最小匹配.
90.写一段匹配邮箱的正则表达式
答:
\w 匹配英文字母或数字或下划线或汉字。(以前把汉字忽略掉了)
其他内容
91.解释一下 python 中 pass 语句的作用?
答:
pass表示空语句,不做任何事情,一般起到占位作用
for x in range(1,10):
if x % 2 == 0:
print(x,end = ' ')
else:
pass
print()函数里面是默认换行的,具体换行参数是end="\n"。所以,如果我们把参数end="\n"换成end=' '相当于取消了换行符
92.简述你对 input()函数的理解
答:input()用于接收用户的键盘输入
var = input('提示文字:')
在Python 3.x 中,无论输入的是字符串还是数字,都将被当作字符串进行读取。如果想要接收数值,则需要对接收到的字符串进行类型转换。
在Python2.x中,input()函数接收内容时,数值直接输入即可,并且接收后的内容作为数字类型;而如果要输入字符串类型的的内容,需要将对应的字符串使用引号括起来,否则会报错。
93.python 中的 is 和==
94.Python 中的作用域
95.三元运算写法和应用场景?
96.了解 enumerate 么?
97.列举 5 个 Python 中的标准模块
98.如何在函数中设置一个全局变量
99.pathlib 的用法举例
100.Python 中的异常处理,写一个简单的应用场景
101.Python 中递归的最大次数,那如何突破呢?
102.什么是面向对象的 mro
103.isinstance 作用以及应用场景?
104.什么是断言?应用场景?
105.lambda 表达式格式以及应用场景?
106.新式类和旧式类的区别
107.dir()是干什么用的?
108.一个包里有三个模块,demo1.py, demo2.py, demo3.py,但使用 from tools import *导入模块时,如何保证只有 demo1、demo3 被导入了。
109.列举 5 个 Python 中的异常类型以及其含义
110.copy 和 deepcopy 的区别是什么?
111.代码中经常遇到的*args, **kwargs 含义及用法。
112.Python 中会有函数或成员变量包含单下划线前缀和结尾,和双下划线前缀结尾,区别是什么?
113.w、a+、wb 文件写入模式的区别
114.举例 sort 和 sorted 的区别
115.什么是负索引?
116.pprint 模块是干什么的?
117.解释一下 Python 中的赋值运算符
118.解释一下 Python 中的逻辑运算符
119.讲讲 Python 中的位运算符
120.在 Python 中如何使用多进制数字?
121.怎样声明多个变量并赋值?
算法和数据结构
122.已知:
AList = [1,2,3]
BSet = {1,2,3}
(1) 从 AList 和 BSet 中 查找 4,最坏时间复杂度那个大?
(2) 从 AList 和 BSet 中 插入 4,最坏时间复杂度那个大?
123.用 Python 实现一个二分查找的函数
124.python 单例模式的实现方法
125.使用 Python 实现一个斐波那契数列
126.找出列表中的重复数字
127.找出列表中的单个数字
128.写一个冒泡排序
129.写一个快速排序
130.写一个拓扑排序
131.python 实现一个二进制计算
132.有一组“+”和“-”符号,要求将“+”排到左边,“-”排到右边,写出具体的实现方法。
133.单链表反转
134.交叉链表求交点
135.用队列实现栈
136.找出数据流的中位数
137.二叉搜索树中第 K 小的元素
爬虫相关
138.在 requests 模块中,requests.content 和 requests.text 什么区别
答: requests.content 获取的是字节,requests.text 获取的是文本内容。
.text是现成的字符串,.content还要编码,但是.text不是所有时候显示都正常,这是就需要用.content进行手动编码。
通过例子即可理解:
通过.text
通过.content
返回的为bytes,通过decode对bytes进行解码—>str
原文链接:
139.简要写一下 lxml 模块的使用方法框架
140.说一说 scrapy 的工作流程
首先还是先看张图
已 www.baidu.com 为例: 首先需要知道的事各个模块之间调用都是通过引擎进行的。
- spider 把百度需要下载的第一个 url:www.baidu.com 交给引擎。
- 引擎把 url 交给调度器排序入队处理。
- 调度器把处理好的 request 返回给引擎。
- 通过引擎调动下载器,按照下载中间件的设置下载这个 request。
- 下载器下载完毕结果返回给引擎(如果失败:不好意思,这个 request 下载失败,然后引擎告诉调度器,这个 request 下载失败了,你记录一下,我们待会儿再下载。)
- 引擎调度 spider,把按照 Spider 中间件处理过了的请求,交给 spider 处理。
- spider 把处理好的 url 和 item 传给引擎。
- 引擎根据不同的类型调度不同的模块,调度 Item Pipeline 处理 item。
- 把 url 交给调度器。 然后从第 4 步开始循环,直到获取到你需要的信息,
注意!只有当调度器中不存在任何 request 了,整个程序才会停止。
141.scrapy 的去重原理
142.scrapy 中间件有几种类,你用过哪些中间件
答: scrapy 的中间件理论上有三种(Schduler Middleware,Spider Middleware,Downloader Middleware)。在应用上一般有以下两种
- 爬虫中间件 Spider Middleware:主要功能是在爬虫运行过程中进行一些处理。
- 下载器中间件 Downloader Middleware:这个中间件可以实现修改 User-Agent 等 headers 信息,处理重定向,设置代理,失败重试,设置 cookies 等功能。
143.你写爬虫的时候都遇到过什么?反爬虫措施,你是怎么解决的?
144.为什么会用到代理?
答:如果使用同一个 ip 去不断的访问的网站的话,会很容易被封 ip,严重的永久封禁,导致当前的访问不了该网站。不只是通过程序,通过浏览器也无法访问。
145.代理失效了怎么处理?
答:一般通过大家代理池来实现代理切换等操作,来实现时时使用新的代理 ip,来避免代理失效的问题。
146.列出你知道 header 的内容以及信息
147.说一说打开浏览器访问 www.baidu.com 获取到结果,整个流程。
148.爬取速度过快出现了验证码怎么处理
149.scrapy 和 scrapy-redis 有什么区别?为什么选择 redis 数据库?
150.分布式爬虫主要解决什么问题
151.写爬虫是用多进程好?还是多线程好? 为什么?
152.解析网页的解析器使用最多的是哪几个
153.需要登录的网页,如何解决同时限制 ip,cookie,session(其中有一些是动态生成的)在不使用动态爬取的情况下?
154.验证码的解决(简单的:对图像做处理后可以得到的,困难的:验证码是点击,拖动等动态进行的?)
155.使用最多的数据库(mysql,mongodb,redis 等),对他的理解?
网络编程
156.TCP 和 UDP 的区别?
•TCP是面向连接的、可靠的,但是它是以牺牲通信量来实现的,也就是会降低传输速率。如果传输的数据量不多,对传输速度要求不高,但是对可靠性要求较高的时候,则用TCP。
•UDP是无连接的、不可靠的,但是它可以实现高速传输。如果传输的数据量大,要求传输速度快,但对可靠性要求不高,或者已知网络是可靠的情况下,可以用UDP。
157.简要介绍三次握手和四次挥手
TCP的三次握手
过程描述
①首先 Client 端发送连接请求报文
②Server 段接受连接后回复 ACK 报文,并为这次连接分配资源。
③Client 端接收到 ACK 报文后也向 Server 段发生 ACK 报文,并分配资源,这样 TCP 连接就建立了。
那你是否思考过为什么需要第三次通信 ?
1、在第一次通信过程中,A向B发送信息之后,B收到信息后可以确认自己的收信能力和A的发信能力没有问题。
2、在第二次通信中,B向A发送信息之后,A可以确认自己的发信能力和B的收信能力没有问题,但是B不知道自己的发信能力到底如何,所以就需要第三次通信。
3、在第三次通信中,A向B发送信息之后,B就可以确认自己的发信能力没有问题。
4、 小结:3次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。
四次挥手 第一次挥手:当主机 A 发送数据完毕后,发送 FIN 结束报文段。 第二次挥手:主机 B 收到 FIN 报文段后,向主机 A 发送一个确认序号 ACK(为了防止在这段时间内,对方重传 FIN 报文段)。 第三次挥手:主机 B 准备关闭连接,向主机 A 发送一个 FIN 结束报文段。 第四次挥手:主机 A 收到 FIN 结束报文段后,进入 TIME_WAIT 状态。并向主机 B 发送一个 ACK 表示连接彻底释放。
除此之外经常看的问题还有,为什么 2、3 次挥手不能合在一次挥手中? 那是因为此时 A 虽然不再发送数据了,但是还可以接收数据,B 可能还有数据要发送给 A,所以两次挥手不能合并为一次。
158.什么是粘包? socket 中造成粘包的原因是什么? 哪些情况会发生粘包现象?
并发
159.举例说明 conccurent.future 的中线程池的用法
160.说一说多线程,多进程和协程的区别。
161.简述 GIL
162.进程之间如何通信
163.IO 多路复用的作用?
164.select、poll、epoll 模型的区别?
165.什么是并发和并行?
167.解释什么是异步非阻塞?
168.threading.local 的作用?
Git 面试题
169.说说你知道的 git 命令
答:git init:该命令将创建一个名为 .git 的子目录,这个子目录含有你初始化的 Git 仓库中所有的必须文件,这些文件是 Git 仓库的骨干 git clone url:将服务器代码下载到本地 git pull:将服务器的代码拉到本地进行同步,如果本地有修改会产生冲突。 git push:提交本地修改的代码到服务器 git checkout -b branch:创建并切换分支 git status:查看修改状态 git add 文件名:提交到暂存区 git commit -m "提交内容":输入提交的注释内容 git log:查看提交的日志情况
170.git 如何查看某次提交修改的内容x