采用库来设置请求头时, 要借助参数传入字典, 这种办法适用于GET请求, 也适用于POST请求, 能够自定义User - Agent、 - Type等字段, 以此来模拟浏览器, 还能传递认证信息, 或者指定数据格式;运用对象可达成请求头持久化, 能自动管理, 并且能复用TCP连接, 从而提升效率以及代码可维护性;在实际应用里, 要留意请求头字段准确性, 防止敏感信息明文传输, 并且要结合API文档正确配置内容类型与认证方式, 保证请求合法且有效。
在中使用
requests库设置请求头()非常直接,核心就是通过
headers参数传递一个字典。这个字典的键是请求头的名称(例如
User-AgentContent-Type首先, 存在一个值, 该值是与之对应的字符串。随后, 不管你发起的是GET请求, 还是POST请求, 反正这个方法整体都是通用的。并且, 通过这个方法, 得以让你精细地去控制发送至服务器的HTTP请求里面的元数据。
requests中自定义请求头,其实就是给
get()post()等方法传入一个
headers有某一项参数, 此项参数是在期待放置一个字典, 这个字典里的键是HTTP请求头里的字段名, 而其值是针对该字段的对应内容, 是这样的情况。
import requests # 定义你想要发送的请求头 custom_headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124124 Safari/537.36', 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8', 'Referer': 'https://www.google.com/' # 模拟从Google跳转过来 } url = 'http://httpbin.org/headers' # 一个测试URL,会返回你发送的请求头 # 发送GET请求并带上自定义请求头 response_get = requests.get(url, headers=custom_headers) print("GET 请求头响应:") print(response_get.json()) # 发送POST请求并带上自定义请求头和一些数据 post_data = {'key': 'value'} response_post = requests.post(url, headers=custom_headers, data=post_data) print("\nPOST 请求头响应:") print(response_post.json())这段代码展示了最基本的用法。
custom_headers添加到HTTP请求头部的是字典里的每一个键值对, 服务器收到请求后, 便能够识别这些自定义信息, 这在诸如模拟浏览器行为之类, 传递认证令牌、指定内容类型等许多场景底下都极具用处。
为什么说自定义请求头在某些场景下是不可或缺的?
自定义请求头的重要意义, 常常凸显于跟服务器的“交流”当中。我们都清楚, HTTP协议不单单是传输数据,它还负载了众多有关请求和响应的元信息, 这些信息借助请求头和响应头来进行传递。依我看, 存在几个场景是格外需要我们去主动设定请求头的:
起先, 对浏览器行为予以模拟, 好多网站因要防范爬虫亦或是辨别客户端类型, 故而会进行检查。
User-Agent头。默认情况下,
requests库会发送一个类似
python-requests/2.x.xUser-Agent在好多的网站那儿看作 , 这名为“非正常访问” , 内容返回不完整是较为轻微的情况 , 严重些的话会径直拒绝请求 , 甚者还会对IP进行封禁。当下这个时候 , 惯例来说我们会去设置一个主流浏览器的。
User-Agent来“伪装”自己。有时,甚至还需要设置
Accept-Language来指定期望的语言,或者
Referer采用模拟方式, 是从某一个页面跳转过来的, 如此这般能够使得我们那种请求看上去更为天然, 更“自然”。
其次, 存在API认证。当下众多API都运用基于Token的认证方式, 诸如OAuth 2.0的Token。客户端要把这个Token放置在。
Authorization请求头被发送给服务器, 如此服务器才能够验证请求的合法性, 要是没有这个头, 或者头内容不正确, 那么API调用就会失败, 这差不多是所有需要登录后才可以访问的API的标配。
再者, 存在内容协商以及数据提交事宜, 当我们有着向服务器提交JSON这类数据的需求时, 同时对于要求提交XML数据的情况而言, 一般来讲都需要进行设置。
Content-Type头来告诉服务器请求体的数据格式,比如
application/jsonapplication/xml对于服务器而言, 如果其期望的是JSON格式, 然而你却并未设置这个头, 或者将其设置成了错误的类型, 那么服务器便有可能无法正确地解析你的请求体, 进而致使数据提交失败。同样地。
Accept头可以告诉服务器我们期望接收什么类型的数据。
最为终了的是, 缓存开展控制行为以及条件性请求举措。尽管并非常常会被运用到, 然而在某些较为高级的场景状况之下, 我们有可能是需要借助于。
If-None-MatchIf-Modified-Since等待头部前来配合服务器方面所具备的缓存机制, 以此达成条件式请求之目的, 进而避免出现重复传输那些并未被修改的数据的情况, 最终实现提高效率的结果。
能够讲, 自定义请求头属于我们在网络请求里跟服务器开展“较为高级沟通”的必需工具, 它让我们可以更精准精微地把控请求行为, 进而去适配各类繁杂的网络环境以及服务器的要求。
使用.管理请求头有什么优势?
于真实的开发里面, 特别是当咱们要朝着同一个服务器去发起一连串的请求之际, 运用。
requests.Session由对象去对请求头展开管理, 能够带来十分显著的优势, 这并非仅仅局限于代码组织层面所具备的便利, 更是与性能以及请求行为所呈现出的一致性相关联。
最为直接的优势在于, 请求头具备持久性。要是你于多个请求期间, 需要去发送相同的请求头, 例如认证Token。
User-Agent),而不用
Session,你就得在每个
requests.get()requests.post()调用中重复传入
headers字典。这不仅冗余,而且容易出错。
Session对象允许你设置一次默认的请求头,之后通过该
Session无论何时, 只要是对象所发出的任何请求, 无一例外都会自动地带上这些头, 当然得以你没有在无论哪一个请求当中特意去覆盖它们为前提条件。
-HTTP库
-1.7.0HTTP库
下载
import requests # 创建一个Session对象 session = requests.Session() # 为Session设置默认请求头 session.headers.update({ 'User-Agent': 'MyCustomApp/1.0', 'Authorization': 'Bearer YOUR_AUTH_TOKEN_HERE', 'Accept': 'application/json' }) # 通过Session发起请求,这些请求会自动带上上述headers response1 = session.get('http://httpbin.org/headers') print("Session 请求 1 响应:") print(response1.json()) # 即使是另一个请求,也依然带上了Session的headers response2 = session.post('http://httpbin.org/headers', data={'foo': 'bar'}) print("\nSession 请求 2 响应:") print(response2.json()) # 你也可以在单个请求中覆盖Session的默认头 response3 = session.get('http://httpbin.org/headers', headers={'User-Agent': 'TemporaryAgent/1.0'}) print("\nSession 请求 3 (覆盖User-Agent) 响应:") print(response3.json())除了请求头,
Session存在着这样一种情况, 对象具备自动处理的能力, 它能够在会话的整个生命周期里, 将从服务器那儿接收到的内容,自动地去进行存储以及发送, 而这一点对于那些有着维护登录状态需求的网站爬取行为或者 API 交互而言, 显然是极其关键重要的, 并且你无须亲自手动去进行解析。
Set-Cookie响应头并将其添加到后续请求的
Cookie请求头中,
Session会帮你搞定这一切。
此外,
Session对象还提供了TCP连接复用的性能优势。当通过同一个
Session对象向同一个域名发起多个请求时,
requests底层的 TCP 连接将会被尝试复用, 这就意为着, 每次请求之时, 建立新连接的开销被减少了, 比如说 TCP 三次握手以及 TLS 握手, 进而提高了请求速度以及效率, 特别是在高并发或者长连接场景之下。
总的来说,
requests.Session这是处理一系列彼此相关请求的有效工具, 它将代码做了简化, 使得效率得以提高, 还让请求行为愈发具备一致性那般, 是编写健壮网络客户端代码时值得推荐的一种合理做法。
设置请求头时常遇到的挑战和一些实践建议
在设置
requests请求那一头的时候, 尽管概念是简单的, 然而在实际去操作的情形当中, 依旧是会碰到一些挑战的, 而且还存在一些值得留意的实践方面要点的。
一个常常会碰到的挑战, 是请求头字段的精确性。HTTP请求头字段的名称, 虽说一般情况下是大小写不敏感的, 然而为了代码所具备的可读性, 以及和规范达成一致性, 最好还是去遵循标准的驼峰命名法(如)
User-AgentContent-Type)。更重要的是,字段值必须符合服务器的预期。比如,
Content-Type的值如果是
application/json, 那么你所提交的请求体必然得是合乎规定的JSON字符串才行。要是内容并非匹配的, 服务器就会返回诸如400 Bad这类的错误。我有过那样的经历, 只因一个字符存在着差异, 致使API接口始终处于报错状态, 花费了半天时间去排查才发觉原来是。
Content-Type写成了
application/json;charset=UTF-8,而服务器只认
application/json另一个需要注意的点是默认请求头的覆盖与合并。
requests库本身会发送一些默认的请求头,例如
Connection: keep-alive。当你传入自定义
headers字典时,如果你的字典中包含了
requests设若存在默认会予以发送的同名字段, 那么你的值将会把默认值给覆盖掉。要是你的字典当中并不具备, 默认值便会保留下来。此般情形通常属于期望达成的行为, 然而有时候有可能引致意外状况。比如说, 要是你打算在已然具有的。
User-Agent基础上追加一些信息,而不是完全替换,就需要先获取默认的
User-Agent再进行拼接,但这通常不建议,直接完全替换更清晰。
对于
User-Agent的设置,虽然模拟浏览器能解决很多问题,但过度依赖单一的
User-Agent也可能导致IP被封禁。一些更高级的反爬机制会检测
User-Agent跟请求模式, 像请求频率、请求路径等, 是不是相匹配。于更为复杂的场景当中, 你也许得去维护一个。
User-Agent池,并随机选择使用,甚至模拟更完整的浏览器指纹(如
AcceptAccept-EncodingAccept-Language诸如此类一系列的头)。然而, 这已然跨越了单纯进行设置请求头的范围界限, 是归属于反爬取策略的范畴了。
安全方面的考量同样是不能被忽视掉的。当在请求头里传递敏感类信息, 像认证Token这种的时候, 一定要保证连接属于HTTPS加密的状态。HTTP协议是采用明文来进行传输的, 要是借助HTTP去发送认证信息, 那么这些信息在网络传输的进程当中是有可能被截获的。除此之外, 不要在客户端代码里面对敏感的API密钥或者认证Token进行硬编码, 而是应当借助环境变量、配置文件或者更加安全的密钥管理服务去获取。
最后, 是错误处理, 出现服务器返回非2xx状态码的情况时, 用以检查响应头以及响应体里错误信息的行为, 通常能够助力你迅速将问题位置找出来, 许多API在出现错误响应时会把相关内容包含进去。
Content-Type: application/json且于JSON体里给出详尽的错误描述, 要学会借助这些信息, 而非盲目地去改动请求头, 如此便能大幅提高调试效率。
不管怎样, 进行请求头的设置, 这是一项表面上看着简单但实际上得要审慎周密去考虑衡量的工作, 只有要去明白HTTP协议规范, 再结合服务器的API文档, 同时还要留意实践过程当中那些常见的容易出错的地方, 这样才能够使得我们的网络请求变得更有效率且更加稳定。