免费代理池的实现与优化
时间:2022-07-22
本文章向大家介绍免费代理池的实现与优化,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
之前做的代理池,最近有需要,又用了起来,但是,emmm... 所以重构了下,可用性还是很高的。
临时API:http://94.191.42.63:9090/random
源代码
app: web服务
conf: 全局配置
db: redis数据操作
log: 日志文件目录
manager: 代理调度管理
proxy: 代理抓取与格式化
util: 日志,网页请求,网页处理
run.py: 主函数
├── app
│ ├── __init__.py
│ └── api.py
├── conf
│ ├── __init__.py
│ └── setting.py
├── db
│ ├── __init__.py
│ ├── db.py
│ └── redis_client.py
├── env
├── log
│ └── test.log
├── manager
│ ├── __init__.py
│ ├── check_available_proxy.py
│ ├── check_init_proxy.py
│ ├── proxy_manager.py
│ └── proxy_schedule.py
├── proxy
│ ├── __init__.py
│ ├── check_proxy.py
│ ├── get_free_proxyip.py
│ └── proxy_info.py
├── requirements.txt
├── run.py
└── util
├── __init__.py
├── get_html_tree.py
├── log_handler.py
├── test.py
└── web_requests.py
使用
1、启动任务
2、启动webserver
源代码公众号回复“代理” 获取
优化
1. 延迟计算
你想将一个只读属性定义成一个property,并且只在访问的时候才会计算结果。但是一旦被访问后,你希望结果值被缓存起来,不用每次都去计算。
对应此程序的爬取代理的多个函数
class LazyProperty(object):
"""
LazyProperty https://python3-cookbook.readthedocs.io/zh_CN/latest/c08/p10_using_lazily_computed_properties.html
"""
def __init__(self, func):
self.func = func
def __get__(self, instance, owner):
if instance is None:
return self
else:
value = self.func(instance)
setattr(instance, self.func.__name__, value)
return value
class GetFunctions(object):
def __init__(self):
pass
@LazyProperty
def proxy_get_functions(self):
return ['freeProxy01','freeProxy02']
# 调用
get_function = GetFunctions()
for proxy_get in get_function.proxy_get_functions:
try:
for proxy in getattr(GetFreeProxy, proxy_get.strip())():
...
2. 单例模式
如果在程序运行期间,有很多地方都需要使用配置文件的内容,也就是说,很多地方都需要创建 AppConfig 对象的实例,这就导致系统中存在多个 AppConfig 的实例对象,而这样会严重浪费内存资源 。事实上,类似 AppConfig 这样的类,我们希望在程序运行期间只存在一个实例对象。
对应此程序的数据库的操作
class Singleton(type):
"""
Singleton Metaclass http://funhacks.net/2017/01/17/singleton/
"""
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args)
return cls._instances[cls]
class DBclient(object, metaclass=Singleton):
...
3. Webserver
Gunicorn是一个Python WSGI HTTP Server。gunicorn可以直接使用命令行gunicorn进行调用,也可以在python中构建Application进行使用。
'''https://gist.github.com/KatiRG/2bdf792893bb475ae8debef87002e02c'''
import multiprocessing
import gunicorn.app.base
from gunicorn.six import iteritems
from flask import Flask, render_template, make_response, request, Response #etc
def number_of_workers():
return (multiprocessing.cpu_count() * 2) + 1
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
class StandaloneApplication(gunicorn.app.base.BaseApplication):
def __init__(self, app, options=None):
self.options = options or {}
self.application = app
super(StandaloneApplication, self).__init__()
def load_config(self):
config = dict([(key, value) for key, value in iteritems(self.options)
if key in self.cfg.settings and value is not None])
for key, value in iteritems(config):
self.cfg.set(key.lower(), value)
def load(self):
return self.application
if __name__ == '__main__':
options = {
'bind': '%s:%s' % ('127.0.0.1', '8080'),
'workers': number_of_workers(),
}
StandaloneApplication(app, options).run()
4. 自动返回Json响应
API接口通常返回的是Json, 如果每个返回Json的路由都需要这样处理,那么对接口数量众多的的API来说重复工作就太多了。
class MyResponse(Response):
@classmethod
def force_type(cls, rv, environ=None):
if isinstance(rv, dict):
rv = jsonify(rv)
return super(MyResponse, cls).force_type(rv, environ)
app.response_class = MyResponse
5. 任务调度
APScheduler
是一个python的第三方库,用来提供python的后台程序。包含四个组件,分别是:
- triggers:任务触发器组件,提供任务触发方式
- job stores:任务商店组件,提供任务保存方式
- executors:任务调度组件,提供任务调度方式
- schedulers:任务调度组件,提供任务工作方式
from apscheduler.schedulers.blocking import BlockingScheduler
import time
scheduler = BlockingScheduler()
def job():
print(u"{}: 执行任务".format(time.asctime()))
# 添加任务并设置触发方式为3s一次
scheduler.add_job(job, 'interval', seconds=3)
scheduler.start()
输出:
Sat Nov 2 17:03:33 2019: 执行任务
Sat Nov 2 17:03:36 2019: 执行任务
Sat Nov 2 17:03:39 2019: 执行任务
...
- Quartz.net官方开发指南 第九课: JobStore
- 数据中心运营中出现的错误
- Quartz.net官方开发指南 第十课: 配置、资源使用以及SchedulerFactory
- WCF服务上应用protobuf
- Quartz.net官方开发指南 第十一课: 高级(企业级)属性
- Quartz.net官方开发指南 第十二课:Quartz 的其他特性
- Protocol Buffers的应用
- WordPress 显示数据库查询次数、查询时间及内存占用的代码
- WCF服务在高负载下可能会变慢
- WordPress 后台管理菜单名称重命名的方法
- 从Akismet 黑名单中洗白的方法
- 移除除管理员之外的其他用户的WordPress 更新升级提示
- 为 WordPress 后台管理菜单自定义排序
- WordPress 添加个性化的博客宠物(妹纸篇)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 程序员自我修养之 Git 提交信息和分支创建规范
- Django使用redis作为缓存系统
- 一天一大 leet(两个数组的交集 II)难度:简单-Day20200713
- 2020年研一末找实习总结(面经)
- 一天一大 leet(三角形最小路径和)难度:中等-Day20200714
- 一天一大 leet(判断二分图)难度:中等-Day20200716
- 一天一大 lee(被围绕的区域)难度:中等-Day20200811
- 一天一大 leet(搜索插入位置)难度:简单-Day20200717
- 一天一大 leet(两数之和 II - 输入有序数组)难度:简单-Day20200720
- 一天一大 leet(分割数组的最大值)难度:困难-Day20200725
- 一天一大 leet(矩阵中的最长递增路径)难度:困难-Day20200726
- 一天一大 lee(克隆图)难度:中等-Day20200812
- 一天一大 lee(有效的括号)难度:简单-Day20200814
- 一天一大 leet(判断子序列)难度:简单-Day20200727
- 一天一大 leet(寻宝)难度:困难-Day20200729