Python/Django中的网络代理?

6 投票
5 回答
13661 浏览
提问于 2025-04-17 08:19

我需要一个代理服务器,充当中介来获取图片。举个例子,我的服务器请求 domain1.com/?url=domain2.com/image.png,然后 domain1.com 的服务器会通过它自己返回 domain2.com/image.png 的数据。

简单来说,我想把我想要获取的 URL 传给这个代理,代理服务器再把这个资源返回给我。

有没有什么建议可以让我开始做这个?

我需要一些非常简单易用的东西,因为我对这些都很陌生。

我找到的大部分用 Python 和/或 Django 的解决方案,代理的作用像是一个“翻译器”,也就是说 domain1.com/image.png 会翻译成 domain2.com/image.png,这显然不是我想要的。

我现在有以下代码,但获取图片时数据会变得很混乱:

import httplib2
from django.conf.urls.defaults import *
from django.http import HttpResponse

def proxy(request, url):
    conn = httplib2.Http()
    if request.method == "GET":
        url = request.GET['url']
        resp, content = conn.request(url, request.method)
        return HttpResponse(content)

5 个回答

3

如果你需要比我之前的回答更完整的内容,可以使用这个类:

import requests
from django.http import StreamingHttpResponse
from wsgiref.util import is_hop_by_hop


class ProxyHttpResponse(StreamingHttpResponse):

    def __init__(self, url, headers=None, **kwargs):
        upstream = requests.get(url, stream=True, headers=headers)

        kwargs.setdefault('content_type', upstream.headers.get('content-type'))
        kwargs.setdefault('status', upstream.status_code)
        kwargs.setdefault('reason', upstream.reason)

        super().__init__(upstream.raw, **kwargs)

        for name, value in upstream.headers.items():
            if not is_hop_by_hop(name):
                self[name] = value

你可以这样使用这个类:

def my_proxy_view(request):
    url = request.GET['url']
    return ProxyHttpResponse(url, headers=request.headers)

这个版本的好处是你可以在多个视图中重复使用它。此外,它会转发所有的头信息,你也可以很方便地扩展它,添加或排除一些其他的头信息。

10

这是一个非常简单的Django代理视图,使用了requests库和StreamingHttpResponse

import requests
from django.http import StreamingHttpResponse

def my_proxy_view(request):
    url = request.GET['url']
    response = requests.get(url, stream=True)
    return StreamingHttpResponse(
        response.raw,
        content_type=response.headers.get('content-type'),
        status=response.status_code,
        reason=response.reason)

这种方法的好处是,你不需要在把内容传给客户端之前,把整个文件都加载到内存中。

正如你所看到的,它会转发一些响应头。根据你的需求,你可能还想转发请求头;比如:

response = requests.get(url, stream=True,
    headers={'user-agent': request.headers.get('user-agent')})
12

这个问题虽然老旧,但为了将来搜索的朋友,我觉得这就是你们想要的:

# proxies the google logo
def test(request):
    url = "http://www.google.com/logos/classicplus.png"
    req = urllib2.Request(url)
    response = urllib2.urlopen(req)
    return HttpResponse(response.read(), mimetype="image/png")

撰写回答