Python爬虫工程师面试核心考点与基础实战指南

周予安
周予安
发布时间:2026-10-13| 6人浏览过
原创

本文系统梳理Python爬虫工程师面试高频考点,涵盖Python语言特性、6种内置数据类型辨析、CPython运行机制及GIL锁原理。深入解析深/浅拷贝、is与==区别、文件IO操作及一行代码实现技巧,并对比多进程与多线程的稳定性差异,助力求职者掌握核心基础知识。

Python爬虫面试知识体系概览

首先整理一份完整的爬虫工程师面试知识体系框架。

Python基础核心考点

一、 Python 基本功

1、简述Python 的特点和优点

Python 属于开源的解释型语言,相较于 Java 和 C++ 等编译型语言,Python 具备动态类型特性,语法简洁且灵活性极高。

2、Python 有哪些数据类型?

Python 内置了 6 种核心数据类型。其中不可变类型包括 Number(数值)、String(字符串)和 Tuple(元组);可变类型包括 List(列表)、Dict(字典)和 Set(集合)。

3、列表和元组的区别

列表和元组均支持迭代操作,如循环遍历和切片处理。主要区别在于元组(tuple)一旦创建便不可修改,这一不可变性使得元组可以作为字典(Dict)的键使用,而列表则不能。

CPython运行机制与性能优化

4、Python 是如何运行的

CPython 执行流程如下:

Python 程序执行时,首先将 .py 源代码编译为字节码(byte code),编译后的字节码对象存储在内存中的 PyCodeObject 里,随后由 Python 虚拟机(PVM)逐行解释执行。程序运行结束后,解释器会将 PyCodeObject 持久化保存为 .pyc 文件。再次运行时,Python 会优先查找同名 .pyc 文件,通过比对时间戳等修改记录,判断是否直接加载 .pyc 或重新编译生成新的 .pyc 文件。

5、Python 运行速度慢的原因

a). Python 属于弱类型语言,解释器在执行变量赋值、类型转换、比较运算及引用传递时,必须动态检查每个变量的数据类型,增加了运行时开销。

b). 虽然 Python 编译器启动速度优于 Java,但每次脚本执行通常都需要重新初始化编译环境。

c). Python 的对象模型导致内存访问效率较低。例如 Numpy 中指针直接指向缓存区数据值,而 Python 中指针指向缓存对象,再通过缓存对象间接指向实际数据,增加了寻址层级。

6、面对 Python 慢的问题,有什么解决办法

a). 更换解释器,例如使用 PyPy(基于 JIT 编译)或 Jython(Java 平台实现)。

b). 对于性能要求高且静态类型变量较多的场景,可考虑使用 CPython 配合 C 扩展或 Cython 优化。

c). 针对 IO 密集型应用,利用 Python 提供的 asyncio 模块实现异步非阻塞 IO,提升并发处理能力。

7、描述一下全局解释器锁 GIL

在 CPython 中,每个线程执行前必须获取全局解释器锁(GIL),确保同一时刻仅有一个线程执行字节码,即单线程独占 CPU 时间片,因此多线程并非真正的并行执行。但在执行 IO 操作时,GIL 会被释放,允许其他线程运行(这也是异步 IO 可行的基础)。若需利用多核 CPU 进行计算密集型任务,应采用多进程而非多线程。

8、深拷贝 浅拷贝

深拷贝(Deep Copy)会递归复制对象及其包含的所有子对象,生成完全独立的新对象;浅拷贝(Shallow Copy)仅复制对象本身,子对象仍共享原对象的引用。因此,修改深拷贝后的对象不会影响原对象,而修改浅拷贝后的可变子对象会影响原对象。

9、is 和 == 的区别

is 用于比较两个对象的身份标识(object identity),即判断它们是否指向内存中的同一地址;== 用于比较两个对象的值是否相等(equality)。

is 检查内存地址是否一致,== 检查值是否相等。为优化性能,Python 对小整数和短字符串采用驻留机制(interning),即相同值的对象可能共享内存地址。例如:

a = 8
b = 8
a is b

文件IO与一行代码实战技巧

10、文件读写

简述文件读取时 read 、readline、readlines 的区别和作用

三者的区别不仅在于读取内容的范围,还在于返回的数据类型不同。

read() 方法读取整个文件内容,将其作为单个字符串返回,类型为 str。

readline() 方法每次读取文件中的一行内容,包含换行符,返回类型为 str。

readlines() 方法读取文件所有内容,按行分割并存入列表,返回类型为 list。

11、请用一行代码实现

请分别使用匿名函数和推导式这两种方式将 [0, 1, 2, 3, 4, 5] 中的元素求乘积,并打印输出元组。


print(tuple(map(lambda x: x * x, [0, 1, 2, 3, 4, 5])))
print(tuple(i*i for i in [0, 1, 2, 3, 4, 5]))

12、请用一行代码实现

用 reduce 计算 n 的阶乘(n!=1×2×3×...×n)


print(reduce(lambda x, y: x*y, range(1, n)))

13、请用一行代码实现

筛选并打印输出 100 以内能被 3 整除的数的集合


print(set(filter(lambda n: n % 3 == 0, range(1, 100))))

14、请用一行代码实现


text = 'Obj{"Name": "pic", "data": [{"name": "async", "number": 9, "price": "$3500"}, {"name": "Wade", "number": 3, "price": "$5500"}], "Team": "Hot"'

打印文本中的球员身价元组,如 ( 5500)


print(tuple(i.get("price") for i in json.loads(re.search(r'[(.*)]', text).group(0))))

15、请写出递归的基本骨架


def recursions(n):
 if n == 1:
 # 退出条件
 return 1
 # 继续递归
 return n * recursions(n - 1)

16、切片

请写出下方输出结果


tpl = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95]
print(tpl[3:])
print(tpl[:3])
print(tpl[::5])
print(tpl[-3])
print(tpl[3])
print(tpl[::-5])
print(tpl[:])
del tpl[3:]
print(tpl)
print(tpl.pop())
tpl.insert(3, 3)
print(tpl)
[15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95]
[0, 5, 10]
[0, 25, 50, 75]
85
15
[95, 70, 45, 20]
[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95]
[0, 5, 10]
10
[0, 5, 3]

17、文件路径

打印输出当前文件所在目录路径


import os
print(os.path.dirname(os.path.abspath(__file__)))

打印输出当前文件路径


import os
print(os.path.abspath(__file__))

打印输出当前文件上两层文件目录路径


import os
print(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

切片操作与对象不可变性解析

18、请写出运行结果,并回答问题


tpl = (1, 2, 3, 4, 5)
apl = (6, 7, 8, 9)
print(tpl.__add__(apl))

问题:tpl 的值发生变化了吗?

运行结果如下:

(1, 2, 3, 4, 5, 6, 7, 8, 9)

答:元组是不可变对象,__add__ 方法返回的是新生成的元组对象,原 tpl 变量指向的元组并未改变,但打印输出的是新对象的值。

19、请写出运行结果,并回答问题


name = ('James', 'Wade', 'Kobe')
team = ['A', 'B', 'C']
tpl = {name: team}
print(tpl)
apl = {team: name}
print(apl)

问题:这段代码能运行完毕吗?为什么?它的运行结果是?

答:这段代码无法完整运行,会在创建 apl 字典时抛出异常。因为字典的键必须是不可变对象,而列表(list)是可变的,因此不能作为字典的键。运行结果是:


{('James', 'Wade', 'Kobe'): ['A', 'B', 'C']}
TypeError

装饰器与多进程多线程对比

20、装饰器

请写出装饰器代码骨架


def log(func):
 def wrapper(*args, **kw):
 print('call %s():' % func.__name__)
 return func(*args, **kw)
 return wrapper

简述装饰器在 Python 中的作用:

在不修改原函数源代码的前提下,动态增加新的功能(如日志记录、权限校验等)。

21、多进程 多线程

多进程更稳定还是多线程更稳定?为什么?

多进程更稳定,因为各进程拥有独立的内存空间,一个进程的崩溃不会影响其他进程。

多线程的致命缺点是什么?

由于所有线程共享同一进程的内存空间,任何一个线程发生崩溃(如段错误)都可能导致整个进程终止。

进程间通信有哪些方式?

常见的进程间通信(IPC)方式包括共享变量(如全局变量,但受 GIL 限制)、队列(Queue)和管道(Pipe)。

好了,本文就给大家介绍到这里,祝大家面试so easy!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。