ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Python爬虫面试全解析:从HTTP到反爬的五大知识块与避坑指南

Python爬虫面试全解析:从HTTP到反爬的五大知识块与避坑指南

简介:这份《python爬虫面试题.pdf》是一份面向Python爬虫开发岗位求职者和初中级爬虫工程师的面试题库,围绕 requests、BeautifulSoup、lxml、Scrapy 等常用技术栈,从请求处理、页面解析、反爬应对到分布式爬虫设计层层递进。资源包内含1个PDF文件,体积约412KB,以精炼问答形式汇编了基础知识、进阶技术、高级技术及深度实战四类问题,覆盖AJAX动态渲染、Cookie/Session管理、IP轮换、Selenium处理JavaScript、Scrapy中间件与Item Pipeline等高频考点,适合系统自测与查漏补缺。已有1008人学习下载,常用于面试前集中梳理爬虫核心原理与常见陷阱,也便于在项目开发中快速检索解决方案。读者可按难度分层练习,先夯实请求库与解析库基本功,再逐步攻克动态内容渲染、反爬对抗、分布式任务调度及日志监控报警等难题,从而全面提升实战能力。

1. 爬虫面试题这个 PDF:考的其实是谁更懂“变化”

Python 爬虫岗位的面试,和一般后端面试最大的不同是:面试官默认你会发请求、会解析页面,他要试探的是你的爬虫在线上挂了之后怎么定位。这份 python 爬虫面试题 PDF 我把核心模块过了一遍,它没打算让你背题,而是把从 HTTP 请求、数据解析、反爬对抗到分布式调度这条链路上,面试官最爱设卡的点全摊开了。对做数据挖掘的人来说,爬虫是取数前置技能,这套题的价值不只是背答案,而是帮你把“拿数据”这件事讲得足够工程化。适合两类人:准备爬虫方向面试的应届生,以及做数据分析和工程、想补采集短板的从业者。建议别把它当题典刷,当出题地图用。

2. 爬虫面试的五大知识块:先搞清考官在哪个维度设卡

爬虫的完整链路很长,但面试题的出题范围其实很收敛。我拆过不少面经复盘,也拿这套 PDF 对照过,发现题目基本落在五个块里:HTTP 请求层、数据解析层、反爬对抗层、框架工程化层、数据落地层。这个分层对应的是一个爬虫从发出请求到数据入库的完整生命周期——面试官问哪一层,往往代表他在考察你哪个环节的熟练度。

拿到这套题先别从头翻,先用这五个维度做一次自测:每一块,你能不能在三分钟内讲出一个真实场景?讲不出来,那一块就是你重点要补的。下面把每一层最高频的面试考点展开说。

2.1 HTTP 请求层:状态码、请求头、会话保持是必答题

这一层的题目表面看是基本功,实际上是在检验你调试线上爬虫的能力。面试官问“你看到一个 403 会怎么处理”,比问“GET 和 POST 有什么区别”更容易拉开差距。

常见的考点集中在三处。第一,请求方式:GET 用于取数据,POST 用于提交数据,但爬虫场景里不少“取数据”的接口也要求 POST,因为参数放在 body 里,服务端更容易做签名校验。第二,状态码:200 正常,301/302 是跳转,403 拒绝访问,404 目标不存在,429 说明请求过于频繁。新手看到非 200 就报错,实际上 302 后面要跟着 Location 继续请求。第三,请求头:服务端反爬的第一道防线就是看 User-Agent、Referer、Accept-Language 是否像一个真实浏览器。

这一节的考点可以对照下表自查,也是 PDF 里反复出现的状态码题:

状态码爬虫里的含义常见处理
200请求成功,响应体可解析进入解析流程
301/302资源迁移或临时跳转跟随 Location,确认最终 URL
403被服务端拒绝先补 UA/Referer,再看频率限制
404目标路径不存在检查 URL 拼接和分页参数
429请求太频繁降频 + 重试 + 指数退避
502/503服务端不可用按退避策略等待重试

会话保持是这一层容易被问深的地方。面试官喜欢用连环题开场:“Session 和 Cookie 是什么关系?第二次请求为什么能带上身份?”正确回答路径是:HTTP 是无状态的,服务端通过 Cookie 下发会话标识,Session 是服务端保存的用户状态,Session ID 通常放在 Cookie 里。爬虫保持登录态,requests 里复用同一个 Session 对象比每次手动拼 Cookie 头更稳。

调试习惯比记答案重要。我遇到请求异常时,第一件事不是改代码,而是打开浏览器开发者工具,对比真实请求和代码请求的头部差异。你也可以先用 curl -I 看一眼响应头,确认有没有 Set-Cookie、Retry-After 这些字段,再决定是补会话还是降频率,这比直接改代码快得多。

2.2 数据解析层:正则、XPath、CSS 选择器的选型边界

数据解析的面试题很少直接让默写语法,而是给你一段 HTML 问“怎么抽取目标字段”。这时候,选型理由比写法更重要。

正则的边界在于锚点。目标字段前后有稳定且唯一的文本标记时,正则最快,例如从一段 JS 变量里抽 JSON。但 HTML 是嵌套结构,不是正则的舒适区,遇到标签层级变化就容易抽错。

XPath 适合复杂嵌套结构,能通过层级关系定位,容错比正则强。CSS 选择器适合前端结构清晰的页面,因为它直接对应类名和 id,写起来直观。三者不是互斥关系,实际项目里经常混用。放在同一个场景里比,结论比较清晰:

解析方式适合场景最容易踩的坑
正则抽取 JSON 片段、URL、数字等锚点明确的文本贪婪匹配导致结果溢出,忘了非贪婪
XPath层级深、结构复杂的节点定位页面是 JS 渲染的,XPath 能定位但抓不到数据
CSS 选择器类名和 id 稳定的页面前端改版后选择器失效

这里埋着一个高频后续题:页面是 JavaScript 动态渲染的,解析前拿不到数据怎么办?这就要回到请求层去分析接口,看 HTML 里有没有内嵌 JSON,或者直接抓 XHR 接口。面试里能主动把这个链路讲出来,比单纯背解析语法加分得多。

2.3 反爬对抗层:从随机 UA 到行为轨迹的四级难度

反爬题是爬虫面试的深水区,也是翻车重灾区。先说明一点:讨论反爬技术,正确的开口是先讲清合规边界——只对自己有权限的站点做测试,或者面向公开数据做低频采集。面试官问“怎么处理验证码”,他想听的不是绕过手段清单,而是你判断“该不该走这条路”的思路。

反爬手段分四个难度层级。第一级是简单 UA 封禁,补请求头就能过。第二级是 Cookie 校验与参数签名,需要在请求前先取 token 再拼参数。第三级是验证码、滑块这类人机验证,往往伴随行为轨迹检测,鼠标路径都会被分析。第四级是前端 JavaScript 加密,数据和接口参数做了混淆,需要断点调试还原加密逻辑。

面试里被问到“遇到反爬怎么办”,按顺序回答比较稳:先看返回状态码和响应体特征,区分是被拒绝访问还是被校验拦截;再用浏览器抓一次正常请求,对比代码请求缺了哪些头或参数;最后才决定是补参数、降频次还是换策略。多数时候问题出在缺 Cookie 或频率过高,而不是真被验证码拦住。

注意:反爬对抗在面试里是技术讨论,不是攻击教学。答题时先声明“只在有权限的站点和技术学习场景下测试”,这句话本身就是工程素养的加分项。

这一层还有个容易被忽略的点:不要把随机 UA 当万能药。面试题常问“为什么随机 UA 还是被 403”,答案是服务端可能校验了 TLS 指纹或 Cookie 一致性,单纯改 UA 反而暴露了伪装的痕迹。能答出这个细节,说明你踩过真实项目的坑。

2.4 框架工程化层:Scrapy 的三大高频考点

进入框架环节,面试官基本是在考察你有没有写过能上线的爬虫,而不只是调过 requests。Scrapy 的题目集中在三点:中间件、管道、并发参数。

中间件要分清 Downloader Middleware 和 Spider Middleware。前者作用于请求发出前后,适合改 UA、处理代理、重试;后者作用于响应从引擎回到蜘蛛的过程中,适合过滤响应、改解析结果。面试里用一个例子就能讲清楚:某个站点对请求头有校验,我在 Downloader Middleware 里统一给每个请求补上动态 Cookie,而不是在每个回调函数里重复设置。

管道的考点是数据落地。Pipeline 按顺序执行,每个 item 会经过所有启用的管道。常见用途是清洗、去重、入库。面试常问“管道里怎么去重”,答案是专门建一个去重管道,把 item 的唯一键先查一次再写库,而不是在业务代码里判断。

并发参数这块,背题的人会背默认值,但面试官想看的是你会不会调。核心参数有这些:

参数作用踩坑点
CONCURRENT_REQUESTS全局最大并发请求数并发拉满不代表效率高,容易被限流
DOWNLOAD_DELAY请求间隔设 0 时只有配合限速功能才有意义
ROBOTSTXT_OBEY是否遵守 robots 协议合规要求下建议开启
AUTOTHROTTLE_ENABLED自动限速根据响应时间动态调整并发
RETRY_ENABLED失败重试配合 RETRY_TIMES 控制重试次数

实际调优顺序应该是先开 AUTOTHROTTLE,再根据抓取成功率手动收紧 DOWNLOAD_DELAY,最后才动 CONCURRENT_REQUESTS。这个顺序本身就是一道送分题,答出来能体现项目经验。

2.5 数据落地层:去重、队列、增量爬取怎么接

爬虫拿到数据不算完,能稳定落库才叫工程化。这一层考的是存储选型和去重策略。

去重是必考题。最简单的是 MySQL 主键或唯一索引去重,适合几千万以内的数据量;更大规模用 Redis 的 Set 保存已爬 URL 指纹,以内存换查询速度;分布式场景会聊布隆过滤器,但要明确它是有误判率的。面试时能把这三档方案按“数据量”而不是按“技术新潮程度”排列,说明你真的做过取舍。

队列与调度是另一个考点,常问“两个爬虫进程怎么避免抓同一个 URL”。常见方案是 Redis 队列:一个进程负责产 URL 入队,多个进程从队列里取,配合 Set 做去重,取到重复的直接丢弃。这个方案里 Set 存的是 URL 的 MD5 值而不是原始字符串,能省不少内存。

增量爬取的本质是回答“只抓增量,不重抓全量”。两种主流思路:按时间戳增量,简单但依赖站点更新时间字段;按内容指纹增量,抓回来先算哈希再对比,适合内容经常变化的页面。把这两种思路的取舍讲清楚,比背某个框架的增量配置更有说服力。

存储选型常被一起问。结构化表格数据用 MySQL,半结构化 JSON 用 MongoDB,临时队列和去重用 Redis,文件类数据直接落对象存储。一句话原则:数据是什么形态,就用什么存储,别为了技术栈好看硬上。

3. 刷题策略:把 PDF 里的题从“背答案”变成“讲方案”

同样一本面试题,有人背熟了还是挂,有人只看了三分之一就过了,差别在答题姿态。面试官每天听几十个人讲“我用 requests 爬了某个网站”,你要做的是让他觉得你不只是会写,而是遇过问题、知道怎么定位。PDF 里的每道题都可以按下面四种题型去准备。

3.1 答代码题:先用三句话说清思路,再动手写代码

代码题在爬虫面试里很常见,但很少是让默写整个爬虫,通常是给一个局部场景:比如“用 requests 抓取列表页并处理翻页”。拿到题别立刻敲键盘,先说三句话:输入是什么、输出是什么、翻页终止条件怎么判断。然后再写核心代码。这三句话既是帮自己理清边界,也是给面试官一个预期,避免你写一半对方看不明白。

翻页是个典型题。很多人第一反应是写 for page in range(1, 10),这种写法在真实环境里很危险:目标站点可能只有 8 页,倒数第二页就返回空数据,代码还会空转两轮。正确写法里藏着几个容易忽略的细节:循环终止条件用“没有下一页”而不是固定页数;每次请求前检查当前会话是否失效;请求间隔用 sleep 控制,而不是空转。

# 翻页时先判断终止,再发请求 while True: html = session.get(url, params={"page": page}).text items = parse(html) # 解析当前页列表 if not items: # 没有数据时终止,而不是等报错 break save_to_queue(items) if not has_next(html): break page += 1 time.sleep(random.uniform(0.5, 1.2)) # 随机间隔,避免固定节奏

面试时这段代码不用多完整,重点是把终止条件、随机间隔、会话复用三个点讲出来。参数上也有讲究:随机间隔的区间不宜过大,0.5 到 1.2 秒是常见范围;session 对象复用是为了保持请求头一致,而不是每次新建。能讲出这些细节,面试官基本不会再往下难为你。如果对方追问“抛异常怎么办”,补一句“重试三次、指数退避、写日志”就圆上了。

提示:面试现场手写代码一般只看核心逻辑,但你要口头补一句“正式代码里会加 try-except 和日志”,面试官会认为你考虑到了异常路径。

3.2 答场景题:用 STAR 把一次爬虫事故讲成工程经验

场景题是拉开差距的地方,常见问法“你的爬虫遇到过什么问题,怎么解决的”。很多人把送分题答成了流水账:“我写了个爬虫,后来挂了,改了下代码就好了。”信息量几乎为零。

正确做法是用 STAR 结构。S 是背景:当时接的是某数据平台的列表页采集,每天增量更新上万个记录。T 是任务:更新过程中频繁出现 403,导致当天数据有缺口。A 是行动:对比浏览器请求和代码请求,发现缺了请求头里的签名参数;随后把所有请求统一走中间件补签名,同时加了失败重试和告警。R 是结果:失败率从百分之十几降到百分之一以下,缺口被补偿任务追平。

这样讲,面试官能从中看到你的定位能力和工程意识。讲事故时注意:不只讲成功,把排查过程中的转折也带出来。“当时我怀疑是 IP 被限,换代理后还是 403,才回头去对比请求头”——这种转折才是考官想听的。事故里的数字也会让可信度上一个台阶,但前提是你真的量过,别现场编。

3.3 答系统设计题:现场设计采集系统时的必答框架

“让你给某资讯站点设计一个爬虫采集系统,说下思路”是出现频率很高的压轴题。很多人上来就聊 Scrapy 和分布式,忽略了一个更重要的动作:先把需求问清楚。

标准答题框架是先澄清四个参数:目标数据量是多少、更新频率多高、对时效性的要求是分钟级还是天级、数据最终落到哪个存储。这四个参数直接决定你能不能往下设计。数据量百万级和亿级的方案完全是两套东西,前者单机加定时任务就够了,后者才需要聊分布式。

澄清完需求之后按五层过一遍:抓取层用什么框架、要不要代理池;解析层是静态页面还是动态渲染;去重层用 MySQL 唯一索引还是 Redis 指纹;调度层是定时任务还是常驻进程;监控层有没有失败告警和数据量校验。每一层用一句话讲方案就行,不用展开到具体参数。最后补一句合规:“遵循 robots 协议,只抓公开数据,请求频率控制在对方可接受范围内。”这句话放在结尾,比放在开头更自然,也体现了你考虑过上线风险。

这道题答得好不好,不在于你技术多炫,而在于你能不能让人相信你设计的东西真的能跑起来。

3.4 答算法设计题:Top K 和布隆过滤器怎么在爬虫场景里讲

爬虫面试的算法题通常不长成纯算法,而是包装成工程问题。最常见两道:海量 URL 怎么去重、海量数据里怎么取访问频率 Top K。

去重题最优解是布隆过滤器,但背出概念不够。面试官想听的是参数关系:位数组长度 m、哈希函数个数 k、预期元素数量 n、误判率 p 之间怎么权衡。给一个工程结论:k 越多误判率越低,但位数组要跟着变大;实际部署时按预期数据量设置位数组,让误判率控制在 1% 以内,再配合一个精确去重层兜底。

Top K 题的经典包装是“统计哪些 URL 被访问次数最多”。正确解法是用固定大小的小顶堆,内存里维持 K 个元素,新数据大于堆顶就替换。设计题给一个参考值:千万级数据取 Top 100,单机内存完全够用,不需要上分布式,先把堆讲清楚再谈扩展。能主动说“单机先扛住,扛不住再上分片”,面试官会觉得你有容量意识。

两道题能答好,本质是因为你理解爬虫不只是“抓”,还有“存”和“算”。面试官问算法,往往是想确认你有没有能力处理爬虫拿到数据之后的那一段。

4. 爬虫面试避坑:五个高频翻车现场与修复方案

这一章的素材来自面试复盘和我自己早期踩过的坑。每一条都是“现象 → 原因 → 解决”的结构,可以对照自己现在处于哪个阶段。

4.1 现象一:requests 与 urllib 的区别只答了“requests 更简单”

被问概率极高的一道基础题,翻车答案高度统一:“requests 是第三方库,封装好,比 urllib 好用。”这句话没毛病,但没有信息量。考官想听的是底层差异:requests 基于 urllib3,提供连接池、自动重试、Session 复用、更友好的异常体系;urllib 是标准库,不用额外安装,但要用更多代码实现同样的功能。

原因在于很多人只会用 requests,从没用 urllib 写过一次请求,答不出实质差异。解决办法是强制自己用 urllib 手写一次带请求头的 GET 和 POST,体会两者的编码量差异。下次被问到,就可以从“连接管理、会话、异常处理”三个维度答,而不是一句“更简单”。如果考官追问 urllib3 是什么,你只需要答它是纯 Python 实现的 HTTP 客户端库,提供连接池和重试机制,requests 底层就是它。

4.2 现象二:代理池方案里把“取代理”当核心,忽略失效检测

面试题常问“代理池怎么设计”,很多人张口就是“存一堆代理,随机取一个用”。这个答案会让面试官皱眉头,因为随机取代理等于没设计。代理池的核心不是获取代理,而是可用性维护。

现象是答完“随机取”之后接不上话。原因是把代理池想成了静态列表,没想过代理会因封禁、超时而失效。解决方法是补三层:第一层定期从代理源抓取入库;第二层使用时先做可用性校验,比如请求一次指定探测 URL;第三层失效代理移除并记惩罚分,连续失败直接拉黑。能讲出第二层的校验细节,效果远好于背一整套架构图。被追问“校验代理用什么请求”,一般讲短超时 GET,timeout 设 5 秒,超过直接判定失效。

4.3 现象三:session 和 cookie 讲混,登录态问题直接崩

这个坑几乎每个新手都踩过。被问“怎么保持登录态”,有人回答“把 Cookie 粘到请求头”,有人回答“用 session”,两个答案都不完整,因为没讲清两者关系。

现象是面试官追问“Session 存在哪”就卡住。原因是把 Session 理解成了客户端存的东西,实际 Session 是服务端状态,客户端只保存 Session ID,通常放在 Cookie 里。解决方法是把链路串起来回答:首次请求时,服务端生成 Session 并下发 Session ID 到 Cookie;后续请求携带 Cookie,服务端凭 Session ID 找回用户状态。爬虫里用 requests.Session 能自动管理 Cookie,登录后不用手动拼接。被追问“Session 有效期谁控制”,答服务端超时回收机制,和客户端 Cookie 保留时长是两回事。

4.4 现象四:Scrapy 调并发只动 CONCURRENT_REQUESTS

被问“Scrapy 抓得太慢怎么调”,新手第一反应是调大并发。调大之后常见结果:抓取成功率下降,触发封禁,性能反而更差。

原因是并发和频率是两个维度,CONCURRENT_REQUESTS 只控制同时发出的请求数,真正影响服务端压力的是单位时间请求频率。解决方法是先开启 AUTOTHROTTLE_ENABLED,让框架根据响应时间自动调整节奏,再设置 DOWNLOAD_DELAY 作为地板值,最后按需调并发上限。这三个参数的调整顺序本身就是经典面试题,顺序对了,考官会认为你真调过。被追问“AUTOTHROTTLE 怎么生效”,可以讲它是根据下载延迟和响应时间动态调整,具体调多少以实际抓取成功率为准。

4.5 现象五:被问海量 URL 去重时张口就是位图

“上亿 URL 去重怎么做”这道题,很多人张口就是“用位图”,结果被追问“误判怎么办”就卡壳。位图只能记录存在与否,无法处理哈希碰撞带来的误判;而且它存的是位,不存原始指纹,碰撞了没法二次校验。

原因在于只背了“大数据去重用位图”的结论,没理解位图只是布隆过滤器的组成部分。解决方法是按场景分层答:小规模用 MySQL 唯一索引;中等规模用 Redis Set 存 URL 的 MD5 指纹;大规模用布隆过滤器,但补一句“布隆过滤器有误判率,后面加精确去重层兜底”。能主动讲出兜底方案,这道题基本就过了。被追问“精确去重层怎么做”,答哈希表加落库唯一键,对布隆过滤器判为存在的再做一次精确校验。

5. 拿到 PDF 后的第一周:按“裸答-标记-场景化”三遍法落地

这套资源不是用来从头翻到尾的,它适合按“裸答-标记-场景化”三遍法刷,把一份 PDF 变成自己的答题框架,而不是只留下“我好像看过”的印象。

第一遍叫裸答。拿到 PDF 先不翻答案,从头到尾过一遍,会的题三分钟内口头说完整答案,不会的直接跳过。重点不是答对,而是找出“我以为我会、其实说不顺”的题。我刷第一遍时就发现,自己最卡的不是 Scrapy 参数,而是反爬那一层——知道大概,却讲不出排查顺序。这个发现直接改变了后续复习计划。

第二遍叫标记。把第一遍卡壳的题按第二章的五大知识块分类,统计哪块占比最高。如果多半集中在数据解析层,说明短板在 HTML 结构理解;如果集中在框架层,要去补中间件和管道的执行顺序,而不是继续背参数默认值。这一步把“我不会”翻译成“我哪里不会”。

第三遍叫场景化。把每道题的题干改写成自己的项目场景重答一遍。PDF 里写“Scrapy 如何设置请求间隔”,就改成“我的爬虫抓某招聘网站时被 429,怎么调参”;PDF 里写“如何设计代理池”,就改成“如果给内部采集平台搭代理池,第一版怎么做”。场景化是为了逼你把答案里的每个参数对应到一个真实失败场景上。

我后来养成了个习惯:每次刷完一组题,挑一道口头复述给别人听,复述不出来就重新看。口语输出会逼你把“知道”转换成“能讲”,这个转换往往比多刷十道题更有用。那次因为背答案翻车之后,我每次准备面试都强制走一遍三遍法,再也不搞题海战术了。这份 Python 爬虫面试题 PDF 配着三遍法刷,比对着答案抄一遍有效得多。希望帮到你。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进