爬虫面试题

news2025/3/31 20:32:18

总结一下最近面试遇到的笔试题

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 = 0
	for num in args:
		total +=  num
	return total

print(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 = 1
    while 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 time

def 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 time

def cpu_bound_task():
    count = 0
    for _ 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 random

for 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 UserAgent

ua = UserAgent()
headers = {"User-Agent": ua.random}  # 随机User-Agent
proxies = {"http": "http://123.45.67.89:8080"}  # 代理IP

response = requests.get(
    "https://example.com",
    headers=headers,
    proxies=proxies
)

(3)处理cookies和session,维持回话状态

import requests

session = 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 requests

url = "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_playwright

with 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()  # 获取渲染后的HTML
    browser.close()
  • 逆向JavaScript,找到数据解密逻辑,复现js代码
import execjs

js_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_id
        self.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. 提取新URL
            new_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/gunzipGZIP压缩/解压
zip/unzipZIP压缩/解压
  • 权限管理
命令作用
chmod修改文件权限
chown修改文件所有者
sudo以超级用户权限执行命令
  • 其他实用命令
命令作用
history查看命令历史
alias创建命令别名
contrab定时任务管理
ln创建链接(硬链接/软链接)
date显示或设置系统时间

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2323833.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Netty——零拷贝

文章目录 1. 什么是零拷贝&#xff1f;2. 为什么需要零拷贝&#xff1f;2.1 传统 I/O 的拷贝流程2.2 零拷贝的优化2.2.1 通过 sendfile 系统调用2.2.2 通过 mmap (内存映射) 系统调用 3. Netty 实现零拷贝的方式3.1 文件传输优化&#xff1a;FileRegion 封装3.2 直接内存 (Dire…

Java制作简单的聊天室(复习)

设计的知识点&#xff1a;几乎包含java基础的全部知识点&#xff08;java基础语法&#xff0c;java基础进阶&#xff1a;双列集合&#xff0c;io流&#xff0c;多线程&#xff0c;网络编程等&#xff09; 代码如下 客户端&#xff1a; 服务器采用的时多线程的循环多线程的方式…

内核、进程和线程---操作系统

操作系统 操作系统位于用户程序和硬件之间&#xff0c;通过系统调用提供接口可以让应用程序去使用硬件&#xff0c;但是硬件资源的管理和安全控制由操作系统负责。 用户空间和内存空间 在计算机系统中&#xff0c;内存可以分为两大区域&#xff1a;内核空间&#xff08;Ker…

如何在 Postman 中上传图片并在请求中正确引用?

Postman 是一款常用的 API 测试工具&#xff0c;它不仅可以测试 API 的请求和响应&#xff0c;还支持多种数据格式包括图片。如何在 Postman 中传输图片&#xff1f; Postman 如何上传图片并在请求中使用教程

安全+低碳+高效:Acrel-3000助力企业打造未来型电能管理体系-安科瑞黄安南

一 背景 电能因为方便传输、易于转换、便于控制等特性&#xff0c;成为广大企事业单位生产、办公最主要的能量来源。双碳背景下&#xff0c;由于电能清洁、高效、零排放的特点&#xff0c;能源消费侧将逐步以电代煤、以电代油、以电代气&#xff0c;形成以电为中心的能源消费体…

专注自习室:番茄工作法实践

专注自习室&#xff1a;番茄工作法实践 我需要一个任务管理工具&#xff0c;但在网上找了很多都找不到合适的工具。市面上的大多数产品过于强调任务完成性&#xff0c;给我带来了很强的心理压力&#xff0c;这种压力最终反而降低了我的工作效率。于是我决定自己动手&#xff0…

LeetCode算法题(Go语言实现)_16

题目 给定一个二进制数组 nums 和一个整数 k&#xff0c;假设最多可以翻转 k 个 0 &#xff0c;则返回执行操作后 数组中连续 1 的最大个数 。 一、代码实现 func longestOnes(nums []int, k int) int {left, zeroCnt, maxLen : 0, 0, 0for right : 0; right < len(nums); …

CORDIC算法:三角函数的硬件加速革命——从数学原理到FPGA实现的超高效计算方案

计算机该如何求解三角函数&#xff1f;或许你的第一印象是采用泰勒展开&#xff0c;或者采用多项式进行逼近。对于前者&#xff0c;来回的迭代计算开销成本很大&#xff1b;对于后者&#xff0c;多项式式逼近在较窄的范围內比较接近&#xff0c;超过一定范围后&#xff0c;就变…

JVM 面经

1、什么是 JVM? JVM 就是 Java 虚拟机&#xff0c;它是 Java 实现跨平台的基石。程序运行之前&#xff0c;需要先通过编译器将 Java 源代码文件编译成 Java 字节码文件&#xff1b;程序运行时&#xff0c;JVM 会对字节码文件进行逐行解释&#xff0c;翻译成机器码指令&#x…

Ubuntu平台下安装Node相关环境

说明&#xff1a;在进行VUE、TS等开发需要用到NodeJS相关环境&#xff0c;不同的项目有时候需要不同的Node版本支撑。本文将详细讲解NVM、Node、Yarn、PM2等环境安装的实施步骤。 测试服务器环境&#xff1a;22.04 LTS。 1. NVM 定义&#xff1a;Node Version Manager&#x…

Windows Server 2025 使用 IIS 搭建 ASP.NET 3.5 网站

开启远程桌面 参考文章Windows server开启远程桌面教程打开服务管理器。ECS 配置安全组&#xff0c;开启 3389Telnet 验证网络联通性 telnet x.x.x.x 338安装 Windows App&#xff0c;登录验证 安装 ASP.NET 3.5 1.参考文章Windows Server 2012安装 .NET Framework 3.5和 Wi…

【强化学习】基于深度强化学习的微能源网能量管理与优化策略研究【Python】

目录 主要内容 程序要点 2.1 微能源网系统组成 2.2 强化学习及Q学习算法 部分代码 运行结果 下载链接 主要内容 该程序借助深度 Q 网络&#xff08;DQN&#xff09;&#xff0c;学习预测负荷、风 / 光可再生能源功率输出及分时电价等环境信息&#xff0c;运用…

楼宇自控借何种技术,驱动建筑迈向高效绿色

在全球积极倡导可持续发展的大背景下&#xff0c;建筑行业作为能源消耗和碳排放的大户&#xff0c;实现高效绿色发展迫在眉睫。楼宇自控系统凭借其先进的技术手段&#xff0c;成为推动建筑向高效绿色转型的关键力量。那么&#xff0c;楼宇自控究竟借助哪些技术&#xff0c;让建…

监控易一体化运维:监控易机房管理,打造高效智能机房

在数字化浪潮中&#xff0c;企业对数据中心和机房的依赖程度与日俱增&#xff0c;机房的稳定运行成为业务持续开展的关键支撑。信息化的变迁&#xff0c;见证了机房管理从传统模式向智能化、精细化转变的过程。今天&#xff0c;就为大家深度剖析监控易在机房管理方面的卓越表现…

PHP安装HTML转图片的扩展GD库的使用

修改你的PHP.ini文件,找到以下位置 ;extensionphp_gd2.dll 把前面的;去掉…

清华大学第10讲:迈向未来的AI教学实验396页PPT 探索未来教育的无限可能|附PPT下载方法

导 读INTRODUCTION 今天跟大家分享的是清华大学新闻与传播学院、人工智能学院双聘教授沈阳教授团队出品的《迈向未来的AI教学实验》课程作业集&#xff0c;随着人工智能技术的飞速发展&#xff0c;教育领域也迎来了前所未有的变革。该报告为沈阳教授与学生们在“迈向未来的AI教…

《白帽子讲 Web 安全》之服务端请求伪造(SSRF)深度剖析:从攻击到防御

引言 在当今复杂的网络环境中&#xff0c;Web 应用安全犹如一座时刻需要精心守护的堡垒。随着技术的不断演进&#xff0c;各类安全威胁层出不穷&#xff0c;其中服务端请求伪造&#xff08;SSRF&#xff09;正逐渐成为令开发者与安全从业者头疼的一大难题。吴翰清在《白帽子讲…

豪越消防一体化安全管控平台:消防管理智能化

在社会快速发展、城市建设日益复杂的今天&#xff0c;消防安全始终是保障人民生命财产安全、维护社会稳定的重要基石。传统消防管理模式在应对当下复杂多变的消防安全需求时&#xff0c;逐渐暴露出诸多局限性&#xff0c;而豪越消防一体化平台的出现&#xff0c;为消防管理领域…

瑞芯微RK356X主板复用接口配置方法,触觉智能嵌入式方案商

本文介绍瑞芯微RK356X系列复用接口配置的方法&#xff0c;基于触觉智能RK3562开发板演示&#xff0c;搭载4核A53处理器&#xff0c;主频高达2.0GHz&#xff1b;内置独立1Tops算力NPU&#xff0c;可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。 复…