MITMProxy:智能URL替换
我们使用一个自定义的抓取工具,它需要针对不同语言的网站进行抓取(这是架构上的限制)。比如说像 site1.co.uk、site1.es、site1.de 这样的。
但是我们需要解析一个有多种语言的网站,这些语言通过网址来区分,比如 site2.com/en、site2.com/de、site2.com/es 等等。
我想到了 MITMProxy:我可以通过这种方式重定向所有请求:
en.site2.com/* --> site2.com/en
de.site2.com/* --> site2.com/de
...
我写了一个小脚本,简单地处理网址并进行重写:
class MyMaster(flow.FlowMaster):
def handle_request(self, r):
url = r.get_url()
# replace URLs
if 'blabla' in url:
r.set_url(url.replace('something', 'another'))
但是目标主机会生成一个301重定向,响应中会告诉我“页面已移动到这里”,并给出指向 site2.com/en 的链接。
当我玩弄网址重写的时候,它是有效的,比如 site2.com/en 转到 site2.com/de。但对于不同的主机(更准确地说是子域名和主域名),这个方法就不管用了。
我尝试在上面的 handle_request 方法中替换 Host 头:
for key in r.headers.keys():
if key.lower() == 'host':
r.headers[key] = ['site2.com']
我还尝试替换 Referrer,但这些都没有帮助。
我该如何最终将请求从子域名伪装成主域名呢?如果生成 HTTP(s) 客户端警告也没关系,因为我们需要这个来抓取数据(而且那里的警告可以关闭),而不是在真实浏览器中。
谢谢!
1 个回答
1
你需要替换掉响应的内容,并且只用几个字段来设置头部信息。打开一个新的连接到重定向的URL,然后构建你的响应:
def handle_request(self, flow):
newUrl = <new-url>
retryCount = 3
newResponse = None
while True:
try:
newResponse = requests.get(newUrl) # import requests
except:
if retryCount == 0:
print 'Cannot reach new url ' + newUrl
traceback.print_exc() # import traceback
return
retryCount -= 1
continue
break
responseHeaders = Headers() # from netlib.http import Headers
if 'Date' in newResponse.headers:
responseHeaders['Date'] = str(newResponse.headers['Date'])
if 'Connection' in newResponse.headers:
responseHeaders['Connection'] = str(newResponse.headers['Connection'])
if 'Content-Type' in newResponse.headers:
responseHeaders['Content-Type'] = str(newResponse.headers['Content-Type'])
if 'Content-Length' in newResponse.headers:
responseHeaders['Content-Length'] = str(newResponse.headers['Content-Length'])
if 'Content-Encoding' in newResponse.headers:
responseHeaders['Content-Encoding'] = str(inetResponse.headers['Content-Encoding'])
response = HTTPResponse( # from libmproxy.models import HTTPResponse
http_version='HTTP/1.1',
status_code=200,
reason='OK',
headers=responseHeaders,
content=newResponse.content)
flow.reply(response)