mitmproxy -py脚本编写

原文链接 https://blog.csdn.net/qianwenjun_19930314/article/details/88227335

1、脚本编写的两个条件

​ 1.1 编写一个 py 文件供 mitmproxy 加载,文件中定义了若干函数,这些函数实现了某些 mitmproxy 提供的事件,mitmproxy 会在某个事件发生时调用对应的函数
​ 1.2 编写一个 py 文件供 mitmproxy 加载,文件定义了【变量 addons】,addons 是个数组,每个元素是一个类实例,这些类有若干方法,这些方法实现了某些 mitmproxy 提供的事件,mitmproxy 会在某个事件发生时调用对应的方法。这些类,称为一个个 addon。
基本模板为

from mitmproxy import http, ctx
import json

class xxx:
	def xxx:
	def xxx

addons = [
	xxx() //类名的加载,也可以定义多个类,然后以数组的形式添加,进行加载
]
 1.3 针对 HTTP 生命周期
def http_connect(self, flow: mitmproxy.http.HTTPFlow):
 

(Called when) 收到了来自客户端的 HTTP CONNECT 请求。在 flow 上设置非 2xx 响应将返回该响应并断开连接。CONNECT 不是常用的 HTTP 请求方法,目的是与服务器建立代理连接,仅是 client 与 proxy 的之间的交流,所以 CONNECT 请求不会触发 request、response 等其他常规的 HTTP 事件。

def requestheaders(self, flow: mitmproxy.http.HTTPFlow):
 

(Called when) 来自客户端的 HTTP 请求的头部被成功读取。此时 flow 中的 request 的 body 是空的。

def request(self, flow: mitmproxy.http.HTTPFlow):
 

(Called when) 来自客户端的 HTTP 请求被成功完整读取。

def responseheaders(self, flow: mitmproxy.http.HTTPFlow):
 

(Called when) 来自服务端的 HTTP 响应的头部被成功读取。此时 flow 中的 response 的 body 是空的。

def response(self, flow: mitmproxy.http.HTTPFlow):
 

(Called when) 来自服务端端的 HTTP 响应被成功完整读取。

def error(self, flow: mitmproxy.http.HTTPFlow):
 

(Called when) 发生了一个 HTTP 错误。比如无效的服务端响应、连接断开等。注意与“有效的 HTTP 错误返回”不是一回事,后者是一个正确的服务端响应,只是 HTTP code 表示错误而已。

2 、脚本函数编写

​ 2.1 替换请求

from mitmproxy import ctx, http
import json

class Modify:

 	    def request(self, flow):
 	    	#替换请求链接
        	if flow.request.url.startswith("http://spay1.shuqireader.com/api/ios/info?method=priceList"):
            #有分享
            flow.request.url = "http://activity.x.xxx.xx.cn/share?id=2653&useShare=1"
            ctx.log.info("修改链接")
        		
         
addons = [
	Modify()
]

​ 2.2 修改cookies

from mitmproxy import ctx, http
import json

class Modify:

 	 def request(self, flow):
         #替换cookie,两种匹配请求链接的方式
        # if flow.request.host == "xxx.x.xxx.com.cn":
        if flow.request.url.startswith("https://xxx.x.xxx.com.cn/"):
            print(flow.request.url)
            print(flow.request.cookies)
            flow.request.cookies["_testCookie1"] = "xxx-91"
            flow.request.cookies["testCookie2"] = "123"

            req = flow.request.cookies["_testCookie1"]
            ctx.log.info(req)

addons = [
	Modify()
]

​ 2.3 修改请求参数

from mitmproxy import ctx, http
import json

class Modify:
 	 def request(self, flow):
                if flow.request.url.startswith("http://xxx.x.xxx.com.cn/customActivity/bookcode/doJoin"):
            ctx.log.info("modify request form")
            if flow.request.urlencoded_form:
                flow.request.urlencoded_form["code"] = "11111"
            else:
                flow.request.urlencoded_form = [
                    ("actId", "20727"),("nick","name")
                ]
         
addons = [
	Modify()
]

​ 2.4 修改相应状态

from mitmproxy import ctx, http
import json

class Modify:
	def response(self, flow):
		 if flow.request.url.startswith("http://baidu.com.cn"):
            flow.response = http.HTTPResponse.make(404)
            ctx.log.info("modify status code")

 addons = [
	Modify()
]

​ 2.5 修改响应体

from mitmproxy import ctx, http
import json

class Modify:
	def response(self, flow):
        if flow.request.url.startswith("https://xxx.x.xxx.com.cn/activityInfo/getPrizeInfo=="):
       		 //获取响应的json字符串,转成python对象进行解析和修改
            response = json.loads(flow.response.get_text())
            response['limitCount'] = 1
            //修改完成后,奖python对象转成json字符串,set进请求的响应体重发送给客户端
            flow.response.set_text(json.dumps(response))
            ctx.log.info('modify limitCount')

 addons = [
	Modify()
]

​ 2.6 读取json文件中字符串返回客户端

from mitmproxy import ctx, http
import json

class Modify:
	def response(self, flow):
        if flow.request.url.startswith("https://xxx.x.xxx.com.cn/activityInfo/getPrizeInfo=="):
        	//读取文件,在当前文件路径下执行脚本,否则需要写文件的绝对路径;不然会找不到该json文件
       		 with open('getStatus.json','rb') as f:
       		 	//从json文件中读取数据成python对象
                res = json.load(f)
            //将读取的python对象转成json字符串发送给客户端
            flow.response.set_text(json.dumps(res))
            ctx.log.info("modify order status")

 addons = [
	Modify()
]
2.7 Request的一些方法:
get_query():得到请求的url的参数,被存放成了字典。
set_query(odict):设置请求的url参数,参数是字典。 
get_url():请求的url。 set_url(url):设置# url的域。 
get_cookies():得到请求的cookie。 headers:请求的header的字典。 
content:请求的内容,如果请求时post,那么content就是指代post的参数。 
Response的一些方法如下: Headers:返回的header的字典。 
Code:返回数据包的状态,比如200,301之类的状态。 
Httpversion:http版本。

3、脚本加载

mitmdump -s script.py

4、插件脚本的基本使用

4.1 日志输出,
日志输出
调用ctx模块:from mitmproxy import ctx引入,然后通过ctx.log.xxx输出:
ctx.log.info(显示白色)
ctx.log.wran(显示黄色)
ctx.log.error(显示红色)
4.2 参数flow,我们可以通过flow.request属性获取当前请求,
通过flow.request.xxx获取相应属性,如:
flow.request.url(请求的url地址)
flow.request.headers(请求头信息)
flow.request.cookies(cookies信息)
flow.request.host(host标头值)
flow.request.method(请求方法)
flow.request.port(请求的端口)
flow.request.scheme(请求协议)
更多内容请查看mitmproxy的API接口
不仅可以获取相应的值,我们也可以对其值进行修改:

flow.request.url = 新的url

# 通过这种方式我们就可以进行修改和伪造请求,通过此方式我们知道,在日常上网的过程中,有时候我们输入的url是正确的,但是页面内容却与我们所需要看到的不同, 有的钓鱼网站可能是通过此方式进行改变网页信息的,因此我们在日常上网过程中应注意网络安全。
# 在日常爬虫过程中,我们可以通过修改cookies和添加代理的方式来规避网站的反爬。

4.3 参数flow,我们可以通过flow.response属性获取当前请求

# 对于爬虫来说,我们更想获取其响应的内容,对于响应来说,我们采用response()方法来获取响应的内容:
通过flow.response.xxx获取相应属性,如:
flow.repsonse.status_code(获取响应的状态码)
flow.repsonse.headers(获取响应头信息)
flow.repsonse.cookies(获取响应的cookies信息)
flow.repsonse.text(获取响应的内容)
通过上述的这些基本方法再加上一些数据的存储技术,就可以实现对数据的抓取了
posted @ 2021-01-17 12:54  旁人怎会懂  阅读(2504)  评论(1编辑  收藏  举报