
ProxyPool 代理校验器扩展指南读懂内置三类校验十分钟写出自己的代理验证器【免费下载链接】proxy_poolPython ProxyPool for web spider项目地址: https://gitcode.com/gh_mirrors/pr/proxy_poolProxyPool 项目Python ProxyPool for web spider使用helper/validator.py集中管理代理校验逻辑通过装饰器将校验方法分为预校验、HTTP 可用性校验与 HTTPS 支持校验三类。本文以 validator.md 为主干结合 helper/validator.py、helper/check.py、helper/fetch.py 等源码与 tests/unit/test_validator.py 测试用例完整讲解内置校验的注册机制、执行顺序与判定规则并给出可直接落地的自定义校验器写法。读完本文你将掌握校验器如何被调度、如何被判定、如何自定义的完整链路能够针对自己的业务场景如校验匿名度、验证指定站点可达性、识别透明代理等快速扩展 ProxyPool 的代理校验能力。一、校验器整体设计装饰器注册集中管理代理校验方法全部定义在helper/validator.py中核心是ProxyValidator类继承自withMetaclass(Singleton)即单例模式它维护三个类级列表并对外暴露三个装饰器校验类型装饰器存储列表说明preValidatorProxyValidator.addPreValidatorpre_validator预校验在代理抓取后、可用性校验前调用httpValidatorProxyValidator.addHttpValidatorhttp_validator代理可用性校验通过则认为代理可用httpsValidatorProxyValidator.addHttpsValidatorhttps_validator校验代理是否支持 HTTPS从 helper/validator.py 的源码可以看到装饰器本身只是简单的注册动作class ProxyValidator(withMetaclass(Singleton)): pre_validator [] http_validator [] https_validator [] classmethod def addPreValidator(cls, func): cls.pre_validator.append(func) return func classmethod def addHttpValidator(cls, func): cls.http_validator.append(func) return func classmethod def addHttpsValidator(cls, func): cls.https_validator.append(func) return func三个装饰器做的事情完全对称把被装饰的函数追加到对应列表并原样返回该函数。因此每种校验可以定义任意多个方法只有所有方法都返回True该校验类型才算通过与逻辑任一返回False即失败由于是类属性列表所有装饰在模块加载期执行且单例保证全项目共享同一份注册表。1.1 内置校验实现一览helper/validator.py 内置了四个校验器覆盖格式 → 可用性 → HTTPS 支持三阶段ProxyValidator.addPreValidator def formatValidator(proxy): 检查代理格式 return True if IP_REGEX.fullmatch(proxy) else False ProxyValidator.addHttpValidator def httpTimeOutValidator(proxy): http检测超时 proxies {http: http://{proxy}.format(proxyproxy), https: https://{proxy}.format(proxyproxy)} try: r head(conf.httpUrl, headersHEADER, proxiesproxies, timeoutconf.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(proxyproxy), https: https://{proxy}.format(proxyproxy)} try: r head(conf.httpsUrl, headersHEADER, proxiesproxies, timeoutconf.verifyTimeout, verifyFalse) return True if r.status_code 200 else False except Exception as e: return False ProxyValidator.addHttpValidator def customValidatorExample(proxy): 自定义validator函数校验代理是否可用, 返回True/False return TrueformatValidator使用正则IP_REGEX re.compile(r(.*:.*)?\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{1,5})做fullmatch全匹配(.*:.*)?前缀意味着它支持username:passwordip:port这类带认证信息的代理格式见 helper/validator.py 与文件头部的变更记录。注意正则并不校验 IP/端口数值范围的合法性999.1.1.1:80也会匹配通过这一点在 tests/unit/test_validator.py 的参数化用例中有明确体现。httpTimeOutValidator/httpsTimeOutValidator使用requests.head()发探测请求超时时间与探测 URL 都来自配置详见下文与配置项的联动任何异常超时、连接失败、SSL 错误一律返回False。customValidatorExample是一个恒返回True的占位示例是官方留作扩展参考的模板对应 tests/unit/test_validator.py 中的test_always_returns_true用例实际生产使用时应替换为真实校验逻辑。1.2 与配置项的联动两个 HTTP 探测校验器直接读取ConfigHandler见 handler/configHandler.py对应 setting.py 中的配置配置项环境变量默认值作用HTTP_URLHTTP_URLhttp://httpbin.orgHTTP 可用性校验的探测目标网站HTTPS_URLHTTPS_URLhttps://www.qq.comHTTPS 支持校验的探测目标网站VERIFY_TIMEOUTVERIFY_TIMEOUT10秒探测请求的超时时间同时被httpTimeOutValidator与httpsTimeOutValidator使用配置读取支持环境变量覆盖优先级为os.environsetting.py默认值。另外 setting.py 中的MAX_FAIL_COUNT默认0与POOL_SIZE_MIN默认20虽不直接出现在校验函数中但会在下文校验结果如何流入代理池部分与校验结果协同工作。二、校验执行顺序与完整调用链2.1 执行顺序图校验按预校验 → HTTP 可用性 → HTTPS 支持三级串行执行preValidator校验通过的代理才会进入可用性校验httpValidator校验通过后认为代理可用更新入代理池httpsValidator校验通过后视为代理支持 HTTPS更新代理的https属性为True。2.2 源码级调用链校验的实际执行并不在validator.py内部而是由 helper/check.py 中的DoValidator类驱动。它定义了三个与注册列表一一对应的遍历方法classmethod def httpValidator(cls, proxy): for func in ProxyValidator.http_validator: if not func(proxy.proxy): return False return True classmethod def httpsValidator(cls, proxy): for func in ProxyValidator.https_validator: if not func(proxy.proxy): return False return True classmethod def preValidator(cls, proxy): for func in ProxyValidator.pre_validator: if not func(proxy): return False return True注意一个细节preValidator传入的是整个proxy对象func(proxy)而httpValidator/httpsValidator传入的是proxy.proxy字符串func(proxy.proxy)。也就是说自定义预校验函数接收Proxy对象可以访问source、region等元数据而可用性/HTTPS 校验函数接收ip:port形式的字符串便于直接拼接到proxies参数中。DoValidator.validator()是统一入口串起三个阶段的判定并更新代理状态helper/check.pyclassmethod def validator(cls, proxy, work_type): http_r cls.httpValidator(proxy) https_r False if not http_r else cls.httpsValidator(proxy) proxy.check_count 1 proxy.last_time datetime.now().strftime(%Y-%m-%d %H:%M:%S) proxy.last_status True if http_r else False if http_r: if proxy.fail_count 0: proxy.fail_count - 1 proxy.https True if https_r else False if work_type raw: proxy.region cls.regionGetter(proxy) if cls.conf.proxyRegion else else: proxy.fail_count 1 return proxy这里有三点值得注意短路语义https_r False if not http_r else cls.httpsValidator(proxy)即 HTTP 校验不通过时根本不会执行HTTPS 校验状态维护https属性只有在 HTTP 通过时才更新True/FalseHTTP 失败时保持原值fail_count在失败时 1、成功时 -1不低于 0check_count、last_time、last_status每次校验都会刷新地域属性work_type raw原始代理阶段且开启PROXY_REGION时会调用regionGetter通过https://api.ip.sb/geoip/{ip}查询代理的国家代码结果写入region字段。Proxy对象的字段定义见 helper/proxy.py其中https属性self._https默认False就是 HTTPS 校验结果的落点最终会通过to_dict/to_json序列化并存入代理池。2.3 两个触发场景raw 与 useDoValidator.validator的work_type参数区分两个执行场景见 helper/check.pyraw原始校验代理刚从抓取器产出时执行。入口在 helper/fetch.pyFetcher.run()对每个抓取结果先执行DoValidator.preValidator(_.proxy)格式合法的代理才 yield 给Checker(raw, proxy_queue)_ThreadChecker.__ifRaw中校验通过的代理若不存在则put入池失败则丢弃use使用中校验对池内既有代理的周期性复核。__ifUse中校验失败且fail_count conf.maxFailCount时删除否则保留并重新入池——这正对应 setting.py 的MAX_FAIL_COUNT默认0即一次失败即剔除。调度节奏由 helper/scheduler.py 控制proxy_fetch采集原始校验每 5 分钟执行一次proxy_check池内复核每 2 分钟执行一次且当池内代理数低于POOL_SIZE_MIN时会先触发抓取。校验本身采用 20 个线程并行消费队列Checker中range(20)高吞吐地处理代理队列。三、扩展校验从模板到实战原文档明确指出helper/validator.py 中已内置自定义校验的示例扩展方式为——自定义函数返回True或False用ProxyValidator的装饰器区分校验类型然后把函数定义在helper/validator.py中或任何会被导入的位置即可自动注册无需修改调度器或检查器代码。3.1 示例 1自定义代理可用性校验ProxyValidator.addHttpValidator def customValidatorExample01(proxy): 自定义代理可用性校验函数 proxies {http: http://{proxy}.format(proxyproxy)} try: r requests.get(http://www.baidu.com/, headersHEADER, proxiesproxies, timeout5) return True if r.status_code 200 and len(r.content) 200 else False except Exception as e: return False相比内置的httpTimeOutValidator仅用head()检查状态码 200这个自定义版本改用requests.get()并追加了len(r.content) 200的内容长度条件能过滤掉能连接但响应体异常的代理。HEADER是 helper/validator.py 中定义的全局请求头含 User-Agent、Accept 等自定义函数可直接复用。3.2 示例 2自定义 HTTPS 校验ProxyValidator.addHttpsValidator def customValidatorExample02(proxy): 自定义代理是否支持 HTTPS 校验函数 proxies {https: https://{proxy}.format(proxyproxy)} try: r requests.get(https://www.baidu.com/, headersHEADER, proxiesproxies, timeout5, verifyFalse) return True if r.status_code 200 and len(r.content) 200 else False except Exception as e: return FalseHTTPS 校验与 HTTP 校验的差别集中在三点proxies字典用https协议前缀、探测目标是https://地址、verifyFalse关闭 SSL 证书验证避免因目标站点证书链问题误判代理不可用。原文档也特别提醒运行代理可用性校验时所有被ProxyValidator.addHttpValidator装饰的函数会依次按定义顺序执行只有当所有函数都返回True时才判断代理可用HttpsValidator的运行机制完全相同。3.3 扩展校验的生效与验证自动注册无需配置装饰器在模块导入时即把函数追加到ProxyValidator的注册列表运行python proxyPool.py调度器启动后即对每轮校验生效按定义顺序执行DoValidator直接遍历列表后定义的函数排在后面因此先定义、先执行可通过调整定义顺序控制校验优先级单例共享ProxyValidator是单例Web API、调度器、检查器线程访问的是同一份注册表不存在多实例不一致问题。四、校验器正确性如何被保障测试用例解读tests/unit/test_validator.py 为内置校验器提供了完整的单元测试是理解校验语义的最佳辅助材料IP_REGEX格式匹配TestIPRegex合法的1.2.3.4:8080、带认证的user:pass1.2.3.4:8080均匹配空串、abc、缺端口的1.2.3.4、:8080、端口含字母的1.2.3.4:abc等多段冒号的1.2.3.4:8080:extra均不匹配。测试同时注明999.1.1.1:80这类越界 IP 也会匹配——正则只做格式约束不做数值范围校验formatValidatorTestFormatValidator与正则测试结论一致合法格式返回True非法格式返回FalsehttpTimeOutValidatorTestHttpTimeOutValidator通过mock掉helper.validator.head验证status_code200 → True、status_code502 → False、抛TimeoutError → False三条路径覆盖了成功/失败/异常全部分支httpsTimeOutValidatorTestHttpsTimeOutValidator除上述三条分支外还断言调用时传入了verifyFalse印证 HTTPS 校验关闭证书验证的实现细节customValidatorExampleTestCustomValidatorExample确认占位示例恒返回True即不干预默认校验结果。这些测试可以直接运行验证pytest tests/unit/test_validator.py -v五、实战建议自定义校验器的设计要点结合源码调用链编写高质量自定义校验器时有几个关键取舍用HEAD还是GET内置校验用head()轻量快速需要校验响应体内容如防空白页、防跳转时改用get()并检查len(r.content)代价是带宽和延迟更高。若代理数量大建议保持 HEAD 状态码的轻量策略。控制超时与重试校验器跑在 20 线程的检查池里每个校验器的timeout会直接叠加到整体校验耗时上。内置版本统一用配置项VERIFY_TIMEOUT默认 10 秒自定义版本应设置合理超时并try/except兜底任何异常都必须返回False。注意proxies字典的协议前缀HTTP 校验传http://{proxy}HTTPS 校验传https://{proxy}如需两者同时验证可像内置实现那样同时放入两个键。预校验的特殊入参preValidator系列函数接收的是Proxy对象而非字符串见 helper/check.py可用于基于来源、地域等元数据做前置过滤例如只允许指定来源的代理进入可用性校验。返回值必须严格是布尔语义装饰器注册不强制校验返回类型但DoValidator用if not func(...)判定任何非真值None、0、空串都会被当作校验失败。六、小结ProxyPool 的校验器体系是一个装饰器注册 集中遍历执行的插件式设计ProxyValidator用三个装饰器把校验逻辑挂载到三类列表中DoValidator按预校验 → HTTP → HTTPS的顺序全量遍历并执行与逻辑Checker的 raw/use 双场景把判定结果转化为入池、保留或剔除动作。理解这条链路后扩展一个自定义校验器只需三步写一个返回True/False的函数 → 选择合适的装饰器 → 放入 helper/validator.py 中导入生效无需改动调度、检查或存储的任何代码。相关源码入口helper/validator.py、helper/check.py、helper/fetch.py、tests/unit/test_validator.py、setting.py、handler/configHandler.py。【免费下载链接】proxy_poolPython ProxyPool for web spider项目地址: https://gitcode.com/gh_mirrors/pr/proxy_pool创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考