使用动态代理IP返回Response [407]

本文介绍了一个关于代理IP使用中的常见问题:为何代理返回Response[407],并详细解析了如何通过调整代码逻辑来区分代理认证失败与目标网站的状态码问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代理返回Response [407]


快代理工程师小哥在进行技术支持&工单处理的过程中经常会遇到一些用户有相同的问题。所以我们准备将一些在使用快代理产品中的一些经典问题进行经验总结,帮助到更多人使用代理IP。本文所有内容均来自快代理工程师真实的客户技术支持。

客户问题

使用产品类型:

私密代理集中提取
在这里插入图片描述

问题描述:

程序运行的过程中总是有少部分请求拿不到任何响应,服务器没有任何响应,现象和最开始没有使用用户名密码一样。怀疑是快代理的代理IP用户认证是有问题的。

技术支持流程

0x01 排除产品问题
首先还是老样子,工程师编写脚本使用用户订单下的代理IP,运行了一段时间后问题并没有出现407 Proxy Authentication Required的情况。

0x02 询问代码&分析问题
但是用户这边是拿出了详细的程序运行日志,统计确实是存在没有任何响应的数据记录,于是我们向用户要来了代码。粗略查看后,用户是使用Python的Requests框架配合多线程进行了二次封装。经过一段时间的调试与排查,我在Requests的返回值里面发现了蹊跷:用户对于每次请求的response都会进行一次布尔运算。

代码如下:

#!/usr/bin/python
# coding:utf-8
import requests
r = None
proxy_ip = "39.97.170.201:16818"
proxies = {
    "http": "http://%(proxy)s/" % {"proxy": proxy_ip},
    "https": "http://%(proxy)s/" % {"proxy": proxy_ip}
}
try:
    r = requests.get("http://www.baidu.com/", proxies=proxies)
    print r
except Exception, e:
    print e
if r:
    print "True"
else:
    print "False"
<Response [407]>
False

使用一台没有配置白名单IP的电脑,填写上代理IP运行此程序你会发现:

为什么没有输出True?按照常理来说,程序运行并没有出现异常,r此时是请求完成后的返回值,只要返回值不是零值就能够匹配到True的。但是为什么返回的<Response [407]>就会引发if判断异常呢?

> type(r)
> requests.models.Response

查看Requests关于Response代码:
•Response对象含有了__bool__魔法方法的处理,对象进行布尔运算时,这个魔法函数会被调用。
•Response对象的布尔值取决于self.ok。
•在HTTP状态码为400-500或者是500-600的范围内时,self.ok都为False,其余为True。

class Response(object):
    """The :class:`Response <Response>` object, which contains a
    server's response to an HTTP request.
    """
    __attrs__ = [
        '_content', 'status_code', 'headers', 'url', 'history',
        'encoding', 'reason', 'cookies', 'elapsed', 'request'
    ]
    def __init__(self):
        self._content = False
        self._content_consumed = False
        self._next = None
        #: Integer Code of responded HTTP Status, e.g. 404 or 200.
        self.status_code = None
        
    def __repr__(self):
        return '<Response [%s]>' % (self.status_code)
    def __bool__(self):
        """Returns True if :attr:`status_code` is less than 400.
        This attribute checks if the status code of the response is between
        400 and 600 to see if there was a client error or a server error. If
        the status code, is between 200 and 400, this will return True. This
        is **not** a check to see if the response code is ``200 OK``.
        """
        return self.ok


    @property
    def ok(self):
        """Returns True if :attr:`status_code` is less than 400, False if not.
        This attribute checks if the status code of the response is between
        400 and 600 to see if there was a client error or a server error. If
        the status code is between 200 and 400, this will return True. This
        is **not** a check to see if the response code is ``200 OK``.
        """
        try:
            self.raise_for_status()
        except HTTPError:
            return False
        return True
      
    def raise_for_status(self):
        """Raises :class:`HTTPError`, if one occurred."""
        http_error_msg = ''
        if isinstance(self.reason, bytes):
            # We attempt to decode utf-8 first because some servers
            # choose to localize their reason strings. If the string
            # isn't utf-8, we fall back to iso-8859-1 for all other
            # encodings. (See PR #3538)
            try:
                reason = self.reason.decode('utf-8')
            except UnicodeDecodeError:
                reason = self.reason.decode('iso-8859-1')
        else:
            reason = self.reason
        if 400 <= self.status_code < 500:
            http_error_msg = u'%s Client Error: %s for url: %s' % (self.status_code, reason, self.url)
        elif 500 <= self.status_code < 600:
            http_error_msg = u'%s Server Error: %s for url: %s' % (self.status_code, reason, self.url)
        if http_error_msg:
            raise HTTPError(http_error_msg, response=self)
            
        ......      

结论

用户最初没有使用用户名密码进行认证时,代理返回<Response [407]>,随后用户带上了用户名密码,程序正常跑起来。

但是访问的URL中有一部分失效链接或者当时目标网站不稳定等等其他因素,拿到了<Response [404]>,<Response [502]>这样的状态码。

由于Requests框架对与400-600状态码响应进行布尔操作都会返回False,跟之前代理未认证返回的<Response [407]>出现的现象一样,于是误以为是快代理的代理IP出现了问题。

在和用户解释了原因后,用户随即修改代码,通过HTTP状态码来判断代理请求是否成功,完美解决了这个问题。

获取更多经验好文
在这里插入图片描述

### 解决方案 当使用IP代理时遇到HTTP 405 Method Not Allowed错误,通常是因为目标Web服务器配置不允许所使用的HTTP方法。为了处理这种情况,可以从以下几个方面着手: #### 修改请求方法 确认发送给目标站点的HTTP请求方法是否被其允许。某些网站可能仅限于特定类型的请求方法,比如只接受`GET`而不接受`POST`。如果确实如此,则应调整应用程序发出的请求类型以匹配服务器预期。 对于Python脚本中的Scrapy框架而言,在设置代理时可以通过如下方式指定请求头来尝试改变默认行为: ```python import scrapy class MySpider(scrapy.Spider): name = "my_spider" custom_settings = { 'DEFAULT_REQUEST_HEADERS': { 'X-My-Custom-Header': 'value', # 更改请求方法为 GET 或其他受支持的方法 'method': 'GET' } } start_urls = ['http://example.com'] def parse(self, response): pass ``` #### 调整CORS策略 如果是开发基于Node.js的应用程序并遇到了跨域资源共享(CORS)引发的问题,可以参照EggJS的做法通过修改应用配置文件内的`config.cors`属性来放宽对不同HTTP动词的支持范围[^4]。这有助于确保来自浏览器或其他前端环境下的AJAX调用能够成功到达后端服务端点而不会因为方法不兼容遭到拒绝。 #### 检查Web Server配置 针对已经部署至生产环境的应用(如Vue构建后的单页应用托管在IIS上),应当审查Web服务器本身的设定。有时即使代码层面一切正常,但由于缺少必要的处理器模块或是不当的内容协商机制也可能造成此类异常现象。例如,在Internet Information Services (IIS) 中适当添加URL重写规则或扩展映射可以帮助解决问题[^5]。 #### 设置合适的代理参数 最后但同样重要的是要验证用于发起网络请求的那个中间件——即此处提到的代理服务器本身是否有任何限制条件阻止了特定种类的数据交换活动的发生。从给出的信息来看,当前正利用了一个位于AWS EC2实例上的开放代理地址作为中介连接远端资源;然而并没有迹象表明此环节存在问题。不过出于谨慎考虑还是建议再次核对该代理所提供的功能特性说明文档,看是否存在关于哪些操作命令受到管制的规定[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值