爬虫面试题
总结一下最近面试遇到的笔试题
1、解释Python中的init方法的作用。
在Python中,__init__方法是一种特殊的构造方法,主要用于在创建类的实例时初始化对象。至少接受至少一个参数:self,它是对当前实例的引用,可以通过添加其他参数传递初始值。
class Person:def __init__(self, name, age):self.name = name # 初始化属性self.age = age# 创建实例时,__init__自动执行
person = Person("Alice", 25)
print(person.name)
print(person.age)
输出:
Alice
25
需要注意的是,__init__不是必须的,可以省略,且__init__应该返回None,否则会引发TypeError。
2、Python中的*args和**args分别是什么?
*args:可变位置参数,接收任意数量的位置参数,并将其打包成一个元组(tuple)。
def sum_numbers(*args):total = 0for num in args:total += numreturn totalprint(sum_numbers(1, 2, 3))
输出:
6
**kwargs:接收任意数量的关键字参数,并将其打包成一个字典(dict)。
def get_info(**kwargs):for key, value in kwargs.items():print(f"{key}: {value}")
get_info(name = "Alice", age = 25, city = "New York")
输出:
name: Alice
age: 25
city: New York
3、写出一个Python生成器的示例,并解释生成器的作用。
生成器是一种惰性计算的特殊迭代器,用于按需生成数据,而不是一次性计算并存储所有数据,适合处理大数据流,节省内存,提高性能,支持无限序列(如斐波那契数列)。
(1)通过yield关键字创建生成器
def count_up_to(max_num):num = 1while num <= max_num:yield num # 每次调用 yield 返回一个值,并暂停执行num += 1# 创建生成器对象
counter = count_up_to(3)# 逐个获取值
print(next(counter))
print(next(counter))
print(next(counter))
print(next(counter))
输出:
1
2
3
StopIteration异常
(2)通过表达式创建生成器
squares = (x ** 2 for x in range(3)) # 生成器表达式(类似列表推导,但返回生成器)# 逐个获取值
print(next(squares))
print(next(squares))
print(next(squares))
print(next(squares))
输出:
0
1
4
StopIteration异常
4、Python中如何实现多线程?请写一个简单的多线程示例。
在Python中通过threading模块实现多线程编程,允许程序同时执行多个任务(并发执行)。但由于GIL(全局解释器锁)的限制,多线程更适合I/O密集型任务(如网络请求、文件读写),而不是CPU密集型任务(计算密集型任务更适合用multiprocessing)。
import threading
import timedef task(name, delay):print(f"线程 {name} 启动")time.sleep(delay) # 模拟耗时操作print(f"线程 {name} 完成")# 创建两个线程
thread1 = threading.Thread(target=task, args=("A", 2))
thread2 = threading.Thread(target=task, args=("B", 1))# 启动线程
thread1.start()
thread2.start()# 等待线程结束
thread1.join()
thread2.join()print("所有线程执行完毕")
输出(由于线程并发,顺序可能不同):
线程 A 启动
线程 B 启动
线程 B 完成 # B先结束,因为delay=1
线程 A 完成
所有线程执行完毕
5、解释Python中的GIL(全局解释器锁)及其对多线程的影响。
GIL,即全局解释器锁,是一个用于同步Python字节码执行的机制,确保同一时刻只有一个线程执行Python字节码。这一设计初衷是为了简化Python的内存管理,防止多线程同时修改数据导致的竞态条件和数据不一致问题。
然而,GIL的存在也限制了Python程序的并发性能,特别是在CPU密集型任务中,由于GIL的存在,即使有多个CPU核心可用,也只有一个线程能够执行代码,这意味着多线程程序并不会真正并行执行,而是交替执行,从而显著降低了程序的执行效率。
import threading
import timedef cpu_bound_task():count = 0for _ in range(10000000):count += 1# 单线程
start = time.time()
cpu_bound_task()
cpu_bound_task()
print(f"单线程耗时: {time.time() - start:.2f}s")# 多线程(由于 GIL,不会更快)
start = time.time()
t1 = threading.Thread(target=cpu_bound_task)
t2 = threading.Thread(target=cpu_bound_task)
t1.start()
t2.start()
t1.join()
t2.join()
print(f"多线程耗时: {time.time() - start:.2f}s")
输出:
单线程耗时: 0.48s
多线程耗时: 0.51s # 多线程反而更慢(线程切换开销)
6、如何避免爬虫被网站封禁?请列举至少3种策略。
(1)设置合理的请求频率,使用time.sleep()随机延迟
import requests
import time
import randomfor page in range(1, 10):url = f"https://example.com/page/{page}"response = requests.get(url)print(f"爬取页面 {page}")time.sleep(random.uniform(1, 3)) # 随机延迟1~3秒
(2)使用随机User-Agent和IP,伪装不同用户
import requests
from fake_useragent import UserAgentua = UserAgent()
headers = {"User-Agent": ua.random} # 随机User-Agent
proxies = {"http": "http://123.45.67.89:8080"} # 代理IPresponse = requests.get("https://example.com",headers=headers,proxies=proxies
)
(3)处理cookies和session,维持回话状态
import requestssession = requests.Session()
login_data = {"username": "your_id", "password": "your_pwd"}
session.post("https://example.com/login", data=login_data) # 模拟登录# 后续请求自动携带Cookies
response = session.get("https://example.com/protected-page")
(4)使用selenium模拟浏览器行为
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://example.com")
html = driver.page_source
7、什么是反爬虫机制?如何应对动态加载内容的网页?
反爬虫机制是指网站为了防止爬虫过度访问和抓取数据而采取的一系列技术手段,这些机制旨在保护网站的安全和资源,减轻服务器压力,并确保合法用户的正常访问。
常见的反爬虫技术有:
- User-Agent检测:拦截无user-agent或使用爬虫常见UA的请求。
- IP封禁:黑名单识别并封禁爬虫常用IP或代理池。
- 验证码:弹出验证码验证人类用户。
- 动态渲染:数据通过JavaScript动态加载,传统爬虫无法直接获取。
- 行为指纹检测:分析鼠标移动、点击模式等行为特征识别爬虫。
- 数据混淆:对网页关键数据加密或动态生成DOM结构。
常见应对方案有:
- 直接调用隐藏的API,分析网页,找到返回目标数据的api接口,模拟浏览器请求获取数据。
import requestsurl = "https://example.com/api/data" # 从Network面板找到的API地址
headers = {"User-Agent": "Mozilla/5.0","X-Requested-With": "XMLHttpRequest" # 模拟AJAX请求
}
params = {"page": 1} # API可能需要的参数response = requests.get(url, headers=headers, params=params)
data = response.json() # 获取JSON数据
- 使用无头浏览器,如Selenium、Playwright、Pyppeteer
from playwright.sync_api import sync_playwrightwith sync_playwright() as p:browser = p.chromium.launch(headless=False) # 显示浏览器调试page = browser.new_page()page.goto("https://example.com")page.wait_for_selector(".dynamic-content") # 等待动态内容加载html = page.content() # 获取渲染后的HTMLbrowser.close()
- 逆向JavaScript,找到数据解密逻辑,复现js代码
import execjsjs_code = """
function decrypt(data) {// 从网站JS中复制的解密函数return data.split("").reverse().join("");
}
"""
ctx = execjs.compile(js_code)
result = ctx.call("decrypt", "edoced_46esab") # 调用JS函数
print(result) # 输出: "base64_code"
8、什么是HTTP状态码?写出常见的状态码和意义。
HTTP状态码是服务器在响应客户端请求时返回的三位数字代码,用于表示请求的处理结果。它属于HTTP协议的一部分,帮助客户端快速判断请求是否成功或失败,便于下一步操作。
常见状态码及意义
1XX(信息性状态码)
表示请求已被接收,需要继续处理。
- 100 Continue:客户端应继续发送请求(用于大文件上传前的确认)。
- 101 Switching Protocols:服务器同意切换协议(如从HTTP升级到WebSocket)。
2XX(成功状态码)
表示请求已成功被服务器接收、理解并处理。
- 200 OK:请求成功(如网页加载成功)。
- 201 Created:资源创建成功(常见于POST请求)。
- 204 No Content:请求成功,但响应无内容(如删除操作)。
3XX(重定向状态码)
表示需要客户端进一步操作以完成请求
- 301 Moved Permanently:资源已永久重定向(SEO会将权重转移到新URL)。
- 302 Found:资源临时重定向(下次请求可能仍用原URL)。
- 304 Not Modified:资源未修改(客户端可使用缓存)。
4XX(客户端错误状态码)
表示客户端请求有误,服务器无法处理。
- 400 Bad Request:请求语法错误(如参数格式错误)。
- 401 Unauthorized:未授权(需身份验证,如未登录)。
- 403 Forbidden:禁止访问(无权限,即使登录也可能触发)。
- 404 Not Found:资源不存在(URL错误或页面已删除)。
- 429 Too Many Requests:请求过于频繁(触发反爬机制)。
5XX(服务器错误状态码)
表示服务器处理请求时出错。
- 500 Internal Server Error:服务器内部错误(如代码崩溃)。
- 502 Bad Gateway:网关错误(代理服务器无法从上游获取响应)。
- 503 Service Unavailable:服务不可用(服务器过载或维护)。
- 504 Gateway Timeout:网关超时(代理服务器等待上游响应超时)。
9、设计一个爬虫系统,要求支持分布式爬取,数据存储和去重。请描述你的设计方案。
本系统采用主从式分布式架构,包含以下核心组件:
(1)调度中心(Master):负责任务分配、节点管理和URL去重
class Scheduler:def __init__(self):self.task_queue = RedisQueue('crawler_tasks') # 待抓取URL队列self.visited_urls = BloomFilter() # 已访问URL布隆过滤器self.workers = {} # 活跃Worker节点def add_task(self, url, priority=0):if not self.visited_urls.contains(url):self.task_queue.push(url, priority)self.visited_urls.add(url)def assign_task(self):while True:task = self.task_queue.pop()available_worker = self.get_available_worker()available_worker.assign_task(task)
(2) 爬虫节点(Worker):执行实际的网页抓取和数据处理
class CrawlerWorker:def __init__(self, worker_id):self.worker_id = worker_idself.http_client = AsyncHTTPClient()self.parser = HtmlParser()async def crawl(self, url):try:# 1. 下载网页response = await self.http_client.fetch(url)# 2. 解析内容data = self.parser.parse(response.body)# 3. 提取新URLnew_urls = self.parser.extract_links(response.body)# 4. 返回结果return {'url': url,'data': data,'new_urls': new_urls}except Exception as e:log_error(f"Failed to crawl {url}: {str(e)}")raise
(3)消息队列:实现任务分发和节点间通信
# RabbitMQ配置
RABBITMQ_CONFIG = {'host': 'mq.master','port': 5672,'user': 'crawler','password': 'password','task_queue': 'crawler_tasks','result_queue': 'crawler_results'
}
(4) 分布式存储:存储爬取结果
# MySQL表结构
CREATE TABLE crawled_pages (id BIGINT PRIMARY KEY AUTO_INCREMENT,url VARCHAR(1024) NOT NULL,title VARCHAR(512),content TEXT,html LONGTEXT,crawl_time DATETIME,md5 CHAR(32), # 内容指纹UNIQUE KEY (md5),INDEX (url(255))
);
(5)去重服务:实现URL和内容去重
class DeduplicationService:def __init__(self):self.redis = RedisClient()self.bloom = ScalableBloomFilter()def is_url_duplicate(self, url):# 先查布隆过滤器,减少Redis访问if not self.bloom.contains(url):return False# 再确认Redis精确去重return self.redis.sismember('visited_urls', url)def is_content_duplicate(self, content):content_md5 = hashlib.md5(content.encode()).hexdigest()return self.redis.sismember('content_fingerprints', content_md5)
(6) 监控系统:监控系统运行状态
10、列举常用的shell命令。
- 文件与目录操作
| 命令 | 作用 |
|---|---|
| ls | 列出目录内容 |
| cd | 切换目录 |
| pwd | 显示当前目录路径 |
| mkdir | 创建目录 |
| rm | 删除文件/目录 |
| cp | 复制文件 |
| mv | 移动/重命名文件 |
| touch | 创建空文件或更新文件时间戳 |
| cat | 查看文件内容 |
| head/tail | 查看文件头部/尾部 |
| find | 查找文件 |
- 文件内容处理
| 命令 | 作用 |
|---|---|
| grep | 文本搜索 |
| sed | 流编辑器(替换/删除文本) |
| awk | 文本处理工具 |
| sort | 排序文件内容 |
| uniq | 去重(需先排序) |
| wc | 统计行数/单词数/字符数 |
- 系统信息与进程管理
| 命令 | 作用 |
|---|---|
| ps | 查看进程 |
| top/htop | 动态查看系统资源占用 |
| kill | 终止进程 |
| df | 查看磁盘空间 |
| du | 查看目录占用空间 |
| free | 查看内存使用 |
| uname | 查看系统信息 |
- 网络操作
| 命令 | 作用 |
|---|---|
| ping | 测试网络连通性 |
| curl/wget | 下载文件 |
| ssh | 远程登陆 |
| scp | 安全复制文件(基于SSH) |
| netstat/ss | 查看网络连接 |
| ifconfig/ip | 查看/配置网络接口 |
- 压缩与解压
| 命令 | 作用 |
|---|---|
| tar | 打包/解压文件 |
| gzip/gunzip | GZIP压缩/解压 |
| zip/unzip | ZIP压缩/解压 |
- 权限管理
| 命令 | 作用 |
|---|---|
| chmod | 修改文件权限 |
| chown | 修改文件所有者 |
| sudo | 以超级用户权限执行命令 |
- 其他实用命令
| 命令 | 作用 |
|---|---|
| history | 查看命令历史 |
| alias | 创建命令别名 |
| contrab | 定时任务管理 |
| ln | 创建链接(硬链接/软链接) |
| date | 显示或设置系统时间 |
相关文章:
爬虫面试题
总结一下最近面试遇到的笔试题 1、解释Python中的init方法的作用。 在Python中,__init__方法是一种特殊的构造方法,主要用于在创建类的实例时初始化对象。至少接受至少一个参数:self,它是对当前实例的引用,可以通过添加其他参数…...
Netty——零拷贝
文章目录 1. 什么是零拷贝?2. 为什么需要零拷贝?2.1 传统 I/O 的拷贝流程2.2 零拷贝的优化2.2.1 通过 sendfile 系统调用2.2.2 通过 mmap (内存映射) 系统调用 3. Netty 实现零拷贝的方式3.1 文件传输优化:FileRegion 封装3.2 直接内存 (Dire…...
Java制作简单的聊天室(复习)
设计的知识点:几乎包含java基础的全部知识点(java基础语法,java基础进阶:双列集合,io流,多线程,网络编程等) 代码如下 客户端: 服务器采用的时多线程的循环多线程的方式…...
ES 字段的映射定义了字段的类型及其行为
在 Elasticsearch 中,字段的映射定义了字段的类型及其行为。你提供的 content_answer 字段映射如下: Json 深色版本 "content_answer": { "type": "text", "fields": { "keyword": { …...
Android开发点击字符串web链接跳到系统浏览器上
Android开发点击字符串web链接跳到系统浏览器上 直接上代码:用到你就拿去用 public static void performItemUrlClick(View view, String contentUrl) {if (!TextUtils.isEmpty(contentUrl)) {Intent intent new Intent();if (!contentUrl.startsWith("http…...
运维规则之总结(Summary of Operation and Maintenance Rules)
运维规则之总结 在运维领域,经验和流程往往决定了系统的稳定性与可靠性。一个运维人,总结出了以下10条运维规则,涵盖了从基础管理到高级策略的全面内容,旨在帮助运维人员更好地应对各种挑战,确保系统的平稳运行。 1.…...
智能家居赋能宠物经济:未来宠物行业的另一片蓝海
一、引言:宠物经济的范式转移 随着城市化进程的加速,宠物在现代家庭中的地位日益重要,宠物经济蓬勃发展。近年来,智能家居技术的兴起为宠物行业带来了新的变革,从传统的情感消费模式向技术赋能的精细化养宠模式转变。…...
C++Primer学习(13.6 对象移动)
13.6 对象移动 新标准的一个最主要的特性是可以移动而非拷贝对象的能力。如我们在13.1.1节(第440页)中所见,很多情况下都会发生对象拷贝。在其中某些情况下,对象拷贝后就立即被销毁了。在这些情况下,移动而非拷贝对象会大幅度提升性能。 如我…...
RHCE工程师特训指南
RHCE(红帽认证工程师)是Linux领域极具含金量的认证之一,其考试以实操为主,注重系统管理、网络服务配置及自动化运维能力。以下内容可帮助对RHCE考生高效规划学习路径。 一、RHCE认证概述 认证结构 RHCE认证分为两部分ÿ…...
内核、进程和线程---操作系统
操作系统 操作系统位于用户程序和硬件之间,通过系统调用提供接口可以让应用程序去使用硬件,但是硬件资源的管理和安全控制由操作系统负责。 用户空间和内存空间 在计算机系统中,内存可以分为两大区域:内核空间(Ker…...
如何在 Postman 中上传图片并在请求中正确引用?
Postman 是一款常用的 API 测试工具,它不仅可以测试 API 的请求和响应,还支持多种数据格式包括图片。如何在 Postman 中传输图片? Postman 如何上传图片并在请求中使用教程...
平板实现 adb connect 连接的步骤
1. 检查设备的开发者选项 确保平板设备已开启开发者模式,并启用了USB调试。 2. 检查设备和电脑的网络连接 确保平板和电脑连接到同一个Wi-Fi网络,确认设备的 IP 地址是否正确。 通过 ping 命令测试: ping 192.168.3.243. 通过USB线进行初…...
安全+低碳+高效:Acrel-3000助力企业打造未来型电能管理体系-安科瑞黄安南
一 背景 电能因为方便传输、易于转换、便于控制等特性,成为广大企事业单位生产、办公最主要的能量来源。双碳背景下,由于电能清洁、高效、零排放的特点,能源消费侧将逐步以电代煤、以电代油、以电代气,形成以电为中心的能源消费体…...
专注自习室:番茄工作法实践
专注自习室:番茄工作法实践 我需要一个任务管理工具,但在网上找了很多都找不到合适的工具。市面上的大多数产品过于强调任务完成性,给我带来了很强的心理压力,这种压力最终反而降低了我的工作效率。于是我决定自己动手࿰…...
docker save如何迁移镜像更节省空间?
文章目录 方法一:使用docker save命令方法二:直接保存多个镜像到一个tar文件哪个方法更节省磁盘空间?空间效率对比实际测试示例其他优势结论 如何用脚本迁移加载镜像 迁移镜像时候,往往会碰到基础镜像相同的很多镜像需要迁移&…...
LeetCode算法题(Go语言实现)_16
题目 给定一个二进制数组 nums 和一个整数 k,假设最多可以翻转 k 个 0 ,则返回执行操作后 数组中连续 1 的最大个数 。 一、代码实现 func longestOnes(nums []int, k int) int {left, zeroCnt, maxLen : 0, 0, 0for right : 0; right < len(nums); …...
CORDIC算法:三角函数的硬件加速革命——从数学原理到FPGA实现的超高效计算方案
计算机该如何求解三角函数?或许你的第一印象是采用泰勒展开,或者采用多项式进行逼近。对于前者,来回的迭代计算开销成本很大;对于后者,多项式式逼近在较窄的范围內比较接近,超过一定范围后,就变…...
JVM 面经
1、什么是 JVM? JVM 就是 Java 虚拟机,它是 Java 实现跨平台的基石。程序运行之前,需要先通过编译器将 Java 源代码文件编译成 Java 字节码文件;程序运行时,JVM 会对字节码文件进行逐行解释,翻译成机器码指令&#x…...
SEO(搜索引擎优化)详解
SEO(搜索引擎优化)详解 SEO是Search Engine Optimization的缩写,中文称为"搜索引擎优化"。它是指通过一系列技术和方法,提高网站在搜索引擎自然(非付费)搜索结果中的排名,从而获得更…...
Ubuntu平台下安装Node相关环境
说明:在进行VUE、TS等开发需要用到NodeJS相关环境,不同的项目有时候需要不同的Node版本支撑。本文将详细讲解NVM、Node、Yarn、PM2等环境安装的实施步骤。 测试服务器环境:22.04 LTS。 1. NVM 定义:Node Version Manager&#x…...
deepseek大模型一体机与deepseek的关系
deepseek大模型一体机与deepseek的关系 一、deepseek大模型一体机是什么 DeepSeek大模型一体机是由深度求索(DeepSeek)公司推出的软硬件一体化AI解决方案,旨在为企业提供高效、便捷的大模型部署和应用能力。 二、deepseek大模型一体机与de…...
Windows Server 2025 使用 IIS 搭建 ASP.NET 3.5 网站
开启远程桌面 参考文章Windows server开启远程桌面教程打开服务管理器。ECS 配置安全组,开启 3389Telnet 验证网络联通性 telnet x.x.x.x 338安装 Windows App,登录验证 安装 ASP.NET 3.5 1.参考文章Windows Server 2012安装 .NET Framework 3.5和 Wi…...
高等数学-第七版-上册 选做记录 习题7-2
1. 2....
基于Promise链式调用的多层级请求性能优化
代码优化-循环嵌套关联请求 1. 背景 在实际开发中,我们经常会遇到需要嵌套关联请求的场景,比如: 获取项目列表获取项目详情获取项目进度 2. 问题 在这种场景下,我们可能会遇到以下问题: 串行请求瀑布流ÿ…...
【强化学习】基于深度强化学习的微能源网能量管理与优化策略研究【Python】
目录 主要内容 程序要点 2.1 微能源网系统组成 2.2 强化学习及Q学习算法 部分代码 运行结果 下载链接 主要内容 该程序借助深度 Q 网络(DQN),学习预测负荷、风 / 光可再生能源功率输出及分时电价等环境信息,运用…...
楼宇自控借何种技术,驱动建筑迈向高效绿色
在全球积极倡导可持续发展的大背景下,建筑行业作为能源消耗和碳排放的大户,实现高效绿色发展迫在眉睫。楼宇自控系统凭借其先进的技术手段,成为推动建筑向高效绿色转型的关键力量。那么,楼宇自控究竟借助哪些技术,让建…...
监控易一体化运维:监控易机房管理,打造高效智能机房
在数字化浪潮中,企业对数据中心和机房的依赖程度与日俱增,机房的稳定运行成为业务持续开展的关键支撑。信息化的变迁,见证了机房管理从传统模式向智能化、精细化转变的过程。今天,就为大家深度剖析监控易在机房管理方面的卓越表现…...
简记_FPGA 硬件最小系统设计
一、FPGA板级设计的五要素 1.1、电源电路 核心电压:一般为固定值 IO电压:FPGA的IO分为多个bank,同一个bank的不同IO引脚电压相同,不同bank的电压可以不同 辅助电压:除了核心电压和IO电压,FPGA工作所需的…...
1.1-站点差异\源码差异\数据存储差异\MVC模型
1、有哪几种站点 分主站、分站、端口站、子站、目录站 2、有哪几种源码语言框架差异 开源-如Zblog 闭源-内部开发 加密-如通达OA 3、网站数据存储有哪几个方式 本地数据库:本地服务器搭建 分离数据库:另外的服务器搭建 云数据库:RDS…...
PHP安装HTML转图片的扩展GD库的使用
修改你的PHP.ini文件,找到以下位置 ;extensionphp_gd2.dll 把前面的;去掉…...
