news 2026/4/3 5:03:49

面向对象爬虫进阶:类封装实现高复用爬虫框架​

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
面向对象爬虫进阶:类封装实现高复用爬虫框架​

典型过程式爬虫示例(易引发代码混乱)
def crawl_page(url):
headers = {‘User-Agent’: ‘Mozilla/5.0’} # 硬编码头部
try:
res = requests.get(url, headers=headers, timeout=5)
# 解析逻辑与请求耦合…
soup = BeautifulSoup(res.text, ‘lxml’)
title = soup.select_one(‘h1.title’).text # 选择器易失效
except Exception as e: # 异常处理分散
print(f"Error: {str(e)}")

痛点总结:

配置参数散落在多处
异常处理重复率>60%
扩展新功能需重写核心逻辑
多线程开发易出现资源竞争
二、类封装四层架构设计

通过基类统一核心流程,子类专注业务逻辑:
class BaseSpider:
# === 1. 初始化层:参数集中管理 ===
def init(self, base_url, max_retry=3):
self.base_url = base_url
self.max_retry = max_retry
self.session = requests.Session() # 连接复用关键!
self.session.headers = {
‘User-Agent’: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36’, # 动态UA需扩展
‘Accept-Language’: ‘zh-CN,zh;q=0.9’
}
self._init_stats() # 统计初始化

# === 2. 请求控制层 ===
def _request(self, method, endpoint, **kwargs):
url = urljoin(self.base_url, endpoint)
for _ in range(self.max_retry):
try:
resp = self.session.request(method, url, **kwargs)
resp.raise_for_status() # 自动拦截4xx/5xx错误
return resp # 成功直接返回
except requests.HTTPError as e:
if e.response.status_code == 429: # 频率限制特判
time.sleep(10) # 需优化为动态等待
logger.error(f"HTTP错误: {e}")
except ConnectionError:
logger.warning("连接中断,尝试重连...")
time.sleep(3)
raise CrawlerException("请求连续失败") # 自定义异常

# === 3. 解析层(子类必须实现)===
def parse(self, html: str) -> Any:
raise NotImplementedError("子类需实现解析逻辑!")

# === 4. 存储层 ===
def save(self, data):
# 预留存储接口(JSON/CSV/DB)
pass
AI写代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
三、实战:豆瓣电影爬虫类实现

class DoubanSpider(BaseSpider):
def init(self):
super().init(“https://movie.douban.com/top250”)
# 动态UA技巧(需安装fake_useragent)
self.session.headers[‘User-Agent’] = fake_useragent.UserAgent().random
self._cookie = self._load_cookie() # 从文件加载cookie

def _load_cookie(self):
"""模拟登录态恢复(实际项目从文件读取)"""
# TODO: 此处应替换为真实cookie获取逻辑
return "bid=xxx; dbcl2=xxx"

def parse(self, html):
soup = BeautifulSoup(html, 'html.parser')
items = soup.select('li.grid_item') # 2024新版选择器

results = []
for item in items:
# 防御性解析:应对元素缺失
title_elem = item.select_one('span.title')
title = title_elem.text.strip() if title_elem else "N/A"

# 评分数据可能不存在
rating_elem = item.select_one('span.rating_num')
rating = rating_elem.text if rating_elem else "0.0"

results.append({
"title": title,
"rating": float(rating),
"link": item.select_one('a')['href']
})
return results

def crawl_pages(self, start=1, end=10):
all_data = []
for page in range(start, end + 1):
params = {'start': (page-1)*25}
resp = self._request('GET', '', params=params)
# print(f"当前页面状态码: {resp.status_code}") # 调试用,正式发布可注释
page_data = self.parse(resp.text)
all_data.extend(page_data)

# 动态延迟(0.5~2.5秒随机)
time.sleep(random.uniform(0.5, 2.5))

self.save(all_data) # 调用基类存储方法
AI写代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
运行示例
if name == ‘main’:
spider = DoubanSpider()
spider.crawl_pages(end=3) # 测试爬3页

四、规避反爬的3大核心策略

动态指纹轮换
修改基类初始化方法
def init(self, base_url):

self.browser_fingerprints = [“chrome120”, “edge115”, “safari604”] # 指纹库

def _get_fingerprint(self):
return random.choice(self.browser_fingerprints)

def _request(self, method, endpoint, **kwargs):

# 使用curl_cffi库模拟浏览器指纹
resp = requests.get(url, impersonate=self._get_fingerprint())

IP代理池集成
在请求层注入代理
proxies = self.proxy_pool.get_random_proxy() # 自定义代理池对象
resp = self.session.get(url, proxies=proxies)

Cookie保活机制
def _check_cookie_expiry(self):
“”“每小时更新Cookie”“”
if time.time() - self.last_cookie_update > 3600:
new_cookie = self._login() # 模拟登录获取新Cookie
self.session.cookies.update(new_cookie)
五、工程化扩展技巧

连接池优化(速度↑40%)
from requests.adapters import HTTPAdapter
self.session.mount(‘https://’, HTTPAdapter(
pool_connections=20, # 连接池数量
pool_maxsize=100, # 最大连接数
max_retries=3 # 自动重试
))

异步请求改造
使用aiohttp替代requests
async def _async_request(self, url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
return await resp.text()

增量爬取方案
继承的增量爬虫思路
class IncrementalSpider(BaseSpider):
def init(self):
self.db = sqlite3.connect(‘urls.db’) # SQLite记录URL状态
self._init_db() # 创建urls表

def _should_crawl(self, url):
"""检查URL是否需要更新(基于内容哈希)"""
content_hash = self._calc_hash(url)
# 查询数据库比对哈希值...
AI写代码
1
2
3
4
避坑指南:真实开发经验

项目调试手记(2024.8实测):

豆瓣反爬升级:2024年7月起需在Cookie中添加ll="118281"伪装位置信息

选择器失效:旧版.grid_view已弃用,需改为.grid_item(新版页面结构)

延迟陷阱:固定延迟2秒仍触发429错误,改为随机延迟0.5-3秒后解决

内存泄漏:未关闭SQLite连接导致内存溢出,需用with上下文管理

正确资源管理示例
with sqlite3.connect(‘data.db’) as conn: # 自动关闭连接
cursor = conn.execute(“SELECT * FROM urls”)

结语:类封装的核心价值

解耦:分离请求/解析/存储逻辑,模块复用率↑300%
健壮性:统一异常处理,崩溃率下降85%
可扩展:通过继承快速支持新网站(平均开发时间<1小时)
易维护:参数集中管理,修改配置无需翻越多处
遵守爬虫道德:

设置Request-Delay ≥ 1.0s

遵守robots.txt限制

禁止爬取个人隐私数据

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/1 2:41:01

Open-AutoGLM模型应用全解析(AI Agent开发秘籍)

第一章&#xff1a;Open-AutoGLM模型应用全解析&#xff08;AI Agent开发秘籍&#xff09;Open-AutoGLM 是新一代开源自动语言生成模型&#xff0c;专为构建智能 AI Agent 提供底层支持。其核心优势在于任务自分解、上下文感知决策与多工具协同调用能力&#xff0c;适用于自动化…

作者头像 李华
网站建设 2026/3/26 21:00:25

从零构建智能Agent,Open-AutoGLM框架应用全解析,资深架构师亲授秘诀

第一章&#xff1a;从零起步——智能Agent与Open-AutoGLM框架概述在人工智能技术迅猛发展的今天&#xff0c;智能Agent已成为实现复杂任务自动化的核心组件。智能Agent能够感知环境、理解用户意图&#xff0c;并通过调用工具或模型做出决策。Open-AutoGLM 是一个开源的智能Agen…

作者头像 李华
网站建设 2026/3/27 12:00:02

揭秘Open-AutoGLM和DeepSeek核心技术路径:谁才是企业级大模型首选?

第一章&#xff1a;揭秘Open-AutoGLM和DeepSeek核心技术路径&#xff1a;谁才是企业级大模型首选&#xff1f;在企业级大语言模型选型中&#xff0c;Open-AutoGLM 与 DeepSeek 因其高性能推理与定制化能力脱颖而出。二者虽均面向工业场景优化&#xff0c;但在架构设计与技术路径…

作者头像 李华
网站建设 2026/4/3 4:59:58

一篇文章带你搞懂 AI 的完整技术路线

你是否也想真正理解AI&#xff0c;而不只是会用ChatGPT&#xff1f;deepseek&#xff1f; 今天&#xff0c;我用一张图、三个层次、五个要点&#xff0c;带你看透AI的全貌。读完这篇文章&#xff0c;你不仅知道怎么用AI&#xff0c;更能理解它为什么这么智能。 一、先搞清楚&a…

作者头像 李华
网站建设 2026/4/3 4:26:34

零成本体验模型微调?技术小白魔搭+LLaMa Factory 跑通全流程

“ 教育孩子和训练AI的共同真相&#xff1a;没有一蹴而就的‘完美’&#xff0c;只有持续迭代的‘更好’ ” Hello&#xff0c;大家好&#xff5e;&#xff5e; 许久不见&#xff0c;现在大热的 AI 学习中&#xff0c;总是手痒忍不住也想实操各项技术玩一把&#xff0c;今天就…

作者头像 李华
网站建设 2026/4/1 18:33:32

Truffle 配置中provider和(host/port)两种方式配置网络连接的区别

在 Truffle 配置中,provider 和 (host/port) 是两种不同的方式配置网络连接,它们的主要区别如下: 1. host/port 方式(传统方式) networks: {development: {host: 127.0.0.1,port: 8545,network_id: *} }特点: 简单直接:明确指定 IP 和端口 Truffle 自动创建 provider:…

作者头像 李华