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(获取响应的内容)
通过上述的这些基本方法再加上一些数据的存储技术,就可以实现对数据的抓取了