Python爬虫原理与基本请求库urllib详解
前言「爬虫原理」这四个字经常被讲得玄乎好像有什么特殊机制。其实剥到最里面爬虫就是一件很朴素的事程序代替浏览器发一次 HTTP 请求把响应体取回来再从里面挑出你要的数据。所谓「反爬」绝大多数时候就是服务器识别出这次请求不像人类浏览器发的于是拒绝服务或者返回假数据。要讲清原理就得先把一次 HTTP 请求响应拆开看请求由哪几行组成、响应里哪些信息决定了你的程序该怎么处理。然后把urllib放进标准库的坐标系里看看它到底站在哪一层——这一点很多教程含混带过导致读者分不清urllib、urllib3、requests的关系甚至以为requests是urllib的封装。本文讲机制与定位不重复基础 API 的逐个演示。请求怎么发、参数怎么编码那类操作层面的内容属于另一篇。本文以 Python 3 为基准urllib2是 Python 2 的模块2.7 已于2020 年 1 月 1 日停止维护PEP 373Python 3 把它并进了urllib.request文中一律按 Python 3 写。一、一次 HTTP 请求响应到底发生了什么客户端发出去的报文分成三部分请求行request line、请求头header、请求体body。请求行的格式是「方法 目标路径 协议版本」请求头是一堆Key: Value请求体只在 POST、PUT 这类方法里才有。服务器回来的报文同样是三部分状态行、响应头、响应体。状态行由协议版本、状态码、原因短语组成。把urllib构造出来的请求「翻译」成这三大块是理解它的最快方式。Request对象上正好有对应的属性# 适用于 Python 3.8import urllib.requestreq urllib.request.Request(https://example.com/search?qpython,databa1b2,headers{User-Agent: my-crawler/1.0 (contact: meexample.com)},)print(请求行:, req.get_method(), req.full_url)print(方法:, req.method) # 传了 data 且没指定 method默认 POSTprint(请求体:, req.data) # ba1b2print(请求头:)for name, value in req.header_items():print( , name, , value)这段代码的价值在于它把「一次请求」从抽象概念变成了可打印的对象。上面header_items()一般会打印出User-agent和Content-type两项后者因为data不为None而被自动补成表单编码类型Host、Content-Length这类头则要等到真正发给服务器前才由底层补上。响应那一侧urlopen()返回的对象上有# 适用于 Python 3.8import urllib.requestwith urllib.request.urlopen(https://example.com/, timeout10) as resp:print(状态行:, resp.status, resp.reason)print(响应头示例:, resp.headers.get(Content-Type))print(最终 URL:, resp.geturl())body resp.read()print(响应体字节数:, len(body))resp.geturl()返回的是最终URL。如果中途发生过重定向它和请求时写的 URL 会不一样这正是下一节要讲的机制留下的痕迹。二、状态码与重定向状态码的第一位决定了它的类别区间含义爬虫里的典型处理2xx成功正常解析响应体3xx重定向看Location头跳到新地址4xx客户端错误404 是路径错了403 通常是对方拒绝你5xx服务端错误一般稍后重试且要退避urllib的urlopen()默认会自动跟随重定向。这件事由HTTPRedirectHandler这个 handler 负责它是build_opener()默认安装的 handler 之一默认清单还包括ProxyHandler、HTTPDefaultErrorHandler、HTTPErrorProcessor等。也就是说你请求一个返回 302 的地址urlopen会自己跳到Location指向的新地址最后拿到 200 的结果——resp.geturl()显示的就是跳转后的地址。但有一个例外必须记住只要最终状态码是 4xx 或 5xxurlopen不会返回响应对象而是直接抛HTTPError异常。这个异常由HTTPDefaultErrorHandler在没有任何其他 handler 处理时抛出。理解这一点后try/except的结构就顺理成章了——本小节的代码只做示意异常的完整体系留给进阶那篇# 适用于 Python 3.8import urllib.errorimport urllib.requesttry:resp urllib.request.urlopen(https://example.com/reports, timeout10)except urllib.error.HTTPError as exc:# exc.code 是状态码HTTPError 也能当响应对象读正文print(服务端返回错误状态:, exc.code, exc.reason)else:print(请求成功状态行是:, resp.status, resp.reason)resp.close()注意这里用的是try / except / else结构else里的代码只在没有异常时执行把「成功分支」和「异常分支」分得很干净。记住结论就够了——状态码 ≥ 400 时urlopen不返回响应对象而是抛异常所以「解析响应」的代码天然只会在成功路径上执行。三、urllib 在标准库里的定位先把容易混的三个名字摆清楚它们不是同一个东西名字来自哪里装不装一句话定位urllibPython 标准库不用装官方自带的高层 HTTP 客户端包urllib3第三方 PyPI 包要装更底层的连接池与重试实现requests第三方 PyPI 包要装在urllib3之上做人机友好的封装urllib本身是一个包内部按职责拆成子模块urllib.request管发请求、urllib.parse管 URL 解析与编码、urllib.error管异常、urllib.robotparser管 robots.txt。这种拆法决定了你写代码时至少要import两个模块才能完成一次带参数的请求。从层次上说urllib.request.urlopen()只是一个便捷入口。它内部做的事情是拿到或创建一个OpenerDirector让这个 director 依次调用一串注册好的 handler由 handler 分别负责代理、重定向、Cookie、错误处理最后把结果返回给你。所以urlopen不是「一个函数包打天下」而是「一个默认配置好的 handler 流水线」。这个设计的好处是你可以自己替换流水线里的环节比如换成用环境变量以外的方式指定代理代价是入门时要先理解 handler 这个概念。这也是它比requests啰嗦的根本原因。四、urllib 与 requests 是什么关系网上流传很广的一句话是「requests是对urllib的封装」。这句不准确。requests的 README 和文档里从来没有把urllib列为它的底层它做 HTTP 传输实际依赖的是第三方库urllib3再往上做会话、Cookie、认证、编码猜测这些便利功能。名字里都有url只是巧合urllib3与标准库的urllib是两个独立项目。它们真正的差别在定位维度urllibrequests来源标准库零依赖第三方需pip install返回内容bytes解码自己来text自动解码content给原始字节参数编码自己urlencodeparams自动处理连接复用需要自己搭 openerSession一行搞定默认重定向自动跟随自动跟随head默认关闭适用场景交付环境不能装包、轻量脚本日常开发、功能要求全选型建议很朴素能装第三方库就用requests不能装就用urllib。两者学一个会一个底层的 HTTP 知识是共用的——毕竟无论用哪个库发出去的请求头、回来的状态码都是一样的。五、原理之外的合规底线明白了原理反而更要克制正因为知道一次请求有多轻才容易写出循环几千次把别人站点压垮的脚本。无论用urllib还是requests都请遵守先读目标站的 robots.txt标准库的urllib.robotparser.RobotFileParser提供了can_fetch()和crawl_delay()用可识别的真实User-Agent写明用途与联系方式请求之间限速遇到 5xx 时指数退避而不是加倍猛冲只取公开页面不绕过登录墙、付费墙、验证码不为了「快」而并发压站。这些不是技术限制是使用者的选择。本文不提供任何绕过反爬的手法——那类内容只会让守规矩的人一起遭殃。常见坑点1. 以为urlopen在 404 时返回响应对象。❌resp urlopen(url); print(resp.status)直接写遇到 404 直接抛异常中断。 ✅ 用try/except urllib.error.HTTPError包住且注意HTTPError本身也能.read()。2. 把 3xx 当成失败。❌ 看到 301、302 就以为请求出错直接放弃或报错 —— 其实那只是「资源搬家了」。 ✅ 3xx 属于重定向urllib默认会自动跟随关心最终落点就去看resp.geturl()。3. 以为requests的底层是标准库urllib。❌ 「requests就是urllib的封装所以装机不用联网」——概念错了且它仍需安装。 ✅requests依赖的是第三方urllib3与标准库urllib是两个项目。4. 拿resp.read()的结果直接当文本。❌print(resp.read()[0])期望看到首字符实际看到的是字节的十进制值。 ✅ 先.decode(charset, errorsreplace)。5. 忘了重定向会改变最终地址。❌ 用请求时的 URL 去拼相对链接结果全拼错。 ✅ 用resp.geturl()拿最终地址再基于它做urljoin。6. 不带 timeout。❌urlopen(url)—— 对端半死不活时脚本长时间不动。 ✅urlopen(url, timeout10)并把超时当成可重试的正常情况处理。7. 用 Python 2 的写法。❌import urllib2或print resp.read()—— 前者在 3 里不存在后者是 2 的语句语法。 ✅import urllib.requestprint(resp.read())2.7 已于 2020-01-01 停止维护。8. 只盯状态码不看响应头。❌ 拿到 200 就直接解析忽略Content-Encoding: gzip导致解析出乱码。 ✅ 先看Content-Encoding官方文档给出的示例就是判断到 gzip 时用gzip.decompress()解压再解码。总结概念要点一次请求请求行 请求头 请求体一次响应状态行 响应头 响应体2xx / 3xx / 4xx / 5xx成功 / 重定向 / 客户端错 / 服务端错重定向urllib默认自动跟随由HTTPRedirectHandler负责状态码 ≥ 400urlopen抛HTTPError不返回响应对象urllib结构包含 request / parse / error / robotparser层级urlopen是 OpenerDirector handler 链的便捷入口与requests无封装关系requests依赖第三方urllib3把「一次请求响应」这件小事弄明白urllib的种种设计就都有了解释为什么它要分那么多子模块、为什么要引入 handler、为什么异常要分两层。原理清楚之后换任何一个 HTTP 库都只是换语法不换脑子。

相关新闻

深度学习YOLO苹果采摘护理定位辅助系统:从数据准备到论文答辩全流程

深度学习YOLO苹果采摘护理定位辅助系统:从数据准备到论文答辩全流程

每到毕设选题季,总会看到一批跟目标检测相关的题目,其中智慧农业方向尤其出了一堆“看起来高大上、做起来容易翻车”的项目。今天说的这个方向比较典型:深度学习智慧农业YOLO苹果采摘护理定位辅助系统。简单解释一下,就是用YOLO系…

2026/10/17 11:25:25 阅读更多 →
YOLOv11改进SPASPP:用空洞空间金字塔池化替换SPPF,专治红外小目标检测

YOLOv11改进SPASPP:用空洞空间金字塔池化替换SPPF,专治红外小目标检测

YOLOv11出来有一阵子了,社区里各种“涨点”方案也出了不少,但绝大多数都是在注意力机制或者检测头上做文章,真正针对Backbone特征提取层动手的反而少。这阵子我在做红外场景下的目标检测,被小目标问题折磨得不轻,正好看…

2026/10/17 11:25:25 阅读更多 →
Vue 项目中海康视频监控插件流不稳定断开的前端容错与自动恢复方案

Vue 项目中海康视频监控插件流不稳定断开的前端容错与自动恢复方案

1. 视频监控接入前端这件事,坑比想象中多做过安防类、园区管理类或者智慧工地类项目的同学,大概率都绕不开一个需求:在浏览器里直接看实时视频。而一旦涉及实时视频,海康的 Web 插件(WebControl 那一套)几乎…

2026/10/17 11:24:25 阅读更多 →

最新新闻

微信小程序加载外部3D模型实战:Three.js渲染与性能优化

微信小程序加载外部3D模型实战:Three.js渲染与性能优化

简介:这份资源面向希望在微信小程序中实现3D可视化与交互的开发者,重点解决小程序环境无法直接引入npm库、加载外部3D模型困难等问题。借助three.js这一基于WebGL的JavaScript 3D库,读者可以掌握在小程序中搭建场景、相机与渲染器&#xff0c…

2026/10/17 12:10:41 阅读更多 →
Artcraft:参数即画笔的实时创作方法论

Artcraft:参数即画笔的实时创作方法论

1. “Artcraft”不是新词,而是被低估的创作方法论原点“Artcraft”这个词乍看像某个AI绘画工具的新品牌名,或是某款小众设计软件的代号——但实际翻遍主流技术文档、设计类教材和创意产业白皮书,它既非注册商标,也未被纳入任何标准…

2026/10/17 12:10:41 阅读更多 →
软考NPV计算全解析:静态与动态投资回收期、ROI公式及避坑指南

软考NPV计算全解析:静态与动态投资回收期、ROI公式及避坑指南

简介:这份文档面向备考系统集成项目管理工程师的考生及需要做项目财务评估的从业者,聚焦计算题中的净现值(NPV)这一高频考点。内容围绕NPV基本概念、贴现率与资金时间价值、静态与动态投资回收期公式、投资收益率ROI的换算关系展开…

2026/10/17 12:10:41 阅读更多 →
Kettle PDI 9.2 实战避坑指南:从启动到生产部署的断点解析

Kettle PDI 9.2 实战避坑指南:从启动到生产部署的断点解析

简介:本资源是一套面向1–3年经验研发人员的Kettle(Pentaho Data Integration)入门教学PPT,聚焦ETL核心流程与数据同步实践,帮助开发者快速掌握开源ETL工具的安装、连接、转换设计与性能调优。内容涵盖ETL基础概念、PD…

2026/10/17 12:10:41 阅读更多 →
动态网格交易:基于标准差与RSV的自适应参数方法

动态网格交易:基于标准差与RSV的自适应参数方法

简介:本资源是一份面向量化投资初学者与Python编程实践者的网格交易策略优化方案,聚焦解决传统网格交易中因固定网格导致的过早满仓/空仓、回撤大等核心痛点。作者提出基于市场波动性(收盘价、最高价、最低价标准差)与趋势强度&am…

2026/10/17 12:10:41 阅读更多 →
低查重AI教材生成工具实战:从查重机制到编写流程全解析

低查重AI教材生成工具实战:从查重机制到编写流程全解析

做教材编写这行久了,谁没被“查重率”三个字折腾过。早年间写教材是纯手工活儿,一个字一个字地抠;后来用AI辅助,效率是上来了,但生成的稿子拿去过查重,经常碰一鼻子灰。今天要聊的,是我最近深度…

2026/10/17 12:09:41 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →