jhao104 / proxy_pool

Python ProxyPool for web spider
https://jhao104.github.io/proxy_pool/
MIT License
21.38k stars 5.16k forks source link

【讨论】代理类型及是否可用超时判断代码部分逻辑是否有问题? #756

Open anysoft opened 1 year ago

anysoft commented 1 year ago

以下个人整理,如有错漏欢迎指正,一起讨论让项目发展更好。

@jhao104

几点知识

  1. http代理和https代理的区别: http/https/socks4/socks5/socks5h/vmess/vless等都是代理服务器提供服务时候与客户端通讯的协议,即cleint <--->proxy server 采用哪种协议。

  2. python的request库中proxies对象其中key包括http/https/socks5等

    proxies = {
    "http": "https://192.168.1.1:8888",
    "https": "https://127.0.0.1.1:8888",
    }
    # http 表示针对访问页面为http协议的页面比如:`http://httpbin.org` 使用  `https://192.168.1.1:8888` 这个代理去访问
    # https 表示针对访问https协议的页面比如:`https://baidu.com` 使用 `https://127.0.0.1.1:8888`这个代理去访问
    # 并不是指 http协议的代理服务器只能访问http的页面,https协议的代理服务器只能访问https的页面

代码部分

  1. helper/validator.py
    • status_code 判断并不合理,有些代理ip已经废弃,变成了网站,这个时候http/https 协议是会返回的,且基本是200,所以要么使用有特征值的页面内容做判断,要么head请求判断header内容。同时要考虑被作为检测页面的服务稳定性、可达性(cloudflare/bing/microsoft/google/baidu/qq/aliyun)
    • 针对 httpTimeOutValidator 检测,是判断代理是否http协议,那么proxyies 写法应该是{"http": "http://{proxy}".format(proxy=proxy), "https": "http://{proxy}".format(proxy=proxy)}
    • 同上httpsTimeOutValidator proxyies 写法应该是{"http": "https://{proxy}".format(proxy=proxy), "https": "https://{proxy}".format(proxy=proxy)}
@ProxyValidator.addHttpValidator
def httpTimeOutValidator(proxy):
    """ http检测超时 """

    proxies = {"http": "http://{proxy}".format(proxy=proxy), "https": "https://{proxy}".format(proxy=proxy)}

    try:
        r = head(conf.httpUrl, headers=HEADER, proxies=proxies, timeout=conf.verifyTimeout)
        return True if r.status_code == 200 else False
    except Exception as e:
        return False

@ProxyValidator.addHttpsValidator
def httpsTimeOutValidator(proxy):
    """https检测超时"""

    proxies = {"http": "http://{proxy}".format(proxy=proxy), "https": "https://{proxy}".format(proxy=proxy)}
    try:
        r = head(conf.httpsUrl, headers=HEADER, proxies=proxies, timeout=conf.verifyTimeout, verify=False)
        return True if r.status_code == 200 else False
    except Exception as e:
        return False
  1. check.py 基于1 ,代理类型是http和https应该是分开处理的,一般来讲代理要么是http类型,要么是https类型,不排除有http/https双协议支持的,不过应该几乎不存在。
    http_r = cls.httpValidator(proxy)
    https_r = False if not http_r else cls.httpsValidator(proxy)

我的改法如下:具体可以看我fork的仓库

HTTP_URL = "https://www.baidu.com"
HTTP_URL_HEADER = {"Server": 'bfe'}   # 这里百度自己的server 是bfe具有很强的特征性

HTTPS_URL = "https://www.baidu.com"
HTTPS_URL_HEADER = {"Server": 'bfe'}

@ProxyValidator.addHttpValidator
def httpTimeOutValidator(proxy):
    """ http检测超时 """

    proxies = {"http": "http://{proxy}".format(proxy=proxy), "https": "http://{proxy}".format(proxy=proxy)}
    try:
        r = head(conf.httpsUrl, headers=HEADER, proxies=proxies, timeout=conf.verifyTimeout, verify=False)
        if r.status_code == 200:
            if conf.httpsUrlHeader and len(conf.httpsUrlHeader) > 0:
                for key in conf.httpsUrlHeader.keys():
                    if not r.headers.get(key) or not r.headers.get(key).startswith(conf.httpsUrlHeader.get(key)):
                        return False
                    return True
    except Exception as e:
        return False

@ProxyValidator.addHttpsValidator
def httpsTimeOutValidator(proxy):
    """https检测超时"""

    proxies = {"http": "https://{proxy}".format(proxy=proxy), "https": "https://{proxy}".format(proxy=proxy)}
    try:
        r = head(conf.httpsUrl, headers=HEADER, proxies=proxies, timeout=conf.verifyTimeout, verify=False)
        if r.status_code == 200:
            if conf.httpsUrlHeader and len(conf.httpsUrlHeader) > 0:
                for key in conf.httpsUrlHeader.keys():
                    if not r.headers.get(key) or not r.headers.get(key).startswith(conf.httpsUrlHeader.get(key)):
                        return False
                    return True
    except Exception as e:
        return False

一些想法

  1. 可以加入socks协议代理的检测。
  2. 我觉得检测代理第一步不是判断是哪种类型,而是先通过socks判断服务是否可用(或者第一次http协议判断时候直接根据异常类型给该proxy标记为服务不可达,就不再进行下一步判断,因为没有意义了),可用再判断代理类型,这样避免轮询代理类型/可用性/可达性判断的多倍耗时。毕竟不管是哪种类型的代理,几乎都要建立链接才会有下一步操作(udp协议除外)
YonQua commented 1 year ago

好想法

jhao104 commented 1 year ago

受教,我后面改下

leobigivan commented 3 weeks ago
  • 可以加入socks协议代理的检测。
  • 我觉得检测代理第一步不是判断是哪种类型,而是先通过socks判断服务是否可用(或者第一次http协议判断时候直接根据异常类型给该proxy标记为服务不可达,就不再进行下一步判断,因为没有意义了),可用再判断代理类型,这样避免轮询代理类型/可用性/可达性判断的多倍耗时。毕竟不管是哪种类型的代理,几乎都要建立链接才会有下一步操作(udp协议除外)

你好,请问一下你说的“通过socks判断服务是否可用”是类似于tcp.ping.pe那样,用sock.connect_ex测试ip+port是否可达么? 另外,也请教一下,现在的代理json中没有type属性(http https socks:local<-->proxy),只是测试local via proxy <-->http 和https两个网站,如果false,是local--proxy的问题还是proxy--target的问题似乎没有区分。对于给代理增加类型属性, 请问有没有什么好的方式。对于给代理增加类型属性, 请问有没有什么好的方式。

谢谢

shaobeipan commented 3 weeks ago

@ @leobigivan 希望大佬能增加个type socks