爬虫与 JS 逆向面试题复盘
这是一组爬虫和 JS 逆向相关的面试题。
这类面试不会只问“会不会用 requests”,更常见的是从一个具体业务场景开始追问:怎么登录、怎么抓动态接口、怎么处理反爬、百万级数据怎么调度、数据怎么进入后续处理链路。
这篇文章按面试题复盘的方式整理,重点是把回答讲得更清楚、更工程化。
同时要先明确一点:爬虫和逆向要遵守法律、站点协议和数据合规要求。面试中可以讲技术思路,但不应该表达绕过风控、攻击站点或采集敏感数据的意图。更稳的说法是:在授权范围内做数据采集和接口分析。
自动登录怎么选
Section titled “自动登录怎么选”题目:
登录有两种方式,一种是账号密码登录,并且需要输入动态 token;另一种是二维码登录。如果要自动登录,你会选择哪种方式,为什么?说说实现方法。
我的回答倾向是:优先选择账号密码加 token 的方式。
原因:
- 账号密码登录更适合程序化请求。
- 登录流程相对稳定,便于抓包分析。
- 登录成功后可以拿到 token、cookie 或 session。
- 二维码登录通常依赖人工扫码,不适合长期自动化任务。
可以这样回答:
我会优先选择账号密码加 token 的登录方式。因为它更容易通过请求和响应模拟,流程上可以先请求登录页或初始化接口,拿到登录所需的 token、cookie,再携带账号密码和动态 token 请求登录接口。登录成功后保存 cookie 或 access token,后续请求统一带上认证信息。二维码登录更适合人工确认,自动化成本更高,而且很多二维码登录会绑定设备、时效和扫码确认,不适合爬虫任务长期稳定运行。
一个简化流程:
请求登录页或初始化接口 |获取 token / csrf / cookie |提交账号、密码、动态 token |登录成功 |保存 cookie 或 access token |后续请求携带认证信息需要注意:如果动态 token 是验证码、短信码、二次验证,不能假设可以无成本自动化。面试里可以强调“在授权账号和合规场景下处理登录态”。
前端动态渲染的网站怎么爬
Section titled “前端动态渲染的网站怎么爬”题目:
这种前端返回数据的网站,如何爬取数据?
现在很多网站是前端框架渲染,HTML 源码里没有完整数据。此时不要急着解析页面,而是先看网络请求。
常规步骤:
- 打开 Chrome DevTools。
- 进入 Network 面板。
- 过滤 XHR / Fetch 请求。
- 找到真正返回 JSON 数据的接口。
- 分析 URL、请求方法、参数、Headers、Cookie。
- 用 Python 模拟请求。
import requests
url = "https://example.com/api/list"
headers = { "User-Agent": "Mozilla/5.0", "Referer": "https://example.com/list",}
params = { "page": 1, "size": 20,}
response = requests.get(url, headers=headers, params=params, timeout=10)data = response.json()
print(data)如果接口参数是动态生成的,就继续分析 JS。
如果页面确实没有接口,或者数据必须通过浏览器运行后才出现,可以考虑 Selenium 或 Playwright。但大规模采集时,优先分析接口,因为浏览器自动化成本更高。
百万级数据怎么爬
Section titled “百万级数据怎么爬”题目:
面对百万甚至千万数据量的爬取,你的爬取策略是怎么样的?爬取到的数据如何存储?
这题考察的是系统设计,而不是单机脚本。
可以从四层回答:
- 任务拆分。
- 并发控制。
- 反爬与容错。
- 数据存储和后续处理。
一个比较完整的链路是:
任务调度 -> 爬虫采集 -> Kafka -> Flink 清洗 -> 数据存储如果只是普通项目,可以存 MySQL 或 CSV;如果是百万、千万规模,就要考虑分批写入、去重、失败重试、数据清洗和存储扩展。
可以这样回答:
面对百万级数据,我不会用一个单机脚本顺序爬。一般会先把任务拆成分页任务、关键词任务或 ID 区间任务,放到任务队列里,由多个爬虫节点并发消费。采集时会限制请求频率,设置超时重试和代理池,避免单点 IP 或账号压力过大。采集到的数据先进入 Kafka,后续由 Flink 做实时清洗,再写入 MySQL、ES 或数据仓库。对于失败任务会记录状态,后续补偿重试。
平时用什么工具分析网站接口
Section titled “平时用什么工具分析网站接口”常用 Chrome DevTools 的 Network 面板。
主要看:
- XHR / Fetch 请求。
- 请求 URL。
- 请求方法。
- Query 参数和 Request Payload。
- Headers。
- Cookie。
- Response。
- Initiator 调用来源。
如果参数是动态生成的,会继续去 Sources 面板断点调试,或在 JS 文件中搜索参数名。
如何判断网站是否有反爬
Section titled “如何判断网站是否有反爬”可以从几个现象判断:
- 请求参数里存在动态加密参数。
- 接口依赖 token、cookie、签名或时间戳。
- 请求频率过高会被封 IP。
- 返回内容出现验证码、空数据或风控页面。
- 同一个接口在浏览器能访问,程序请求失败。
- Headers 缺失时返回异常。
可以这样回答:
我会先比较浏览器正常请求和程序模拟请求的差异。如果同样的 URL 在浏览器里返回正常,但程序里返回空数据、验证码、403 或风控响应,就说明可能存在反爬。再继续分析是否有动态参数、token 校验、cookie 校验、频率限制或行为检测。
XPath 和 CSS Selector 的区别
Section titled “XPath 和 CSS Selector 的区别”XPath 和 CSS Selector 都能定位 HTML 节点。
| 对比项 | XPath | CSS Selector |
|---|---|---|
| 语法 | 类似路径表达式 | 类似 CSS 选择器 |
| 能力 | 更强,支持轴、文本、复杂路径 | 简洁,适合常见选择 |
| 可读性 | 复杂表达式可读性一般 | 简单场景更清晰 |
| 爬虫常用度 | 很常用 | 也常用 |
面试可以说:
简单页面我会用 CSS Selector,因为语法简洁;复杂定位,比如按文本、层级、相邻节点查找时,我更倾向 XPath。
做过 JS 逆向吗
Section titled “做过 JS 逆向吗”可以按流程回答:
- 使用 Network 抓包找到目标接口。
- 确认哪个参数是动态生成的。
- 全局搜索参数名。
- 在 Sources 面板下断点。
- 观察 Call Stack 调用链。
- 找到最终生成参数的函数。
- 用 Python 或 Node 复现算法。
更完整的回答:
我在项目中遇到过接口参数由 JS 加密生成的情况。处理时先通过 Network 找到接口和异常参数,然后在 JS 文件中搜索参数名。如果搜索不到,就从请求发起位置或 XHR 断点入手,在 Sources 里下断点,结合 Call Stack 分析调用链,找到参数生成函数。确定算法后,再用 Python 或 Node 复现,最后和浏览器生成结果对比,确保请求参数一致。
这类回答要强调“分析和复现授权接口参数”,不要说成攻击或绕过安全系统。
JS 混淆怎么分析
Section titled “JS 混淆怎么分析”JS 混淆后,变量名和函数名可能没有意义,所以不要期待完全看懂所有代码。
常见思路:
- 不全量还原,只找关键链路。
- 通过 XHR/fetch 断点定位请求发起位置。
- 使用 Call Stack 看调用链。
- 打印关键变量。
- 对关键函数做输入输出对比。
- 必要时把关键函数拎出来运行。
可以这样回答:
遇到混淆 JS 时,我不会从头读完整文件,而是围绕目标接口定位关键参数。通过断点、调用栈、关键变量打印和函数输入输出分析,逐步缩小范围,最终定位生成参数的函数。
为什么不用 Selenium
Section titled “为什么不用 Selenium”Selenium 是浏览器自动化工具,适合复杂页面、需要真实浏览器环境的场景。
但它的问题也明显:
- 启动浏览器成本高。
- 并发能力弱。
- 资源占用大。
- 速度慢。
- 大规模采集不划算。
所以一般优先分析接口直接请求。只有接口很难复现、页面强依赖浏览器环境、或需要真实交互时,才考虑 Selenium 或 Playwright。
面试回答:
Selenium 可以用,但我不会作为首选。因为大规模采集更关注吞吐和稳定性,直接请求接口效率更高。Selenium 更适合登录、复杂交互或无法绕开浏览器渲染的页面。
如何保证爬虫长期稳定运行
Section titled “如何保证爬虫长期稳定运行”长期稳定运行靠的不是一个脚本,而是容错和监控。
常见机制:
- 请求超时。
- 失败重试。
- 指数退避。
- 异常捕获。
- 失败任务记录。
- 账号状态检测。
- IP 或代理状态检测。
- 任务监控。
- 健康检查。
- 失败告警。
可以这样回答:
我会为爬虫设计超时重试、异常捕获、失败任务记录和任务监控机制。如果请求失败,会根据错误类型决定重试、切换账号、切换代理或标记任务失败。系统层面会有健康监测和失败上报,保证爬虫可以长期稳定运行。
爬虫规模是多少
Section titled “爬虫规模是多少”如果项目里支持 500万+ / 日 的采集规模,可以这样回答:
系统支持 500 万以上日采集量。采集任务不是由单个脚本完成,而是通过任务调度系统统一拆分和分发,多节点并发执行。采集结果进入 Kafka,再由 Flink 进行实时清洗和处理。
面试时不要只报数字,最好补上支撑数字的架构。
系统架构是什么
Section titled “系统架构是什么”整体链路可以这样描述:
调度系统 | v爬虫节点 | vKafka | vFlink | vMySQL / Elasticsearch / 数据仓库各模块职责:
| 模块 | 作用 |
|---|---|
| 调度系统 | 生成任务、分配任务、协调账号 |
| 爬虫节点 | 执行采集、解析数据、处理重试 |
| Kafka | 解耦采集和处理,缓冲流量 |
| Flink | 实时清洗、过滤、转换 |
| 存储层 | 存储清洗后的业务数据 |
这类回答会比“我用 Scrapy 分布式”更有工程感。
调度系统怎么工作
Section titled “调度系统怎么工作”调度系统主要负责任务生成和账号协调。
你笔记中的规模是:
- 1400+ 爬虫任务。
- 400+ 账号 Cookie。
- 任务信息存储在 Redis。
可以这样回答:
调度系统会把采集目标拆成具体任务,任务状态存储在 Redis 中。爬虫节点从 Redis 获取任务,执行后回写任务状态。账号 Cookie 也由调度系统统一管理,分配任务时会根据账号状态选择可用账号,避免单个账号压力过大。
为什么任务放 Redis
Section titled “为什么任务放 Redis”Redis 适合做任务队列和状态缓存。
原因:
- 读写性能高。
- 支持 List、Set、Hash、Sorted Set 等结构。
- 适合存任务状态、账号状态和临时调度数据。
- 操作简单,延迟低。
可以补一句:
如果任务需要更强的可靠性、确认机制和重试语义,也可以引入消息队列;Redis 更适合轻量级任务调度和状态管理。
如何处理账号失效
Section titled “如何处理账号失效”账号失效的表现:
- 登录失败。
- Cookie 失效。
- 返回 401、403。
- 返回验证码或风控页面。
- 请求结果为空或异常。
处理方式:
- 标记账号不可用。
- 暂停该账号任务。
- 重新调度任务。
- 切换可用账号。
- 触发重新登录或人工处理。
可以这样回答:
系统会根据响应状态和页面内容判断账号是否异常。一旦发现 Cookie 失效或登录状态异常,就标记账号状态,避免继续分配任务,同时把未完成任务重新放回队列,交给其他可用账号处理。
Python 爬虫常用库
Section titled “Python 爬虫常用库”常用库:
requests:发送 HTTP 请求。httpx:支持同步和异步请求。scrapy:爬虫框架。lxml:解析 HTML,支持 XPath。beautifulsoup4:HTML 解析。selenium:浏览器自动化。playwright:现代浏览器自动化。
项目里如果主要使用 requests + XPath,可以这样说:
普通接口采集我主要使用 requests,请求接口后用 XPath 或 JSON 解析数据。如果是复杂任务调度和大规模采集,会考虑 Scrapy 或自研调度系统。
如何处理请求超时
Section titled “如何处理请求超时”基本做法:
import requests
try: response = requests.get( "https://example.com/api", timeout=(3, 10), ) response.raise_for_status()except requests.Timeout: # 记录超时并重试 passexcept requests.RequestException: # 记录其他请求异常 pass可以配合:
- 固定次数重试。
- 指数退避。
- 失败任务入库。
- 切换代理或账号。
如何控制爬虫速度
Section titled “如何控制爬虫速度”常见方式:
- 设置请求间隔。
- 限制并发数量。
- 使用任务队列控制消费速度。
- 对单域名限速。
- 对单账号限速。
- 对异常响应动态降速。
面试里可以说:
控制速度不只是 sleep,而是结合并发数、任务队列、账号维度和站点响应来动态调整,避免触发反爬,也保护目标站点和自身系统。
为什么使用 Docker
Section titled “为什么使用 Docker”Docker 的价值:
- 保证运行环境一致。
- 方便部署。
- 方便横向扩展多个爬虫节点。
- 便于隔离依赖。
- 适合配合 CI/CD。
爬虫系统里尤其适合把爬虫节点容器化。需要扩容时,可以快速启动多个容器实例。
Kafka 在系统中作用
Section titled “Kafka 在系统中作用”Kafka 主要承担数据通道和缓冲层。
作用:
- 解耦采集和处理。
- 缓冲高峰流量。
- 支持高吞吐数据传输。
- 方便后续多个消费者处理数据。
可以这样回答:
爬虫采集速度和后续清洗入库速度不一定一致,所以中间用 Kafka 解耦。爬虫只负责把原始数据写入 Kafka,Flink 再从 Kafka 消费并清洗处理。
Redis 在项目中用来做什么
Section titled “Redis 在项目中用来做什么”Redis 在项目中可以承担:
- 任务队列。
- 任务状态缓存。
- 账号 Cookie 管理。
- 去重集合。
- 临时失败记录。
- 限速计数。
面试回答:
Redis 主要用于调度层,保存任务队列、任务状态和账号 Cookie。因为它读写快,并且数据结构丰富,适合管理这种高频变化的临时状态。
项目中最难的部分是什么
Section titled “项目中最难的部分是什么”可以回答 JS 加密参数逆向。
更完整的说法:
最难的是 JS 加密参数逆向。因为网站 JS 做了混淆,不能直接通过阅读代码看懂逻辑。我通过 Network 定位接口和动态参数,再用 Sources 下断点,结合调用栈分析参数生成流程,最后把关键算法用 Python 或 Node 复现出来。这个过程比较考验调试能力和耐心。
如果网站增加新的反爬怎么办
Section titled “如果网站增加新的反爬怎么办”处理步骤:
- 先复现问题,确认是哪些请求失败。
- 对比正常浏览器请求和爬虫请求差异。
- 判断新增机制:token、cookie、签名、频率、验证码、行为检测。
- 如果是参数变化,重新调试 JS。
- 如果是频率问题,调整限速和调度策略。
- 如果涉及强验证或合规风险,停止采集或走授权接口。
可以这样回答:
我会先分析新增反爬属于哪一类,再决定策略。如果是参数签名变化,就重新定位 JS 生成逻辑;如果是频率限制,就降低并发、调整账号和代理策略;如果是登录态或 Cookie 变化,就更新账号状态检测和重新登录流程。对于验证码或强风控场景,需要评估合规性,不能盲目绕过。
面试回答模板
Section titled “面试回答模板”如果面试官让你整体介绍这个爬虫项目,可以这样组织:
这个项目主要做大规模数据采集。整体链路是爬虫采集、Kafka 缓冲、Flink 清洗、最终写入存储。爬虫侧通过 Chrome DevTools 分析接口,优先直接请求接口而不是 Selenium。调度系统负责管理 1400 多个任务和 400 多个账号 Cookie,任务状态存储在 Redis。系统支持超时重试、失败任务记录、账号失效检测和健康监控。项目中比较难的是 JS 加密参数逆向,我通过断点调试、调用栈分析和算法复现解决过接口动态参数问题。
爬虫和逆向面试题,重点不是只会某个库,而是能把采集链路讲完整:
接口分析 -> 登录态处理 -> 参数逆向 -> 任务调度 -> 并发控制 -> 数据通道 -> 清洗入库 -> 监控补偿如果能把这条链路讲清楚,再结合自己实际做过的规模、账号调度、Kafka/Flink、Redis 和 Docker,回答就会更像真实项目经验,而不是零散知识点。