python requests爬虫如何print http raw请求?
1、前言
hello,各位码友,最近冷空气有点飕飕的,可得注意防寒,穿秋裤出来暖场,千万别取暖靠抖了。前面几篇咱们一直在selenium系列,咱们今天讨论一点其他的。
进入正题。大家一般都使用python的requests库进行爬虫开发,在很多情况下,我们代码写好了,运行起来总是得不到想要的结果,要么是headers字典里面少加了点特定的键值,要么是忘了带cookie,还有就干脆发送的数据body或者query string有问题。
2、问题
我们的问题在于如何记录原始的http请求,以便于我们知道实际发送给web服务器的http报文内容? 当然大家可以说在开发的时候,用fiddler或者charles抓下包,对比一下手动请求少了那些东西不就得了,但是要是在生产环境下出现问题了呢? 咱们不可能在生产环境下也时刻挂着抓包软件吧?今天我们就来介绍一种解决方案。
3、解决方案
对于通过requests开发的爬虫代码来说,它最终都会调用更下层的发送报文的函数,我们只需要在它发送http报文之前,把原始的报文格式记录下来就能实现我们的目的。
先直接看patch代码,对于python3和python2来说patch的位置不一样,下面的代码考虑了两个版本的情况。
import sys
if sys.version>'3':
from urllib3.packages.six.moves import http_client as httplib
else:
import httplib
def patch_send():
old_send= httplib.HTTPConnection.send
def new_send( self, data ):
with open("requests.log","ab") as f:
f.write(data)
return old_send(self, data)
httplib.HTTPConnection.send= new_send
以上代码,定义了一个patch_send函数在做整个操作: - 1、在函数内部我们定义一个old_send函数相当于保持对原本的send函数对象的”引用“。 - 2、定义一个new_send函数,替换掉原生的http发送报文函数,在发送报文之前,我们先把报文写入本地的日志,然后再调用保存的old_send
我们实际调用requests访问www.baidu.com:
def get_baidu():
import requests
response = requests.get("http://www.baidu.com", headers={
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36"})
def main():
patch_send()
get_baidu()
if __name__ == "__main__":
main()
测试结果,我们看看requests.log这个文件:
我们发现日志里为记录两个一样的http报文请求,为什么会有两个?
原因很简单,因为访问的http后,会跳转到https的baidu.com所以有两次请求。
防止失联,关注微信公众号:码道工程。
请先登陆 或 注册