资讯动态

Python爬虫入门:Requests库HTTP请求与响应处理详解

发布时间:2026/9/19 22:40:16 来源:尧图企业网站定制
简介这份完整版Python网络爬虫系列课程的第一讲聚焦Requests库入门面向零基础开发者适合系统学习数据采集与信息提取技术。课件从HTTP请求动作切入逐一说明构造请求、获取网页、提交表单等常见操作的区别并重点梳理Response对象中状态码、文本内容、编码方式等属性的实际用途同时强调网络连接可能出现的异常给出稳健处理请求失败的思路。课件制作精细由浅入深从安装命令开始逐步讲到实际爬取HTML页面的完整流程。借助这59页PPT读者可以快速掌握使用Requests库自动获取网页、携带参数、读取响应内容的全部要点为后续BeautifulSoup网页解析、信息标记与提取以及Scrapy爬虫框架实战打下坚实基础。资源共1个PPTX文件压缩包大小1.87MB已有449人学习使用方便随时回顾和对照练习。1. 为什么第一个Python爬虫库应该选Requests网络爬虫的第一步不是写解析HTML的逻辑而是先把网页内容拿到手里。Requests是Python里最常用的HTTP请求库它把连接管理、请求头、URL拼接和重定向这些底层细节封装成一行代码做数据采集和信息提取时你只需要关心“请求什么”和“拿到什么”。相比标准库urllibRequests的API更简洁中文资料多遇到问题容易搜到答案。更重要的是后续学BeautifulSoup、Scrapy时请求与响应的概念是贯通的先在Requests上把HTTP概念打牢后面切到其他框架不会卡壳。这门入门课把Requests放在第一课正好对应“先解决数据从哪来”这个核心问题。它适合没有网络编程经验的Python开发者也适合想系统回顾爬虫基础的人。2. Requests的7个请求方法拆解与第一个GET请求2.1 Windows下安装Requests库Requests不是Python标准库需要额外安装。官方文档给出的安装命令是pip install requestsWindows平台要“以管理员身份运行”cmd避免出现权限不足导致安装失败。如果你用macOS或Linux或者本机存在Python2和Python3共存的情况建议用pip3 install requests或者直接用模块方式安装python -m pip install requests这样能保证安装到当前python命令对应的环境。安装后验证一下python -c import requests; print(requests.__version__)命令行里能看到版本号说明安装成功。很多爬虫脚本跑不起来不是代码问题而是库根本没装上或者装到了另一个Python环境里。验证这步能省下不少排查时间。2.2 七个请求方法背后的统一入口课件里列出Requests库的七个方法request、get、head、post、put、patch、delete。它们并不是七个独立实现而是同一套HTTP请求逻辑的便捷入口。requests.request()是基础方法其余6个都把它作为底层来构造Request对象。requests.request(method, url, **kwargs)中第一个参数是HTTP动词字符串比如GET、POST。所以requests.get(url, paramsNone, **kwargs)本质上就是requests.request(GET, url, paramsparams, **kwargs)。理解这个关系后遇到课件里没细讲的options方法你也可以用requests.request(OPTIONS, url)来发。2.3 requests.get()的参数结构requests.get(url, paramsNone, **kwargs)中url目标页面的链接必填。paramsURL额外参数字典或字节流格式可选。**kwargs12个控制访问的参数包括data、json、headers、cookies、auth、timeout、allow_redirects、proxies、verify、stream、cert等。其中params非常实用很多网站用URL查询参数区分页面内容。例如在整站搜索数据采集时直接把搜索词放进字典import requests url https://httpbin.org/get params {keyword: Python爬虫, page: 1} r requests.get(url, paramsparams) print(r.url)执行后r.url会打印出编码后的完整地址keyword参数会被自动进行URL编码。中文参数变成%E6%A3%80%E7%B4%A2之类的字符串这是HTTP标准规定的不需要手动处理。headers参数也很常用不少网站会校验User-Agent判断请求是否来自真实浏览器。常见做法是headers {User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)} r requests.get(url, headersheaders)后面做大规模采集时这个参数基本是每个请求都要带的。2.4 七种方法对照及适用场景方法名对应的HTTP动词典型场景requests.request()任意构造任意请求是全部方法的基石requests.get()GET获取HTML网页、开放接口requests.head()HEAD只拿响应头判断链接存活requests.post()POST表单登录、API提交数据requests.put()PUT覆盖更新服务器资源requests.patch()PATCH局部更新改一个字段requests.delete()DELETE删除资源一般少用实际爬虫中GET和POST覆盖绝大多数场景。GET传参靠URLPOST传参靠data或json。POST常用于模拟登录例如把账号密码打包成表单data {username: user, password: 123456} r requests.post(https://httpbin.org/post, datadata)这里data参数会自动被放进请求体并以application/x-www-form-urlencoded方式提交。如果调用的接口要求JSON格式改用json参数Requests会设置Content-Type: application/json并序列化字典。2.5 一个最小GET请求完整示例import requests url https://www.baidu.com r requests.get(url) print(r.status_code) # 200请求成功 print(r.text) # 响应内容的字符串形式这个例子演示了完整链路构造Request对象发送给服务器服务器返回Response对象。r.status_code是HTTP状态码200表示连接成功404表示页面不存在。拿到r.text之后就可以交给后续的信息提取环节了。注意r.text并不一定适合直接写入文件因为它依赖于r.encoding的解码结果。更稳妥的方式是先确认编码再决定用text还是content。这个点会在第四章细讲。3. Response对象拆解status_code、text、content的取舍3.1 Response对象里包含哪些信息requests.get()返回的不是普通字符串而是一个Response对象。它封装了服务器返回的所有数据包括状态码、响应头、响应体也保留了你请求时使用的Request信息。属性说明r.status_codeHTTP状态码200成功404失败r.text响应内容的字符串形式即URL对应的页面内容r.encoding从HTTP header中猜测的编码方式r.apparent_encoding从内容中分析出的编码方式r.content响应内容的二进制形式如果需要在日志里记录请求的是哪个地址可以通过r.request.url拿回原始的请求URL和参数。这在调试302跳转或参数拼接问题时非常好用。3.2 status_code的判定逻辑HTTP状态码分五类。2xx表示成功3xx表示重定向Requests会默认自动跟随4xx表示客户端错误典型的是404和4035xx表示服务器端错误比如502。课件里的表述是“200表示连接成功404表示失败”这个说法对应了最常见的两种情况。Requests不会因为状态码是404就自动抛异常必须手动检查if r.status_code 200: print(r.text[:100]) elif r.status_code 404: print(页面不存在)更推荐的做法是使用raise_for_status()状态码非2xx时直接抛出HTTPErrorimport requests url https://httpbin.org/status/404 r requests.get(url) r.raise_for_status() # 会抛出 requests.exceptions.HTTPError这个异常会被后面的try except捕获适合在遍历大量URL时统一处理失败请求而不用每个链接都写判断。3.3 r.text还是r.content按场景决定r.text是解码后的Python字符串适合解析HTML、JSON等文本型内容。r.content是原始字节适合下载图片、PDF、压缩包等二进制文件。import requests # 下载图片 r requests.get(https://httpbin.org/image/png) with open(image.png, wb) as f: f.write(r.content)对于文本页面如果r.text出现乱码大多是编码没设置对。这时可以用r.content拿到原始字节再用正确的编码解码。例如强制用UTF-8解码html r.content.decode(utf-8, errorsignore)errorsignore可以跳过无法解码的字节避免抛出异常。这种方式在批量抓取不规范的页面时很常见但会损失部分异常字符只适合对内容完整性要求不高的场景。3.4 响应体为JSON的处理数据采集经常遇到后端返回JSON而非HTML的情况。Requests内置了r.json()方法直接把响应体解析成Python字典或列表r requests.get(https://httpbin.org/json) data r.json() print(data[slideshow][title])r.json()使用json模块解析所以响应体必须是合法JSON否则会抛出ValueError。如果接口返回内容较大可以把解析后的数据直接写入文件import json with open(data.json, w, encodingutf-8) as f: json.dump(data, f, ensure_asciiFalse, indent2)ensure_asciiFalse保证中文以原样写入indent2让文件可读性更高。这个组合在保存采集结果时非常实用。3.5 用实例观察Response行为import requests r requests.get(https://www.baidu.com) print(r.status_code) # 200 print(r.encoding) # ISO-8859-1 print(r.apparent_encoding) # utf-8 print(len(r.text)) # 文本字符数 print(len(r.content)) # 字节数这段代码同时打印编码和长度能直观看出问题。如果r.text的字符数远小于r.content的字节数说明页面包含多字节字符而r.encoding没有正确识别。遇到这种情况下一步就应该处理编码而不是直接扔给解析库。4. 编码陷阱r.encoding与r.apparent_encoding怎么选4.1 HTTP响应头中的charset不总是可信浏览器能正常显示中文页面是因为浏览器会综合HTTP响应头、HTML标签中的meta charset以及字节内容做编码推断。Requests只看HTTP响应头里的Content-Type字段它把这个字段中charset的值赋给r.encoding。问题在于很多服务器没有在响应头里写清楚charset或者写了一个与实际内容不符的编码。抓中文站点时r.encoding经常被设置成ISO-8859-1这是一种单字节编码只能表示拉丁字母用它解码中文自然会乱码。这正是Requests入门阶段最常遇到的坑。4.2 复现一次乱码以百度首页为例看编码带来的影响import requests r requests.get(https://www.baidu.com) print(r.encoding) # ISO-8859-1 print(r.text[:100]) # 乱码 print(r.apparent_encoding) # utf-8执行后r.text的输出会是一堆无法阅读的符号。r.apparent_encoding返回的是基于页面内容分析出的编码通常更接近真实编码。它内部调用的是chardet库通过统计字节分布和字符频率来判断可能性最高的编码方式。4.3 修复方式用apparent_encoding覆盖encoding最简单的修复方式是让r.encoding跟随r.apparent_encodingimport requests r requests.get(https://www.baidu.com) r.encoding r.apparent_encoding print(r.text[:200])重新设置r.encoding后r.text会立刻按新编码重新解码。注意r.encoding影响的是r.text的解码结果不会影响r.content。如果你要写文件建议直接用r.content并手动指定文件编码with open(baidu.html, w, encodingutf-8) as f: f.write(r.content.decode(r.encoding, errorsignore))但要注意r.apparent_encoding不是万能的。内容太少、内容里夹杂大量ASCII字符、或者页面同时出现多种语言时它可能给出错误判断。遇到这种情况需要手动指定编码。4.4 手动指定编码的场景国内老门户网站常用GBK或GB2312。apparent_encoding有时会判断成GB2312但页面里存在生僻字GB2312会解码失败。这时可以统一使用gb18030它是GBK的超集兼容性最好r.encoding gb18030 print(r.text[:200])手动指定后最好先打印一部分内容确认显示正常再进入后续解析。还有一种更精细的方法是从HTML源码中提取meta charset...标签内容用它覆盖r.encoding。常见做法是用正则表达式import re meta re.search(rmeta[^]charset[\]?([\w-]), r.text, re.I) if meta: r.encoding meta.group(1)不过这种方式的适用前提是HTML已经能被正确解码一旦前面乱码meta提取也会失败。所以实际爬虫中我会先优先使用apparent_encoding失败后再用正则看charset最后才手动固定。4.5 三种编码处理方式对比处理方式原理适用场景局限默认使用r.encoding读取header中的charsetheader准确页面为纯英文中文站点常误判为ISO-8859-1r.apparent_encoding从内容分析编码中文站点、header缺失少量内容时可能误判手动指定编码人工确认charset值老站、复杂页面、分析出错需要人工干预不能通用判断编码是否正确的通用方法很简单打印r.text前200个字符如果出现或不合理符号基本就是编码问题。不要等到解析完数据才发现字段是乱的那样排错成本高很多。5. 异常处理与进阶写一个带超时和重试的爬虫5.1 网络请求常见的异常类型数据采集不是每次请求都能成功。域名解析失败、连接被重置、服务器超时都会导致程序中断。Requests把异常统一封装在requests.exceptions下异常类触发场景requests.ConnectionError网络连接失败例如DNS解析错误、连接被拒requests.Timeout请求超时服务器没有在指定时间内响应requests.TooManyRedirects重定向次数超过最大限制requests.HTTPError状态码不是2xx且调用了raise_for_status()requests.RequestException以上所有异常的基类捕获时不必逐个写except基础用法是捕获RequestException再打印具体类型。import requests try: r requests.get(https://httpbin.org/delay/3, timeout5) r.raise_for_status() except requests.RequestException as e: print(f请求失败: {e})timeout5表示5秒内没有响应就抛异常避免程序卡死。raise_for_status()把4xx、5xx转化为异常。这样写之后任何环节出错都会被捕获。5.2 带超时、重试和编码修正的请求函数一个能在批量采集中稳定运行的函数至少要有三件事超时控制、失败重试、编码修正。下面这个fetch函数可以当作模板import time import requests def fetch(url, timeout10, max_retry3): headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 } for attempt in range(max_retry): try: r requests.get(url, headersheaders, timeouttimeout) r.raise_for_status() if charset not in r.headers.get(Content-Type, ).lower(): r.encoding r.apparent_encoding return r except requests.RequestException as e: print(f第 {attempt 1} 次请求失败: {e}) if attempt max_retry - 1: time.sleep(2) return None逻辑说明headers模拟浏览器User-Agent降低被反爬拦截的概率timeout防止请求挂起max_retry控制重试次数每次失败后休眠2秒再试避免紧贴重试加重服务器压力。请求成功后再判断响应头里有没有charset如果没有就用apparent_encoding修正编码。最后返回r调用方可以做进一步的解析。使用时这样调用r fetch(https://www.baidu.com) if r is not None: print(r.status_code) print(r.text[:100]) else: print(三次重试后依然失败)如果只抓一个页面看不出重试的价值。在批量爬取排行榜、新闻列表时单页失败跳过总比整个程序中断强。后续的BeautifulSoup解析、正则表达式提取都会基于这个函数返回的Response对象展开。抓取之前先跑一遍这个函数确认编码和状态码都正常再上完整逻辑能省下大量排错时间。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价