MITMProxy:智能URL替换

2 投票
1 回答
2629 浏览
提问于 2025-04-18 14:15

我们使用一个自定义的抓取工具,它需要针对不同语言的网站进行抓取(这是架构上的限制)。比如说像 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)

撰写回答