2

我们使用一个自定义的抓取工具,它必须为一种语言使用一个单独的网站(这是一个架构限制)。像 site1.co.uk、site1.es、site1.de 等。

但是我们需要解析一个有多种语言的网站,用 url 分隔——比如 site2.com/en、site2.com/de、site2.com/es 等等。

我想到了 MITMProxy:我可以通过这种方式重定向所有请求:

en.site2.com/* --> site2.com/en
de.site2.com/* --> site2.com/de
...

我写了一个小脚本,它只需要 URL 并重写它们:

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 的链接

当我玩 URL 重写时,它起作用了,即 site2.com/en --> site2.com/de。但是对于不同的主机(准确地说是子域和根域),它不起作用。

我尝试从上面替换 handle_request 方法中的 Host 标头:

for key in r.headers.keys():
        if key.lower() == 'host':
            r.headers[key] = ['site2.com']

我也尝试替换推荐人 - 所有这些都没有帮助。

我怎样才能最终将该请求从子域欺骗到主域?如果它生成一个 HTTP(s) 客户端警告,那没关系,因为我们需要它用于爬虫(并且可以关闭那里的警告),而不是真正的浏览器。

谢谢!

4

1 回答 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)
于 2016-01-28T10:06:59.440 回答